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
path: root/intern
diff options
context:
space:
mode:
Diffstat (limited to 'intern')
-rw-r--r--intern/CMakeLists.txt6
-rw-r--r--intern/atomic/intern/atomic_ops_unix.h11
-rw-r--r--intern/atomic/intern/atomic_ops_utils.h4
-rw-r--r--intern/audaspace/Python/AUD_PyAPI.cpp2
-rw-r--r--intern/cycles/app/cycles_xml.cpp634
-rw-r--r--intern/cycles/blender/addon/engine.py3
-rw-r--r--intern/cycles/blender/addon/properties.py42
-rw-r--r--intern/cycles/blender/addon/ui.py181
-rw-r--r--intern/cycles/blender/addon/version_update.py1
-rw-r--r--intern/cycles/blender/blender_camera.cpp12
-rw-r--r--intern/cycles/blender/blender_curves.cpp87
-rw-r--r--intern/cycles/blender/blender_mesh.cpp403
-rw-r--r--intern/cycles/blender/blender_object.cpp22
-rw-r--r--intern/cycles/blender/blender_particles.cpp2
-rw-r--r--intern/cycles/blender/blender_shader.cpp261
-rw-r--r--intern/cycles/blender/blender_sync.cpp1
-rw-r--r--intern/cycles/blender/blender_sync.h4
-rw-r--r--intern/cycles/blender/blender_util.h49
-rw-r--r--intern/cycles/bvh/CMakeLists.txt2
-rw-r--r--intern/cycles/bvh/bvh.cpp629
-rw-r--r--intern/cycles/bvh/bvh.h50
-rw-r--r--intern/cycles/bvh/bvh_binning.cpp72
-rw-r--r--intern/cycles/bvh/bvh_binning.h39
-rw-r--r--intern/cycles/bvh/bvh_build.cpp285
-rw-r--r--intern/cycles/bvh/bvh_build.h27
-rw-r--r--intern/cycles/bvh/bvh_node.cpp70
-rw-r--r--intern/cycles/bvh/bvh_node.h47
-rw-r--r--intern/cycles/bvh/bvh_params.h18
-rw-r--r--intern/cycles/bvh/bvh_sort.cpp43
-rw-r--r--intern/cycles/bvh/bvh_sort.h10
-rw-r--r--intern/cycles/bvh/bvh_split.cpp136
-rw-r--r--intern/cycles/bvh/bvh_split.h82
-rw-r--r--intern/cycles/bvh/bvh_unaligned.cpp178
-rw-r--r--intern/cycles/bvh/bvh_unaligned.h81
-rw-r--r--intern/cycles/device/device_cpu.cpp4
-rw-r--r--intern/cycles/device/device_cuda.cpp5
-rw-r--r--intern/cycles/device/device_memory.h5
-rw-r--r--intern/cycles/device/device_multi.cpp4
-rw-r--r--intern/cycles/device/device_network.cpp4
-rw-r--r--intern/cycles/device/device_opencl.cpp164
-rw-r--r--intern/cycles/graph/node.cpp139
-rw-r--r--intern/cycles/graph/node.h12
-rw-r--r--intern/cycles/graph/node_type.cpp40
-rw-r--r--intern/cycles/graph/node_type.h25
-rw-r--r--intern/cycles/graph/node_xml.cpp38
-rw-r--r--intern/cycles/kernel/CMakeLists.txt46
-rw-r--r--intern/cycles/kernel/bvh/bvh.h (renamed from intern/cycles/kernel/geom/geom_bvh.h)85
-rw-r--r--intern/cycles/kernel/bvh/bvh_nodes.h656
-rw-r--r--intern/cycles/kernel/bvh/bvh_shadow_all.h (renamed from intern/cycles/kernel/geom/geom_bvh_shadow.h)250
-rw-r--r--intern/cycles/kernel/bvh/bvh_subsurface.h (renamed from intern/cycles/kernel/geom/geom_bvh_subsurface.h)177
-rw-r--r--intern/cycles/kernel/bvh/bvh_traversal.h (renamed from intern/cycles/kernel/geom/geom_bvh_traversal.h)363
-rw-r--r--intern/cycles/kernel/bvh/bvh_volume.h (renamed from intern/cycles/kernel/geom/geom_bvh_volume.h)221
-rw-r--r--intern/cycles/kernel/bvh/bvh_volume_all.h (renamed from intern/cycles/kernel/geom/geom_bvh_volume_all.h)221
-rw-r--r--intern/cycles/kernel/bvh/qbvh_nodes.h433
-rw-r--r--intern/cycles/kernel/bvh/qbvh_shadow_all.h (renamed from intern/cycles/kernel/geom/geom_qbvh_shadow.h)287
-rw-r--r--intern/cycles/kernel/bvh/qbvh_subsurface.h (renamed from intern/cycles/kernel/geom/geom_qbvh_subsurface.h)194
-rw-r--r--intern/cycles/kernel/bvh/qbvh_traversal.h505
-rw-r--r--intern/cycles/kernel/bvh/qbvh_volume.h (renamed from intern/cycles/kernel/geom/geom_qbvh_volume.h)249
-rw-r--r--intern/cycles/kernel/bvh/qbvh_volume_all.h (renamed from intern/cycles/kernel/geom/geom_qbvh_volume_all.h)249
-rw-r--r--intern/cycles/kernel/closure/alloc.h90
-rw-r--r--intern/cycles/kernel/closure/bsdf.h116
-rw-r--r--intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h54
-rw-r--r--intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h35
-rw-r--r--intern/cycles/kernel/closure/bsdf_diffuse.h33
-rw-r--r--intern/cycles/kernel/closure/bsdf_diffuse_ramp.h35
-rw-r--r--intern/cycles/kernel/closure/bsdf_disney_clearcoat.h34
-rw-r--r--intern/cycles/kernel/closure/bsdf_disney_diffuse.h31
-rw-r--r--intern/cycles/kernel/closure/bsdf_disney_sheen.h37
-rw-r--r--intern/cycles/kernel/closure/bsdf_disney_specular.h79
-rw-r--r--intern/cycles/kernel/closure/bsdf_hair.h71
-rw-r--r--intern/cycles/kernel/closure/bsdf_microfacet.h336
-rw-r--r--intern/cycles/kernel/closure/bsdf_microfacet_multi.h507
-rw-r--r--intern/cycles/kernel/closure/bsdf_microfacet_multi_impl.h226
-rw-r--r--intern/cycles/kernel/closure/bsdf_oren_nayar.h45
-rw-r--r--intern/cycles/kernel/closure/bsdf_phong_ramp.h56
-rw-r--r--intern/cycles/kernel/closure/bsdf_reflection.h7
-rw-r--r--intern/cycles/kernel/closure/bsdf_refraction.h9
-rw-r--r--intern/cycles/kernel/closure/bsdf_toon.h78
-rw-r--r--intern/cycles/kernel/closure/bsdf_util.h6
-rw-r--r--intern/cycles/kernel/closure/bssrdf.h125
-rw-r--r--intern/cycles/kernel/closure/volume.h26
-rw-r--r--intern/cycles/kernel/geom/geom.h23
-rw-r--r--intern/cycles/kernel/geom/geom_attribute.h22
-rw-r--r--intern/cycles/kernel/geom/geom_curve.h4
-rw-r--r--intern/cycles/kernel/geom/geom_motion_triangle.h38
-rw-r--r--intern/cycles/kernel/geom/geom_primitive.h10
-rw-r--r--intern/cycles/kernel/geom/geom_qbvh.h147
-rw-r--r--intern/cycles/kernel/geom/geom_qbvh_traversal.h425
-rw-r--r--intern/cycles/kernel/geom/geom_subd_triangle.h262
-rw-r--r--intern/cycles/kernel/geom/geom_triangle.h61
-rw-r--r--intern/cycles/kernel/geom/geom_triangle_intersect.h72
-rw-r--r--intern/cycles/kernel/kernel_accumulate.h24
-rw-r--r--intern/cycles/kernel/kernel_bake.h35
-rw-r--r--intern/cycles/kernel/kernel_compat_cpu.h13
-rw-r--r--intern/cycles/kernel/kernel_compat_cuda.h1
-rw-r--r--intern/cycles/kernel/kernel_compat_opencl.h1
-rw-r--r--intern/cycles/kernel/kernel_emission.h6
-rw-r--r--intern/cycles/kernel/kernel_globals.h10
-rw-r--r--intern/cycles/kernel/kernel_light.h21
-rw-r--r--intern/cycles/kernel/kernel_path.h57
-rw-r--r--intern/cycles/kernel/kernel_path_branched.h21
-rw-r--r--intern/cycles/kernel/kernel_random.h16
-rw-r--r--intern/cycles/kernel/kernel_shader.h66
-rw-r--r--intern/cycles/kernel/kernel_shadow.h4
-rw-r--r--intern/cycles/kernel/kernel_subsurface.h54
-rw-r--r--intern/cycles/kernel/kernel_textures.h14
-rw-r--r--intern/cycles/kernel/kernel_types.h235
-rw-r--r--intern/cycles/kernel/kernel_volume.h19
-rw-r--r--intern/cycles/kernel/kernels/cpu/kernel.cpp46
-rw-r--r--intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h48
-rw-r--r--intern/cycles/kernel/kernels/cpu/kernel_cpu_impl.h2
-rw-r--r--intern/cycles/kernel/kernels/cuda/kernel.cu6
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel.cl1
-rw-r--r--intern/cycles/kernel/osl/CMakeLists.txt1
-rw-r--r--intern/cycles/kernel/osl/background.cpp20
-rw-r--r--intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp46
-rw-r--r--intern/cycles/kernel/osl/bsdf_phong_ramp.cpp48
-rw-r--r--intern/cycles/kernel/osl/emissive.cpp23
-rw-r--r--intern/cycles/kernel/osl/osl_bssrdf.cpp102
-rw-r--r--intern/cycles/kernel/osl/osl_bssrdf.h61
-rw-r--r--intern/cycles/kernel/osl/osl_closures.cpp303
-rw-r--r--intern/cycles/kernel/osl/osl_closures.h116
-rw-r--r--intern/cycles/kernel/osl/osl_services.cpp12
-rw-r--r--intern/cycles/kernel/osl/osl_shader.cpp281
-rw-r--r--intern/cycles/kernel/osl/osl_shader.h10
-rw-r--r--intern/cycles/kernel/shaders/CMakeLists.txt1
-rw-r--r--intern/cycles/kernel/shaders/node_anisotropic_bsdf.osl6
-rw-r--r--intern/cycles/kernel/shaders/node_brick_texture.osl10
-rw-r--r--intern/cycles/kernel/shaders/node_convert_from_color.osl24
-rw-r--r--intern/cycles/kernel/shaders/node_convert_from_float.osl24
-rw-r--r--intern/cycles/kernel/shaders/node_convert_from_int.osl26
-rw-r--r--intern/cycles/kernel/shaders/node_convert_from_normal.osl24
-rw-r--r--intern/cycles/kernel/shaders/node_convert_from_point.osl24
-rw-r--r--intern/cycles/kernel/shaders/node_convert_from_string.osl14
-rw-r--r--intern/cycles/kernel/shaders/node_convert_from_vector.osl24
-rw-r--r--intern/cycles/kernel/shaders/node_environment_texture.osl4
-rw-r--r--intern/cycles/kernel/shaders/node_glass_bsdf.osl8
-rw-r--r--intern/cycles/kernel/shaders/node_glossy_bsdf.osl6
-rw-r--r--intern/cycles/kernel/shaders/node_gradient_texture.osl18
-rw-r--r--intern/cycles/kernel/shaders/node_hair_bsdf.osl47
-rw-r--r--intern/cycles/kernel/shaders/node_image_texture.osl28
-rw-r--r--intern/cycles/kernel/shaders/node_magic_texture.osl4
-rw-r--r--intern/cycles/kernel/shaders/node_math.osl44
-rw-r--r--intern/cycles/kernel/shaders/node_mix.osl42
-rw-r--r--intern/cycles/kernel/shaders/node_musgrave_texture.osl12
-rw-r--r--intern/cycles/kernel/shaders/node_normal.osl4
-rw-r--r--intern/cycles/kernel/shaders/node_normal_map.osl12
-rw-r--r--intern/cycles/kernel/shaders/node_ramp_util.h89
-rw-r--r--intern/cycles/kernel/shaders/node_refraction_bsdf.osl6
-rw-r--r--intern/cycles/kernel/shaders/node_rgb_curves.osl48
-rw-r--r--intern/cycles/kernel/shaders/node_rgb_ramp.osl23
-rw-r--r--intern/cycles/kernel/shaders/node_rgb_to_bw.osl25
-rw-r--r--intern/cycles/kernel/shaders/node_sky_texture.osl4
-rw-r--r--intern/cycles/kernel/shaders/node_subsurface_scattering.osl6
-rw-r--r--intern/cycles/kernel/shaders/node_tangent.osl12
-rw-r--r--intern/cycles/kernel/shaders/node_toon_bsdf.osl6
-rw-r--r--intern/cycles/kernel/shaders/node_uv_map.osl6
-rw-r--r--intern/cycles/kernel/shaders/node_vector_curves.osl48
-rw-r--r--intern/cycles/kernel/shaders/node_vector_math.osl14
-rw-r--r--intern/cycles/kernel/shaders/node_vector_transform.osl8
-rw-r--r--intern/cycles/kernel/shaders/node_voronoi_texture.osl4
-rw-r--r--intern/cycles/kernel/shaders/node_wave_texture.osl12
-rw-r--r--intern/cycles/kernel/shaders/stdosl.h3
-rw-r--r--intern/cycles/kernel/split/kernel_shader_eval.h2
-rw-r--r--intern/cycles/kernel/split/kernel_split_common.h1
-rw-r--r--intern/cycles/kernel/svm/svm.h5
-rw-r--r--intern/cycles/kernel/svm/svm_attribute.h4
-rw-r--r--intern/cycles/kernel/svm/svm_brightness.h7
-rw-r--r--intern/cycles/kernel/svm/svm_closure.h808
-rw-r--r--intern/cycles/kernel/svm/svm_color_util.h306
-rw-r--r--intern/cycles/kernel/svm/svm_image.h52
-rw-r--r--intern/cycles/kernel/svm/svm_mix.h274
-rw-r--r--intern/cycles/kernel/svm/svm_ramp.h41
-rw-r--r--intern/cycles/kernel/svm/svm_ramp_util.h97
-rw-r--r--intern/cycles/kernel/svm/svm_tex_coord.h10
-rw-r--r--intern/cycles/kernel/svm/svm_types.h16
-rw-r--r--intern/cycles/render/CMakeLists.txt3
-rw-r--r--intern/cycles/render/attribute.cpp102
-rw-r--r--intern/cycles/render/attribute.h20
-rw-r--r--intern/cycles/render/background.cpp9
-rw-r--r--intern/cycles/render/background.h1
-rw-r--r--intern/cycles/render/bake.cpp2
-rw-r--r--intern/cycles/render/camera.cpp184
-rw-r--r--intern/cycles/render/camera.h8
-rw-r--r--intern/cycles/render/constant_fold.cpp354
-rw-r--r--intern/cycles/render/constant_fold.h70
-rw-r--r--intern/cycles/render/curves.h34
-rw-r--r--intern/cycles/render/film.cpp2
-rw-r--r--intern/cycles/render/graph.cpp330
-rw-r--r--intern/cycles/render/graph.h124
-rw-r--r--intern/cycles/render/image.cpp358
-rw-r--r--intern/cycles/render/image.h12
-rw-r--r--intern/cycles/render/integrator.cpp7
-rw-r--r--intern/cycles/render/integrator.h1
-rw-r--r--intern/cycles/render/light.cpp195
-rw-r--r--intern/cycles/render/light.h4
-rw-r--r--intern/cycles/render/mesh.cpp802
-rw-r--r--intern/cycles/render/mesh.h158
-rw-r--r--intern/cycles/render/mesh_displace.cpp9
-rw-r--r--intern/cycles/render/mesh_subdivision.cpp224
-rw-r--r--intern/cycles/render/nodes.cpp3210
-rw-r--r--intern/cycles/render/nodes.h613
-rw-r--r--intern/cycles/render/object.cpp56
-rw-r--r--intern/cycles/render/object.h11
-rw-r--r--intern/cycles/render/osl.cpp356
-rw-r--r--intern/cycles/render/osl.h9
-rw-r--r--intern/cycles/render/particles.cpp11
-rw-r--r--intern/cycles/render/particles.h2
-rw-r--r--intern/cycles/render/scene.cpp17
-rw-r--r--intern/cycles/render/scene.h24
-rw-r--r--intern/cycles/render/session.cpp2
-rw-r--r--intern/cycles/render/shader.cpp20
-rw-r--r--intern/cycles/render/svm.cpp65
-rw-r--r--intern/cycles/render/svm.h6
-rw-r--r--intern/cycles/subd/CMakeLists.txt2
-rw-r--r--intern/cycles/subd/subd_dice.cpp185
-rw-r--r--intern/cycles/subd/subd_dice.h48
-rw-r--r--intern/cycles/subd/subd_mesh.cpp419
-rw-r--r--intern/cycles/subd/subd_mesh.h78
-rw-r--r--intern/cycles/subd/subd_patch.cpp26
-rw-r--r--intern/cycles/subd/subd_patch.h18
-rw-r--r--intern/cycles/subd/subd_split.cpp199
-rw-r--r--intern/cycles/subd/subd_split.h8
-rw-r--r--intern/cycles/test/CMakeLists.txt29
-rw-r--r--intern/cycles/test/render_graph_finalize_test.cpp149
-rw-r--r--intern/cycles/util/CMakeLists.txt2
-rw-r--r--intern/cycles/util/util_boundbox.h2
-rw-r--r--intern/cycles/util/util_half.h21
-rw-r--r--intern/cycles/util/util_math.h70
-rw-r--r--intern/cycles/util/util_math_fast.h3
-rw-r--r--intern/cycles/util/util_path.cpp18
-rw-r--r--intern/cycles/util/util_string.cpp53
-rw-r--r--intern/cycles/util/util_string.h10
-rw-r--r--intern/cycles/util/util_system.cpp52
-rw-r--r--intern/cycles/util/util_system.h8
-rw-r--r--intern/cycles/util/util_task.cpp23
-rw-r--r--intern/cycles/util/util_texture.h82
-rw-r--r--intern/cycles/util/util_thread.cpp66
-rw-r--r--intern/cycles/util/util_thread.h36
-rw-r--r--intern/cycles/util/util_transform.h13
-rw-r--r--intern/cycles/util/util_types.h1
-rw-r--r--intern/cycles/util/util_windows.cpp88
-rw-r--r--intern/cycles/util/util_windows.h19
-rw-r--r--intern/decklink/CMakeLists.txt58
-rw-r--r--intern/decklink/DeckLinkAPI.cpp50
-rw-r--r--intern/decklink/DeckLinkAPI.h56
-rw-r--r--intern/decklink/linux/DeckLinkAPI.h767
-rw-r--r--intern/decklink/linux/DeckLinkAPIConfiguration.h192
-rw-r--r--intern/decklink/linux/DeckLinkAPIDeckControl.h215
-rw-r--r--intern/decklink/linux/DeckLinkAPIDiscovery.h71
-rw-r--r--intern/decklink/linux/DeckLinkAPIDispatch.cpp148
-rw-r--r--intern/decklink/linux/DeckLinkAPIModes.h191
-rw-r--r--intern/decklink/linux/DeckLinkAPITypes.h110
-rw-r--r--intern/decklink/linux/DeckLinkAPIVersion.h37
-rw-r--r--intern/decklink/linux/LinuxCOM.h100
-rw-r--r--intern/decklink/win/DeckLinkAPI_h.h13323
-rw-r--r--intern/decklink/win/DeckLinkAPI_i.c343
-rw-r--r--intern/ghost/CMakeLists.txt4
-rw-r--r--intern/ghost/GHOST_ISystem.h2
-rw-r--r--intern/ghost/GHOST_Types.h5
-rw-r--r--intern/ghost/intern/GHOST_ContextGLX.cpp51
-rw-r--r--intern/ghost/intern/GHOST_ContextGLX.h3
-rw-r--r--intern/ghost/intern/GHOST_ContextWGL.cpp74
-rw-r--r--intern/ghost/intern/GHOST_ContextWGL.h4
-rw-r--r--intern/ghost/intern/GHOST_DropTargetWin32.cpp12
-rw-r--r--intern/ghost/intern/GHOST_EventManager.cpp12
-rw-r--r--intern/ghost/intern/GHOST_ImeWin32.cpp2
-rw-r--r--intern/ghost/intern/GHOST_NDOFManager.cpp9
-rw-r--r--intern/ghost/intern/GHOST_NDOFManager.h1
-rw-r--r--intern/ghost/intern/GHOST_System.cpp8
-rw-r--r--intern/ghost/intern/GHOST_System.h6
-rw-r--r--intern/ghost/intern/GHOST_SystemCocoa.mm20
-rw-r--r--intern/ghost/intern/GHOST_SystemPathsWin32.cpp6
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.cpp10
-rw-r--r--intern/ghost/intern/GHOST_SystemX11.cpp142
-rw-r--r--intern/ghost/intern/GHOST_SystemX11.h20
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.cpp82
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.h3
-rw-r--r--intern/ghost/intern/GHOST_WindowX11.cpp240
-rw-r--r--intern/ghost/intern/GHOST_WindowX11.h11
-rw-r--r--intern/gpudirect/CMakeLists.txt41
-rw-r--r--intern/gpudirect/dvpapi.cpp147
-rw-r--r--intern/gpudirect/dvpapi.h667
-rw-r--r--intern/guardedalloc/test/simpletest/memtest.c1
-rw-r--r--intern/libmv/intern/autotrack.cc8
-rw-r--r--intern/libmv/libmv/multiview/projection.h2
-rw-r--r--intern/libmv/libmv/numeric/numeric.cc2
-rw-r--r--intern/libmv/libmv/numeric/numeric.h2
-rw-r--r--intern/moto/include/MT_Matrix4x4.h10
-rw-r--r--intern/opencolorio/gpu_shader_display_transform.glsl2
-rw-r--r--intern/opensubdiv/CMakeLists.txt2
-rw-r--r--intern/opensubdiv/gpu_shader_opensubd_display.glsl16
-rw-r--r--intern/opensubdiv/opensubdiv_capi.cc89
-rw-r--r--intern/opensubdiv/opensubdiv_capi.h11
-rw-r--r--intern/opensubdiv/opensubdiv_converter.cc112
-rw-r--r--intern/opensubdiv/opensubdiv_converter_capi.h16
-rw-r--r--intern/opensubdiv/opensubdiv_gpu_capi.cc414
-rw-r--r--intern/opensubdiv/opensubdiv_topology_refiner.h41
298 files changed, 32402 insertions, 9748 deletions
diff --git a/intern/CMakeLists.txt b/intern/CMakeLists.txt
index 43e5b6bff3e..9a5476772ab 100644
--- a/intern/CMakeLists.txt
+++ b/intern/CMakeLists.txt
@@ -34,6 +34,10 @@ add_subdirectory(mikktspace)
add_subdirectory(glew-mx)
add_subdirectory(eigen)
+if (WITH_GAMEENGINE_DECKLINK)
+ add_subdirectory(decklink)
+endif()
+
if(WITH_AUDASPACE)
add_subdirectory(audaspace)
endif()
@@ -79,8 +83,10 @@ if(WITH_OPENSUBDIV)
endif()
# only windows needs utf16 converter
+# gpudirect is a runtime interface to the nVidia's DVP driver, only for windows
if(WIN32)
add_subdirectory(utfconv)
+ add_subdirectory(gpudirect)
endif()
if(WITH_OPENVDB)
diff --git a/intern/atomic/intern/atomic_ops_unix.h b/intern/atomic/intern/atomic_ops_unix.h
index bf54750ea0d..55c00024244 100644
--- a/intern/atomic/intern/atomic_ops_unix.h
+++ b/intern/atomic/intern/atomic_ops_unix.h
@@ -129,23 +129,24 @@ ATOMIC_INLINE uint32_t atomic_cas_uint32(uint32_t *v, uint32_t old, uint32_t _ne
#elif (defined(__i386__) || defined(__amd64__) || defined(__x86_64__))
ATOMIC_INLINE uint32_t atomic_add_uint32(uint32_t *p, uint32_t x)
{
+ uint32_t ret = x;
asm volatile (
"lock; xaddl %0, %1;"
- : "+r" (x), "=m" (*p) /* Outputs. */
+ : "+r" (ret), "=m" (*p) /* Outputs. */
: "m" (*p) /* Inputs. */
);
- return x;
+ return ret+x;
}
ATOMIC_INLINE uint32_t atomic_sub_uint32(uint32_t *p, uint32_t x)
{
- x = (uint32_t)(-(int32_t)x);
+ ret = (uint32_t)(-(int32_t)x);
asm volatile (
"lock; xaddl %0, %1;"
- : "+r" (x), "=m" (*p) /* Outputs. */
+ : "+r" (ret), "=m" (*p) /* Outputs. */
: "m" (*p) /* Inputs. */
);
- return x;
+ return ret-x;
}
ATOMIC_INLINE uint32_t atomic_cas_uint32(uint32_t *v, uint32_t old, uint32_t _new)
diff --git a/intern/atomic/intern/atomic_ops_utils.h b/intern/atomic/intern/atomic_ops_utils.h
index fcbb2346243..bfec9918c16 100644
--- a/intern/atomic/intern/atomic_ops_utils.h
+++ b/intern/atomic/intern/atomic_ops_utils.h
@@ -81,7 +81,9 @@
# endif
#endif
-#ifdef UINTPTR_MAX
+#if defined(__SIZEOF_POINTER__)
+# define LG_SIZEOF_PTR __SIZEOF_POINTER__
+#elif defined(UINTPTR_MAX)
# if (UINTPTR_MAX == 0xFFFFFFFF)
# define LG_SIZEOF_PTR 4
# elif (UINTPTR_MAX == 0xFFFFFFFFFFFFFFFF)
diff --git a/intern/audaspace/Python/AUD_PyAPI.cpp b/intern/audaspace/Python/AUD_PyAPI.cpp
index 300fd55e23b..de5c0a2f463 100644
--- a/intern/audaspace/Python/AUD_PyAPI.cpp
+++ b/intern/audaspace/Python/AUD_PyAPI.cpp
@@ -861,7 +861,7 @@ Factory_filter(Factory* self, PyObject *args)
py_a_len= py_a ? PySequence_Size(py_a) : 0;
py_b_len= PySequence_Size(py_b);
- if(!py_b_len || ((py_a != NULL) && !py_b_len))
+ if(!py_b_len || ((py_a != NULL) && !py_a_len))
{
PyErr_SetString(PyExc_ValueError, "The sequence has to contain at least one value!");
return NULL;
diff --git a/intern/cycles/app/cycles_xml.cpp b/intern/cycles/app/cycles_xml.cpp
index 1165db795de..3d3aca33881 100644
--- a/intern/cycles/app/cycles_xml.cpp
+++ b/intern/cycles/app/cycles_xml.cpp
@@ -31,10 +31,10 @@
#include "mesh.h"
#include "nodes.h"
#include "object.h"
+#include "osl.h"
#include "shader.h"
#include "scene.h"
-#include "subd_mesh.h"
#include "subd_patch.h"
#include "subd_split.h"
@@ -72,18 +72,6 @@ struct XMLReadState : public XMLReader {
/* Attribute Reading */
-static bool xml_read_bool(bool *value, pugi::xml_node node, const char *name)
-{
- pugi::xml_attribute attr = node.attribute(name);
-
- if(attr) {
- *value = (string_iequals(attr.value(), "true")) || (atoi(attr.value()) != 0);
- return true;
- }
-
- return false;
-}
-
static bool xml_read_int(int *value, pugi::xml_node node, const char *name)
{
pugi::xml_attribute attr = node.attribute(name);
@@ -192,18 +180,6 @@ static bool xml_read_string(string *str, pugi::xml_node node, const char *name)
return false;
}
-static bool xml_read_ustring(ustring *str, pugi::xml_node node, const char *name)
-{
- pugi::xml_attribute attr = node.attribute(name);
-
- if(attr) {
- *str = ustring(attr.value());
- return true;
- }
-
- return false;
-}
-
static bool xml_equal_string(pugi::xml_node node, const char *name, const char *value)
{
pugi::xml_attribute attr = node.attribute(name);
@@ -214,113 +190,16 @@ static bool xml_equal_string(pugi::xml_node node, const char *name, const char *
return false;
}
-static bool xml_read_enum(ustring *str, ShaderEnum& enm, pugi::xml_node node, const char *name)
-{
- pugi::xml_attribute attr = node.attribute(name);
-
- if(attr) {
- ustring ustr(attr.value());
-
- if(enm.exists(ustr)) {
- *str = ustr;
- return true;
- }
- else
- fprintf(stderr, "Unknown value \"%s\" for attribute \"%s\".\n", ustr.c_str(), name);
- }
-
- return false;
-}
-
-static bool xml_read_enum_value(int *value, ShaderEnum& enm, pugi::xml_node node, const char *name)
-{
- pugi::xml_attribute attr = node.attribute(name);
-
- if(attr) {
- ustring ustr(attr.value());
-
- if(enm.exists(ustr)) {
- *value = enm[ustr];
- return true;
- }
- else
- fprintf(stderr, "Unknown value \"%s\" for attribute \"%s\".\n", ustr.c_str(), name);
- }
-
- return false;
-}
-
-static ShaderSocketType xml_read_socket_type(pugi::xml_node node, const char *name)
-{
- pugi::xml_attribute attr = node.attribute(name);
-
- if(attr) {
- string value = attr.value();
- if(string_iequals(value, "float"))
- return SHADER_SOCKET_FLOAT;
- else if(string_iequals(value, "int"))
- return SHADER_SOCKET_INT;
- else if(string_iequals(value, "color"))
- return SHADER_SOCKET_COLOR;
- else if(string_iequals(value, "vector"))
- return SHADER_SOCKET_VECTOR;
- else if(string_iequals(value, "point"))
- return SHADER_SOCKET_POINT;
- else if(string_iequals(value, "normal"))
- return SHADER_SOCKET_NORMAL;
- else if(string_iequals(value, "closure color"))
- return SHADER_SOCKET_CLOSURE;
- else if(string_iequals(value, "string"))
- return SHADER_SOCKET_STRING;
- else
- fprintf(stderr, "Unknown shader socket type \"%s\" for attribute \"%s\".\n", value.c_str(), name);
- }
-
- return SHADER_SOCKET_UNDEFINED;
-}
-
/* Camera */
-static void xml_read_camera(const XMLReadState& state, pugi::xml_node node)
+static void xml_read_camera(XMLReadState& state, pugi::xml_node node)
{
Camera *cam = state.scene->camera;
xml_read_int(&cam->width, node, "width");
xml_read_int(&cam->height, node, "height");
- if(xml_read_float(&cam->fov, node, "fov"))
- cam->fov = DEG2RADF(cam->fov);
-
- xml_read_float(&cam->nearclip, node, "nearclip");
- xml_read_float(&cam->farclip, node, "farclip");
- xml_read_float(&cam->aperturesize, node, "aperturesize"); // 0.5*focallength/fstop
- xml_read_float(&cam->focaldistance, node, "focaldistance");
- xml_read_float(&cam->shuttertime, node, "shuttertime");
- xml_read_float(&cam->aperture_ratio, node, "aperture_ratio");
-
- if(xml_equal_string(node, "type", "orthographic"))
- cam->type = CAMERA_ORTHOGRAPHIC;
- else if(xml_equal_string(node, "type", "perspective"))
- cam->type = CAMERA_PERSPECTIVE;
- else if(xml_equal_string(node, "type", "panorama"))
- cam->type = CAMERA_PANORAMA;
-
- if(xml_equal_string(node, "panorama_type", "equirectangular"))
- cam->panorama_type = PANORAMA_EQUIRECTANGULAR;
- else if(xml_equal_string(node, "panorama_type", "fisheye_equidistant"))
- cam->panorama_type = PANORAMA_FISHEYE_EQUIDISTANT;
- else if(xml_equal_string(node, "panorama_type", "fisheye_equisolid"))
- cam->panorama_type = PANORAMA_FISHEYE_EQUISOLID;
-
- xml_read_float(&cam->fisheye_fov, node, "fisheye_fov");
- xml_read_float(&cam->fisheye_lens, node, "fisheye_lens");
-
- xml_read_bool(&cam->use_spherical_stereo, node, "use_spherical_stereo");
- xml_read_float(&cam->interocular_distance, node, "interocular_distance");
- xml_read_float(&cam->convergence_distance, node, "convergence_distance");
-
- xml_read_float(&cam->sensorwidth, node, "sensorwidth");
- xml_read_float(&cam->sensorheight, node, "sensorheight");
+ xml_read_node(state, cam, node);
cam->matrix = state.tfm;
@@ -347,378 +226,14 @@ static void xml_read_shader_graph(XMLReadState& state, Shader *shader, pugi::xml
ShaderGraph *graph = new ShaderGraph();
- map<string, ShaderNode*> nodemap;
-
- nodemap["output"] = graph->output();
+ /* 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(pugi::xml_node node = graph_node.first_child(); node; node = node.next_sibling()) {
- ShaderNode *snode = NULL;
-
- /* ToDo: Add missing nodes
- * RGBCurvesNode, VectorCurvesNode, RGBRampNode and ConvertNode (RGB -> BW).
- */
-
- if(string_iequals(node.name(), "image_texture")) {
- ImageTextureNode *img = new ImageTextureNode();
-
- xml_read_string(&img->filename, node, "src");
- img->filename = path_join(state.base, img->filename);
-
- xml_read_enum(&img->color_space, ImageTextureNode::color_space_enum, node, "color_space");
- xml_read_enum(&img->projection, ImageTextureNode::projection_enum, node, "projection");
- xml_read_float(&img->projection_blend, node, "projection_blend");
-
- /* ToDo: Interpolation */
-
- snode = img;
- }
- else if(string_iequals(node.name(), "environment_texture")) {
- EnvironmentTextureNode *env = new EnvironmentTextureNode();
-
- xml_read_string(&env->filename, node, "src");
- env->filename = path_join(state.base, env->filename);
-
- xml_read_enum(&env->color_space, EnvironmentTextureNode::color_space_enum, node, "color_space");
- xml_read_enum(&env->projection, EnvironmentTextureNode::projection_enum, node, "projection");
-
- snode = env;
- }
- else if(string_iequals(node.name(), "osl_shader")) {
- OSLScriptNode *osl = new OSLScriptNode();
-
- /* Source */
- xml_read_string(&osl->filepath, node, "src");
- if(path_is_relative(osl->filepath)) {
- osl->filepath = path_join(state.base, osl->filepath);
- }
-
- /* Generate inputs/outputs from node sockets
- *
- * Note: ShaderInput/ShaderOutput store shallow string copies only!
- * So we register them as ustring to ensure the pointer stays valid. */
- /* read input values */
- for(pugi::xml_node param = node.first_child(); param; param = param.next_sibling()) {
- if(string_iequals(param.name(), "input")) {
- string name;
- if(!xml_read_string(&name, param, "name"))
- continue;
-
- ShaderSocketType type = xml_read_socket_type(param, "type");
- if(type == SHADER_SOCKET_UNDEFINED)
- continue;
-
- osl->add_input(ustring(name).c_str(), type);
- }
- else if(string_iequals(param.name(), "output")) {
- string name;
- if(!xml_read_string(&name, param, "name"))
- continue;
-
- ShaderSocketType type = xml_read_socket_type(param, "type");
- if(type == SHADER_SOCKET_UNDEFINED)
- continue;
-
- osl->add_output(ustring(name).c_str(), type);
- }
- }
-
- snode = osl;
- }
- else if(string_iequals(node.name(), "sky_texture")) {
- SkyTextureNode *sky = new SkyTextureNode();
-
- xml_read_enum(&sky->type, SkyTextureNode::type_enum, node, "type");
- xml_read_float3(&sky->sun_direction, node, "sun_direction");
- xml_read_float(&sky->turbidity, node, "turbidity");
- xml_read_float(&sky->ground_albedo, node, "ground_albedo");
-
- snode = sky;
- }
- else if(string_iequals(node.name(), "noise_texture")) {
- snode = new NoiseTextureNode();
- }
- else if(string_iequals(node.name(), "checker_texture")) {
- snode = new CheckerTextureNode();
- }
- else if(string_iequals(node.name(), "brick_texture")) {
- BrickTextureNode *brick = new BrickTextureNode();
-
- xml_read_float(&brick->offset, node, "offset");
- xml_read_int(&brick->offset_frequency, node, "offset_frequency");
- xml_read_float(&brick->squash, node, "squash");
- xml_read_int(&brick->squash_frequency, node, "squash_frequency");
-
- snode = brick;
- }
- else if(string_iequals(node.name(), "gradient_texture")) {
- GradientTextureNode *blend = new GradientTextureNode();
- xml_read_enum(&blend->type, GradientTextureNode::type_enum, node, "type");
- snode = blend;
- }
- else if(string_iequals(node.name(), "voronoi_texture")) {
- VoronoiTextureNode *voronoi = new VoronoiTextureNode();
- xml_read_enum(&voronoi->coloring, VoronoiTextureNode::coloring_enum, node, "coloring");
- snode = voronoi;
- }
- else if(string_iequals(node.name(), "musgrave_texture")) {
- MusgraveTextureNode *musgrave = new MusgraveTextureNode();
- xml_read_enum(&musgrave->type, MusgraveTextureNode::type_enum, node, "type");
- snode = musgrave;
- }
- else if(string_iequals(node.name(), "magic_texture")) {
- MagicTextureNode *magic = new MagicTextureNode();
- xml_read_int(&magic->depth, node, "depth");
- snode = magic;
- }
- else if(string_iequals(node.name(), "wave_texture")) {
- WaveTextureNode *wave = new WaveTextureNode();
- xml_read_enum(&wave->type, WaveTextureNode::type_enum, node, "type");
- xml_read_enum(&wave->profile, WaveTextureNode::profile_enum, node, "profile");
- snode = wave;
- }
- else if(string_iequals(node.name(), "normal")) {
- NormalNode *normal = new NormalNode();
- xml_read_float3(&normal->direction, node, "direction");
- snode = normal;
- }
- else if(string_iequals(node.name(), "bump")) {
- BumpNode *bump = new BumpNode();
- xml_read_bool(&bump->invert, node, "invert");
- snode = bump;
- }
- else if(string_iequals(node.name(), "mapping")) {
- MappingNode *map = new MappingNode();
-
- TextureMapping *texmap = &map->tex_mapping;
- xml_read_enum_value((int*) &texmap->type, TextureMapping::type_enum, node, "type");
- xml_read_enum_value((int*) &texmap->projection, TextureMapping::projection_enum, node, "projection");
- xml_read_enum_value((int*) &texmap->x_mapping, TextureMapping::mapping_enum, node, "x_mapping");
- xml_read_enum_value((int*) &texmap->y_mapping, TextureMapping::mapping_enum, node, "y_mapping");
- xml_read_enum_value((int*) &texmap->z_mapping, TextureMapping::mapping_enum, node, "z_mapping");
- xml_read_bool(&texmap->use_minmax, node, "use_minmax");
- if(texmap->use_minmax) {
- xml_read_float3(&texmap->min, node, "min");
- xml_read_float3(&texmap->max, node, "max");
- }
- xml_read_float3(&texmap->translation, node, "translation");
- xml_read_float3(&texmap->rotation, node, "rotation");
- xml_read_float3(&texmap->scale, node, "scale");
+ ustring node_name(node.name());
- snode = map;
- }
- else if(string_iequals(node.name(), "anisotropic_bsdf")) {
- AnisotropicBsdfNode *aniso = new AnisotropicBsdfNode();
- xml_read_enum(&aniso->distribution, AnisotropicBsdfNode::distribution_enum, node, "distribution");
- snode = aniso;
- }
- else if(string_iequals(node.name(), "diffuse_bsdf")) {
- snode = new DiffuseBsdfNode();
- }
- /*else if(string_iequals(node.name(), "disney_bsdf")) {
- snode = new DisneyBsdfNode();
- }*/
- else if(string_iequals(node.name(), "translucent_bsdf")) {
- snode = new TranslucentBsdfNode();
- }
- else if(string_iequals(node.name(), "transparent_bsdf")) {
- snode = new TransparentBsdfNode();
- }
- else if(string_iequals(node.name(), "velvet_bsdf")) {
- snode = new VelvetBsdfNode();
- }
- else if(string_iequals(node.name(), "toon_bsdf")) {
- ToonBsdfNode *toon = new ToonBsdfNode();
- xml_read_enum(&toon->component, ToonBsdfNode::component_enum, node, "component");
- snode = toon;
- }
- else if(string_iequals(node.name(), "glossy_bsdf")) {
- GlossyBsdfNode *glossy = new GlossyBsdfNode();
- xml_read_enum(&glossy->distribution, GlossyBsdfNode::distribution_enum, node, "distribution");
- snode = glossy;
- }
- else if(string_iequals(node.name(), "glass_bsdf")) {
- GlassBsdfNode *diel = new GlassBsdfNode();
- xml_read_enum(&diel->distribution, GlassBsdfNode::distribution_enum, node, "distribution");
- snode = diel;
- }
- else if(string_iequals(node.name(), "refraction_bsdf")) {
- RefractionBsdfNode *diel = new RefractionBsdfNode();
- xml_read_enum(&diel->distribution, RefractionBsdfNode::distribution_enum, node, "distribution");
- snode = diel;
- }
- else if(string_iequals(node.name(), "hair_bsdf")) {
- HairBsdfNode *hair = new HairBsdfNode();
- xml_read_enum(&hair->component, HairBsdfNode::component_enum, node, "component");
- snode = hair;
- }
- else if(string_iequals(node.name(), "emission")) {
- snode = new EmissionNode();
- }
- else if(string_iequals(node.name(), "ambient_occlusion")) {
- snode = new AmbientOcclusionNode();
- }
- else if(string_iequals(node.name(), "background")) {
- snode = new BackgroundNode();
- }
- else if(string_iequals(node.name(), "holdout")) {
- snode = new HoldoutNode();
- }
- else if(string_iequals(node.name(), "absorption_volume")) {
- snode = new AbsorptionVolumeNode();
- }
- else if(string_iequals(node.name(), "scatter_volume")) {
- snode = new ScatterVolumeNode();
- }
- else if(string_iequals(node.name(), "subsurface_scattering")) {
- SubsurfaceScatteringNode *sss = new SubsurfaceScatteringNode();
-
- string falloff;
- xml_read_string(&falloff, node, "falloff");
- if(falloff == "cubic")
- sss->closure = CLOSURE_BSSRDF_CUBIC_ID;
- else if(falloff == "gaussian")
- sss->closure = CLOSURE_BSSRDF_GAUSSIAN_ID;
- else /*if(falloff == "burley")*/
- sss->closure = CLOSURE_BSSRDF_BURLEY_ID;
-
- snode = sss;
- }
- else if(string_iequals(node.name(), "geometry")) {
- snode = new GeometryNode();
- }
- else if(string_iequals(node.name(), "texture_coordinate")) {
- snode = new TextureCoordinateNode();
- }
- else if(string_iequals(node.name(), "light_path")) {
- snode = new LightPathNode();
- }
- else if(string_iequals(node.name(), "light_falloff")) {
- snode = new LightFalloffNode();
- }
- else if(string_iequals(node.name(), "object_info")) {
- snode = new ObjectInfoNode();
- }
- else if(string_iequals(node.name(), "particle_info")) {
- snode = new ParticleInfoNode();
- }
- else if(string_iequals(node.name(), "hair_info")) {
- snode = new HairInfoNode();
- }
- else if(string_iequals(node.name(), "value")) {
- ValueNode *value = new ValueNode();
- xml_read_float(&value->value, node, "value");
- snode = value;
- }
- else if(string_iequals(node.name(), "color")) {
- ColorNode *color = new ColorNode();
- xml_read_float3(&color->value, node, "value");
- snode = color;
- }
- else if(string_iequals(node.name(), "mix_closure")) {
- snode = new MixClosureNode();
- }
- else if(string_iequals(node.name(), "add_closure")) {
- snode = new AddClosureNode();
- }
- else if(string_iequals(node.name(), "invert")) {
- snode = new InvertNode();
- }
- else if(string_iequals(node.name(), "mix")) {
- /* ToDo: Tag Mix case for optimization */
- MixNode *mix = new MixNode();
- xml_read_enum(&mix->type, MixNode::type_enum, node, "type");
- xml_read_bool(&mix->use_clamp, node, "use_clamp");
- snode = mix;
- }
- else if(string_iequals(node.name(), "gamma")) {
- snode = new GammaNode();
- }
- else if(string_iequals(node.name(), "brightness")) {
- snode = new BrightContrastNode();
- }
- else if(string_iequals(node.name(), "combine_rgb")) {
- snode = new CombineRGBNode();
- }
- else if(string_iequals(node.name(), "separate_rgb")) {
- snode = new SeparateRGBNode();
- }
- else if(string_iequals(node.name(), "combine_hsv")) {
- snode = new CombineHSVNode();
- }
- else if(string_iequals(node.name(), "separate_hsv")) {
- snode = new SeparateHSVNode();
- }
- else if(string_iequals(node.name(), "combine_xyz")) {
- snode = new CombineXYZNode();
- }
- else if(string_iequals(node.name(), "separate_xyz")) {
- snode = new SeparateXYZNode();
- }
- else if(string_iequals(node.name(), "hsv")) {
- snode = new HSVNode();
- }
- else if(string_iequals(node.name(), "wavelength")) {
- snode = new WavelengthNode();
- }
- else if(string_iequals(node.name(), "blackbody")) {
- snode = new BlackbodyNode();
- }
- else if(string_iequals(node.name(), "attribute")) {
- AttributeNode *attr = new AttributeNode();
- xml_read_ustring(&attr->attribute, node, "attribute");
- snode = attr;
- }
- else if(string_iequals(node.name(), "uv_map")) {
- UVMapNode *uvm = new UVMapNode();
- xml_read_ustring(&uvm->attribute, node, "uv_map");
- snode = uvm;
- }
- else if(string_iequals(node.name(), "camera")) {
- snode = new CameraNode();
- }
- else if(string_iequals(node.name(), "fresnel")) {
- snode = new FresnelNode();
- }
- else if(string_iequals(node.name(), "layer_weight")) {
- snode = new LayerWeightNode();
- }
- else if(string_iequals(node.name(), "wireframe")) {
- WireframeNode *wire = new WireframeNode;
- xml_read_bool(&wire->use_pixel_size, node, "use_pixel_size");
- snode = wire;
- }
- else if(string_iequals(node.name(), "normal_map")) {
- NormalMapNode *nmap = new NormalMapNode;
- xml_read_ustring(&nmap->attribute, node, "attribute");
- xml_read_enum(&nmap->space, NormalMapNode::space_enum, node, "space");
- snode = nmap;
- }
- else if(string_iequals(node.name(), "tangent")) {
- TangentNode *tangent = new TangentNode;
- xml_read_ustring(&tangent->attribute, node, "attribute");
- xml_read_enum(&tangent->direction_type, TangentNode::direction_type_enum, node, "direction_type");
- xml_read_enum(&tangent->axis, TangentNode::axis_enum, node, "axis");
- snode = tangent;
- }
- else if(string_iequals(node.name(), "math")) {
- MathNode *math = new MathNode();
- xml_read_enum(&math->type, MathNode::type_enum, node, "type");
- xml_read_bool(&math->use_clamp, node, "use_clamp");
- snode = math;
- }
- else if(string_iequals(node.name(), "vector_math")) {
- VectorMathNode *vmath = new VectorMathNode();
- xml_read_enum(&vmath->type, VectorMathNode::type_enum, node, "type");
- snode = vmath;
- }
- else if(string_iequals(node.name(), "vector_transform")) {
- VectorTransformNode *vtransform = new VectorTransformNode();
- xml_read_enum(&vtransform->type, VectorTransformNode::type_enum, node, "type");
- xml_read_enum(&vtransform->convert_from, VectorTransformNode::convert_space_enum, node, "convert_from");
- xml_read_enum(&vtransform->convert_to, VectorTransformNode::convert_space_enum, node, "convert_to");
- snode = vtransform;
- }
- else if(string_iequals(node.name(), "connect")) {
+ if(node_name == "connect") {
/* connect nodes */
vector<string> from_tokens, to_tokens;
@@ -726,35 +241,40 @@ static void xml_read_shader_graph(XMLReadState& state, Shader *shader, pugi::xml
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(nodemap.find(from_tokens[0]) != nodemap.end()) {
- ShaderNode *fromnode = nodemap[from_tokens[0]];
+ 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(xml_socket_name(out->name), from_tokens[1]))
+ if(string_iequals(xml_socket_name(out->name().c_str()), from_socket_name.c_str()))
output = out;
if(!output)
- fprintf(stderr, "Unknown output socket name \"%s\" on \"%s\".\n", from_tokens[1].c_str(), from_tokens[0].c_str());
+ 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_tokens[0].c_str());
+ fprintf(stderr, "Unknown shader node name \"%s\".\n", from_node_name.c_str());
- if(nodemap.find(to_tokens[0]) != nodemap.end()) {
- ShaderNode *tonode = nodemap[to_tokens[0]];
+ 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(xml_socket_name(in->name), to_tokens[1]))
+ if(string_iequals(xml_socket_name(in->name().c_str()), to_socket_name.c_str()))
input = in;
if(!input)
- fprintf(stderr, "Unknown input socket name \"%s\" on \"%s\".\n", to_tokens[1].c_str(), to_tokens[0].c_str());
+ 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_tokens[0].c_str());
+ fprintf(stderr, "Unknown shader node name \"%s\".\n", to_node_name.c_str());
/* connect */
if(output && input)
@@ -762,44 +282,76 @@ static void xml_read_shader_graph(XMLReadState& state, Shader *shader, pugi::xml
}
else
fprintf(stderr, "Invalid from or to value for connect node.\n");
+
+ continue;
}
- else
- fprintf(stderr, "Unknown shader node \"%s\".\n", node.name());
- if(snode) {
- /* add to graph */
- graph->add(snode);
+ ShaderNode *snode = NULL;
+
+#ifdef WITH_OSL
+ if(node_name == "osl_shader") {
+ ShaderManager *manager = state.scene->shader_manager;
- /* add to map for name lookups */
- string name = "";
- xml_read_string(&name, node, "name");
-
- nodemap[name] = snode;
-
- /* read input values */
- for(pugi::xml_attribute attr = node.first_attribute(); attr; attr = attr.next_attribute()) {
- foreach(ShaderInput *in, snode->inputs) {
- if(string_iequals(in->name, attr.name())) {
- switch(in->type) {
- case SHADER_SOCKET_FLOAT:
- case SHADER_SOCKET_INT:
- xml_read_float(&in->value.x, node, attr.name());
- break;
- case SHADER_SOCKET_COLOR:
- case SHADER_SOCKET_VECTOR:
- case SHADER_SOCKET_POINT:
- case SHADER_SOCKET_NORMAL:
- xml_read_float3(&in->value, node, attr.name());
- break;
- case SHADER_SOCKET_STRING:
- xml_read_ustring( &in->value_string, node, attr.name() );
- break;
- default:
- break;
- }
+ 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);
}
}
@@ -864,6 +416,7 @@ static void xml_read_mesh(const XMLReadState& state, pugi::xml_node node)
xml_read_int_array(verts, node, "verts");
xml_read_int_array(nverts, node, "nverts");
+#if 0
if(xml_equal_string(node, "subdivision", "catmull-clark")) {
/* create subd mesh */
SubdMesh sdmesh;
@@ -907,10 +460,17 @@ static void xml_read_mesh(const XMLReadState& state, pugi::xml_node node)
DiagSplit dsplit(sdparams);
sdmesh.tessellate(&dsplit);
}
- else {
+ else
+#endif
+ {
/* 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;
@@ -1010,7 +570,7 @@ static void xml_read_patch(const XMLReadState& state, pugi::xml_node node)
mesh->used_shaders.push_back(state.shader);
/* split */
- SubdParams sdparams(mesh, 0, state.smooth);
+ SubdParams sdparams(mesh);
xml_read_float(&sdparams.dicing_rate, node, "dicing_rate");
DiagSplit dsplit(sdparams);
diff --git a/intern/cycles/blender/addon/engine.py b/intern/cycles/blender/addon/engine.py
index d4b7535b9ee..2c5365c9189 100644
--- a/intern/cycles/blender/addon/engine.py
+++ b/intern/cycles/blender/addon/engine.py
@@ -82,7 +82,6 @@ def init():
import bpy
import _cycles
import os.path
- import sys
# Workaround possibly buggy legacy drivers which crashes on the OpenCL
# device enumeration.
@@ -103,10 +102,12 @@ def init():
_cycles.init(path, user_path, bpy.app.background)
_parse_command_line()
+
def exit():
import _cycles
_cycles.exit()
+
def create(engine, data, scene, region=None, v3d=None, rv3d=None, preview_osl=False):
import bpy
import _cycles
diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py
index 140862721a8..81204eb8ae0 100644
--- a/intern/cycles/blender/addon/properties.py
+++ b/intern/cycles/blender/addon/properties.py
@@ -46,12 +46,6 @@ enum_displacement_methods = (
('BOTH', "Both", "Combination of displacement and bump mapping"),
)
-enum_subdivision_types = (
- ('NONE', "None", "No subdivision"),
- ('LINEAR', "Linear", "Use linear subdivision"),
- ('CATMULL_CLARK', "Catmull–Clark", "Use Catmull-Clark subdivision"),
- )
-
enum_bvh_types = (
('DYNAMIC_BVH', "Dynamic BVH", "Objects can be individually updated, at the cost of slower render time"),
('STATIC_BVH', "Static BVH", "Any object modification requires a complete BVH rebuild, but renders faster"),
@@ -503,6 +497,11 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
description="Use BVH spatial splits: longer builder time, faster render",
default=False,
)
+ cls.debug_use_hair_bvh = BoolProperty(
+ name="Use Hair BVH",
+ description="Use special type BVH optimized for hair (uses more ram but renders faster)",
+ default=True,
+ )
cls.tile_order = EnumProperty(
name="Tile Order",
description="Tile order for rendering",
@@ -959,18 +958,6 @@ class CyclesMeshSettings(bpy.types.PropertyGroup):
items=enum_displacement_methods,
default='BUMP',
)
- cls.subdivision_type = EnumProperty(
- name="Subdivision Type",
- description="Type of subdivision to use",
- items=enum_subdivision_types,
- default='NONE',
- )
- cls.dicing_rate = FloatProperty(
- name="Dicing Rate",
- description="Multiplier for scene dicing rate",
- min=0.1, max=1000.0,
- default=1.0,
- )
@classmethod
def unregister(cls):
@@ -979,11 +966,9 @@ class CyclesMeshSettings(bpy.types.PropertyGroup):
del bpy.types.MetaBall.cycles
-class CyclesObjectBlurSettings(bpy.types.PropertyGroup):
-
+class CyclesObjectSettings(bpy.types.PropertyGroup):
@classmethod
def register(cls):
-
bpy.types.Object.cycles = PointerProperty(
name="Cycles Object Settings",
description="Cycles object settings",
@@ -1015,6 +1000,19 @@ class CyclesObjectBlurSettings(bpy.types.PropertyGroup):
default=False,
)
+ cls.use_adaptive_subdivision = BoolProperty(
+ name="Use Adaptive Subdivision",
+ description="Use adaptive render time subdivision",
+ default=False,
+ )
+
+ cls.dicing_rate = FloatProperty(
+ name="Dicing Rate",
+ description="Multiplier for scene dicing rate",
+ min=0.1, max=1000.0,
+ default=1.0,
+ )
+
@classmethod
def unregister(cls):
del bpy.types.Object.cycles
@@ -1131,6 +1129,7 @@ def register():
bpy.utils.register_class(CyclesWorldSettings)
bpy.utils.register_class(CyclesVisibilitySettings)
bpy.utils.register_class(CyclesMeshSettings)
+ bpy.utils.register_class(CyclesObjectSettings)
bpy.utils.register_class(CyclesCurveRenderSettings)
bpy.utils.register_class(CyclesCurveSettings)
@@ -1142,6 +1141,7 @@ def unregister():
bpy.utils.unregister_class(CyclesLampSettings)
bpy.utils.unregister_class(CyclesWorldSettings)
bpy.utils.unregister_class(CyclesMeshSettings)
+ bpy.utils.unregister_class(CyclesObjectSettings)
bpy.utils.unregister_class(CyclesVisibilitySettings)
bpy.utils.unregister_class(CyclesCurveRenderSettings)
bpy.utils.unregister_class(CyclesCurveSettings)
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index 023841a7a17..42f7970769a 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -76,9 +76,8 @@ def use_cuda(context):
def use_branched_path(context):
cscene = context.scene.cycles
- device_type = context.user_preferences.system.compute_device_type
- return (cscene.progressive == 'BRANCHED_PATH' and device_type != 'OPENCL')
+ return (cscene.progressive == 'BRANCHED_PATH' and not use_opencl(context))
def use_sample_all_lights(context):
@@ -384,7 +383,6 @@ class CyclesRender_PT_performance(CyclesButtonsPanel, Panel):
sub.prop(cscene, "use_progressive_refine")
subsub = sub.column(align=True)
- subsub.enabled = not rd.use_border
subsub.prop(rd, "use_save_buffers")
col = split.column(align=True)
@@ -403,6 +401,7 @@ class CyclesRender_PT_performance(CyclesButtonsPanel, Panel):
col.label(text="Acceleration structure:")
col.prop(cscene, "debug_use_spatial_splits")
+ col.prop(cscene, "debug_use_hair_bvh")
class CyclesRender_PT_layer_options(CyclesButtonsPanel, Panel):
@@ -460,7 +459,9 @@ class CyclesRender_PT_layer_passes(CyclesButtonsPanel, Panel):
col.prop(rl, "use_pass_z")
col.prop(rl, "use_pass_mist")
col.prop(rl, "use_pass_normal")
- col.prop(rl, "use_pass_vector")
+ row = col.row()
+ row.prop(rl, "use_pass_vector")
+ row.active = not rd.use_motion_blur
col.prop(rl, "use_pass_uv")
col.prop(rl, "use_pass_object_index")
col.prop(rl, "use_pass_material_index")
@@ -704,17 +705,9 @@ class Cycles_PT_mesh_displacement(CyclesButtonsPanel, Panel):
col = split.column()
sub = col.column(align=True)
- sub.label(text="Displacment:")
+ sub.label(text="Displacement:")
sub.prop(cdata, "displacement_method", text="")
- col = split.column()
- sub = col.column(align=True)
- sub.label(text="Subdivision:")
- sub.prop(cdata, "subdivision_type", text="")
-
- if cdata.subdivision_type != 'NONE':
- sub.prop(cdata, "dicing_rate")
-
class CyclesObject_PT_motion_blur(CyclesButtonsPanel, Panel):
bl_label = "Motion Blur"
bl_context = "object"
@@ -894,7 +887,7 @@ class CyclesLamp_PT_lamp(CyclesButtonsPanel, Panel):
lamp = context.lamp
clamp = lamp.cycles
- cscene = context.scene.cycles
+ # cscene = context.scene.cycles
layout.prop(lamp, "type", expand=True)
@@ -1114,7 +1107,7 @@ class CyclesWorld_PT_settings(CyclesButtonsPanel, Panel):
world = context.world
cworld = world.cycles
- cscene = context.scene.cycles
+ # cscene = context.scene.cycles
split = layout.split()
@@ -1664,104 +1657,62 @@ def draw_pause(self, context):
def get_panels():
- types = bpy.types
- panels = [
- "RENDER_PT_render",
- "RENDER_PT_output",
- "RENDER_PT_encoding",
- "RENDER_PT_dimensions",
- "RENDER_PT_stamp",
- "RENDER_PT_freestyle",
- "RENDERLAYER_PT_layers",
- "RENDERLAYER_PT_freestyle",
- "RENDERLAYER_PT_freestyle_lineset",
- "RENDERLAYER_PT_freestyle_linestyle",
- "SCENE_PT_scene",
- "SCENE_PT_color_management",
- "SCENE_PT_custom_props",
- "SCENE_PT_audio",
- "SCENE_PT_unit",
- "SCENE_PT_keying_sets",
- "SCENE_PT_keying_set_paths",
- "SCENE_PT_physics",
- "WORLD_PT_context_world",
- "WORLD_PT_custom_props",
- "DATA_PT_context_mesh",
- "DATA_PT_context_camera",
- "DATA_PT_context_lamp",
- "DATA_PT_context_speaker",
- "DATA_PT_normals",
- "DATA_PT_texture_space",
- "DATA_PT_curve_texture_space",
- "DATA_PT_mball_texture_space",
- "DATA_PT_vertex_groups",
- "DATA_PT_shape_keys",
- "DATA_PT_uv_texture",
- "DATA_PT_vertex_colors",
- "DATA_PT_camera",
- "DATA_PT_camera_display",
- "DATA_PT_camera_stereoscopy",
- "DATA_PT_camera_safe_areas",
- "DATA_PT_lens",
- "DATA_PT_speaker",
- "DATA_PT_distance",
- "DATA_PT_cone",
- "DATA_PT_customdata",
- "DATA_PT_custom_props_mesh",
- "DATA_PT_custom_props_camera",
- "DATA_PT_custom_props_lamp",
- "DATA_PT_custom_props_speaker",
- "DATA_PT_custom_props_arm",
- "DATA_PT_custom_props_curve",
- "DATA_PT_custom_props_lattice",
- "DATA_PT_custom_props_metaball",
- "TEXTURE_PT_preview",
- "TEXTURE_PT_custom_props",
- "TEXTURE_PT_clouds",
- "TEXTURE_PT_wood",
- "TEXTURE_PT_marble",
- "TEXTURE_PT_magic",
- "TEXTURE_PT_blend",
- "TEXTURE_PT_stucci",
- "TEXTURE_PT_image",
- "TEXTURE_PT_image_sampling",
- "TEXTURE_PT_image_mapping",
- "TEXTURE_PT_musgrave",
- "TEXTURE_PT_voronoi",
- "TEXTURE_PT_distortednoise",
- "TEXTURE_PT_voxeldata",
- "TEXTURE_PT_pointdensity",
- "TEXTURE_PT_pointdensity_turbulence",
- "TEXTURE_PT_mapping",
- "TEXTURE_PT_ocean",
- "TEXTURE_PT_influence",
- "TEXTURE_PT_colors",
- "PARTICLE_PT_context_particles",
- "PARTICLE_PT_custom_props",
- "PARTICLE_PT_emission",
- "PARTICLE_PT_hair_dynamics",
- "PARTICLE_PT_cache",
- "PARTICLE_PT_velocity",
- "PARTICLE_PT_rotation",
- "PARTICLE_PT_physics",
- "SCENE_PT_rigid_body_world",
- "SCENE_PT_rigid_body_cache",
- "SCENE_PT_rigid_body_field_weights",
- "PARTICLE_PT_boidbrain",
- "PARTICLE_PT_render",
- "PARTICLE_PT_draw",
- "PARTICLE_PT_children",
- "PARTICLE_PT_field_weights",
- "PARTICLE_PT_force_fields",
- "PARTICLE_PT_vertexgroups",
- "MATERIAL_PT_custom_props",
- "MATERIAL_PT_freestyle_line",
- "BONE_PT_custom_props",
- "OBJECT_PT_custom_props",
- ]
-
- return [getattr(types, p) for p in panels if hasattr(types, p)]
-
+ exclude_panels = {
+ 'DATA_PT_area',
+ 'DATA_PT_camera_dof',
+ 'DATA_PT_falloff_curve',
+ 'DATA_PT_lamp',
+ 'DATA_PT_preview',
+ 'DATA_PT_shadow',
+ 'DATA_PT_spot',
+ 'DATA_PT_sunsky',
+ 'MATERIAL_PT_context_material',
+ 'MATERIAL_PT_diffuse',
+ 'MATERIAL_PT_flare',
+ 'MATERIAL_PT_halo',
+ 'MATERIAL_PT_mirror',
+ 'MATERIAL_PT_options',
+ 'MATERIAL_PT_pipeline',
+ 'MATERIAL_PT_preview',
+ 'MATERIAL_PT_shading',
+ 'MATERIAL_PT_shadow',
+ 'MATERIAL_PT_specular',
+ 'MATERIAL_PT_sss',
+ 'MATERIAL_PT_strand',
+ 'MATERIAL_PT_transp',
+ 'MATERIAL_PT_volume_density',
+ 'MATERIAL_PT_volume_integration',
+ 'MATERIAL_PT_volume_lighting',
+ 'MATERIAL_PT_volume_options',
+ 'MATERIAL_PT_volume_shading',
+ 'MATERIAL_PT_volume_transp',
+ 'RENDERLAYER_PT_layer_options',
+ 'RENDERLAYER_PT_layer_passes',
+ 'RENDERLAYER_PT_views',
+ 'RENDER_PT_antialiasing',
+ 'RENDER_PT_bake',
+ 'RENDER_PT_motion_blur',
+ 'RENDER_PT_performance',
+ 'RENDER_PT_post_processing',
+ 'RENDER_PT_shading',
+ 'SCENE_PT_simplify',
+ 'TEXTURE_PT_context_texture',
+ 'WORLD_PT_ambient_occlusion',
+ 'WORLD_PT_environment_lighting',
+ 'WORLD_PT_gather',
+ 'WORLD_PT_indirect_lighting',
+ 'WORLD_PT_mist',
+ 'WORLD_PT_preview',
+ 'WORLD_PT_world'
+ }
+
+ panels = []
+ for panel in bpy.types.Panel.__subclasses__():
+ if hasattr(panel, 'COMPAT_ENGINES') and 'BLENDER_RENDER' in panel.COMPAT_ENGINES:
+ if panel.__name__ not in exclude_panels:
+ panels.append(panel)
+
+ return panels
def register():
bpy.types.RENDER_PT_render.append(draw_device)
@@ -1770,10 +1721,10 @@ def register():
for panel in get_panels():
panel.COMPAT_ENGINES.add('CYCLES')
-
def unregister():
bpy.types.RENDER_PT_render.remove(draw_device)
bpy.types.VIEW3D_HT_header.remove(draw_pause)
for panel in get_panels():
- panel.COMPAT_ENGINES.remove('CYCLES')
+ if 'CYCLES' in panel.COMPAT_ENGINES:
+ panel.COMPAT_ENGINES.remove('CYCLES')
diff --git a/intern/cycles/blender/addon/version_update.py b/intern/cycles/blender/addon/version_update.py
index 221b1437128..830723d6149 100644
--- a/intern/cycles/blender/addon/version_update.py
+++ b/intern/cycles/blender/addon/version_update.py
@@ -104,7 +104,6 @@ def vector_curve_node_remap(node):
"""
Remap values of vector curve node from normalized to absolute values
"""
- from mathutils import Vector
if node.bl_idname == 'ShaderNodeVectorCurve':
node.mapping.use_clip = False
for curve in node.mapping.curves:
diff --git a/intern/cycles/blender/blender_camera.cpp b/intern/cycles/blender/blender_camera.cpp
index 9dec489ce33..f02fc553908 100644
--- a/intern/cycles/blender/blender_camera.cpp
+++ b/intern/cycles/blender/blender_camera.cpp
@@ -37,7 +37,7 @@ struct BlenderCamera {
float lens;
float shuttertime;
Camera::MotionPosition motion_position;
- float shutter_curve[RAMP_TABLE_SIZE];
+ array<float> shutter_curve;
Camera::RollingShutterType rolling_shutter_type;
float rolling_shutter_duration;
@@ -108,10 +108,6 @@ static void blender_camera_init(BlenderCamera *bcam,
/* render resolution */
bcam->full_width = render_resolution_x(b_render);
bcam->full_height = render_resolution_y(b_render);
-
- /* pixel aspect */
- bcam->pixelaspect.x = b_render.pixel_aspect_x();
- bcam->pixelaspect.y = b_render.pixel_aspect_y();
}
static float blender_camera_focal_distance(BL::RenderEngine& b_engine,
@@ -464,7 +460,7 @@ static void blender_camera_sync(Camera *cam, BlenderCamera *bcam, int width, int
cam->rolling_shutter_type = bcam->rolling_shutter_type;
cam->rolling_shutter_duration = bcam->rolling_shutter_duration;
- memcpy(cam->shutter_curve, bcam->shutter_curve, sizeof(cam->shutter_curve));
+ cam->shutter_curve = bcam->shutter_curve;
/* border */
cam->border = bcam->border;
@@ -563,6 +559,10 @@ void BlenderSync::sync_camera_motion(BL::RenderSettings& b_render,
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,
diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp
index 64f1b66405e..378ae67f0c7 100644
--- a/intern/cycles/blender/blender_curves.cpp
+++ b/intern/cycles/blender/blender_curves.cpp
@@ -156,16 +156,16 @@ bool ObtainCacheParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, Par
PointerRNA cpsys = RNA_pointer_get(&b_part.ptr, "cycles");
- CData->psys_firstcurve.push_back(curvenum);
- CData->psys_curvenum.push_back(totcurves);
- CData->psys_shader.push_back(shader);
+ CData->psys_firstcurve.push_back_slow(curvenum);
+ CData->psys_curvenum.push_back_slow(totcurves);
+ CData->psys_shader.push_back_slow(shader);
float radius = get_float(cpsys, "radius_scale") * 0.5f;
- CData->psys_rootradius.push_back(radius * get_float(cpsys, "root_width"));
- CData->psys_tipradius.push_back(radius * get_float(cpsys, "tip_width"));
- CData->psys_shape.push_back(get_float(cpsys, "shape"));
- CData->psys_closetip.push_back(get_boolean(cpsys, "use_closetip"));
+ CData->psys_rootradius.push_back_slow(radius * get_float(cpsys, "root_width"));
+ CData->psys_tipradius.push_back_slow(radius * get_float(cpsys, "tip_width"));
+ CData->psys_shape.push_back_slow(get_float(cpsys, "shape"));
+ CData->psys_closetip.push_back_slow(get_boolean(cpsys, "use_closetip"));
int pa_no = 0;
if(!(b_part.child_type() == 0) && totchild != 0)
@@ -180,7 +180,7 @@ bool ObtainCacheParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, Par
for(; pa_no < totparts+totchild; pa_no++) {
int keynum = 0;
- CData->curve_firstkey.push_back(keyno);
+ CData->curve_firstkey.push_back_slow(keyno);
float curve_length = 0.0f;
float3 pcKey;
@@ -195,15 +195,15 @@ bool ObtainCacheParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, Par
continue;
curve_length += step_length;
}
- CData->curvekey_co.push_back(cKey);
- CData->curvekey_time.push_back(curve_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(keynum);
- CData->curve_length.push_back(curve_length);
+ CData->curve_keynum.push_back_slow(keynum);
+ CData->curve_length.push_back_slow(curve_length);
curvenum++;
}
}
@@ -255,7 +255,7 @@ bool ObtainCacheParticleUV(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, Parti
float3 uv = make_float3(0.0f, 0.0f, 0.0f);
if(b_mesh->tessface_uv_textures.length())
b_psys.uv_on_emitter(psmd, *b_pa, pa_no, uv_num, &uv.x);
- CData->curve_uv.push_back(uv);
+ CData->curve_uv.push_back_slow(uv);
if(pa_no < totparts && b_pa != b_psys.particles.end())
++b_pa;
@@ -309,7 +309,7 @@ bool ObtainCacheParticleVcol(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, Par
float3 vcol = make_float3(0.0f, 0.0f, 0.0f);
if(b_mesh->tessface_vertex_colors.length())
b_psys.mcol_on_emitter(psmd, *b_pa, pa_no, vcol_num, &vcol.x);
- CData->curve_vcol.push_back(vcol);
+ CData->curve_vcol.push_back_slow(vcol);
if(pa_no < totparts && b_pa != b_psys.particles.end())
++b_pa;
@@ -351,10 +351,7 @@ void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData,
}
}
- mesh->verts.reserve(mesh->verts.size() + numverts);
- mesh->triangles.reserve(mesh->triangles.size() + numtris);
- mesh->shader.reserve(mesh->shader.size() + numtris);
- mesh->smooth.reserve(mesh->smooth.size() + numtris);
+ mesh->reserve_mesh(mesh->verts.size() + numverts, mesh->num_triangles() + numtris);
/* actually export */
for(int sys = 0; sys < CData->psys_firstcurve.size() ; sys++) {
@@ -374,8 +371,8 @@ void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData,
xbasis = normalize(cross(RotCam - ickey_loc, v1));
float3 ickey_loc_shfl = ickey_loc - radius * xbasis;
float3 ickey_loc_shfr = ickey_loc + radius * xbasis;
- mesh->verts.push_back(ickey_loc_shfl);
- mesh->verts.push_back(ickey_loc_shfr);
+ 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++) {
@@ -401,8 +398,8 @@ void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData,
xbasis = normalize(cross(RotCam - ickey_loc, v1));
float3 ickey_loc_shfl = ickey_loc - radius * xbasis;
float3 ickey_loc_shfr = ickey_loc + radius * xbasis;
- mesh->verts.push_back(ickey_loc_shfl);
- mesh->verts.push_back(ickey_loc_shfr);
+ 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;
@@ -410,7 +407,6 @@ void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData,
}
}
- mesh->reserve(mesh->verts.size(), mesh->triangles.size(), 0, 0);
mesh->attributes.remove(ATTR_STD_VERTEX_NORMAL);
mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
mesh->add_face_normals();
@@ -437,10 +433,7 @@ void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, int resol
}
}
- mesh->verts.reserve(mesh->verts.size() + numverts);
- mesh->triangles.reserve(mesh->triangles.size() + numtris);
- mesh->shader.reserve(mesh->shader.size() + numtris);
- mesh->smooth.reserve(mesh->smooth.size() + numtris);
+ mesh->reserve_mesh(mesh->verts.size() + numverts, mesh->num_triangles() + numtris);
/* actually export */
for(int sys = 0; sys < CData->psys_firstcurve.size() ; sys++) {
@@ -529,7 +522,7 @@ void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, int resol
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->verts.push_back(ickey_loc_shf);
+ mesh->add_vertex(ickey_loc_shf);
}
if(subv != 0) {
@@ -546,7 +539,6 @@ void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, int resol
}
}
- mesh->reserve(mesh->verts.size(), mesh->triangles.size(), 0, 0);
mesh->attributes.remove(ATTR_STD_VERTEX_NORMAL);
mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
mesh->add_face_normals();
@@ -561,7 +553,7 @@ void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CData)
int num_keys = 0;
int num_curves = 0;
- if(!(mesh->curves.empty() && mesh->curve_keys.empty()))
+ if(mesh->num_curves())
return;
Attribute *attr_intercept = NULL;
@@ -584,8 +576,7 @@ void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CData)
VLOG(1) << "Exporting curve segments for mesh " << mesh->name;
}
- mesh->curve_keys.reserve(mesh->curve_keys.size() + num_keys);
- mesh->curves.reserve(mesh->curves.size() + num_curves);
+ mesh->reserve_curves(mesh->num_curves() + num_curves, mesh->curve_keys.size() + num_keys);
num_keys = 0;
num_curves = 0;
@@ -613,18 +604,16 @@ void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CData)
num_curve_keys++;
}
- mesh->add_curve(num_keys, num_curve_keys, CData->psys_shader[sys]);
+ 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->curves.size() != num_curves)) {
+ if((mesh->curve_keys.size() != num_keys) || (mesh->num_curves() != num_curves)) {
VLOG(1) << "Allocation failed, clearing data";
- mesh->curve_keys.clear();
- mesh->curves.clear();
- mesh->curve_attributes.clear();
+ mesh->clear();
}
}
@@ -667,13 +656,16 @@ static void ExportCurveSegmentsMotion(Mesh *mesh, ParticleCurveData *CData, int
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 */
mP[i] = float3_to_float4(ickey_loc);
mP[i].w = radius;
/* 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 */
- if(len_squared(mP[i] - mesh->curve_keys[i]) > 1e-5f*1e-5f)
+ 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;
}
@@ -697,8 +689,10 @@ static void ExportCurveSegmentsMotion(Mesh *mesh, ParticleCurveData *CData, int
for(int step = 0; step < time_index; step++) {
float4 *mP = attr_mP->data_float4() + step*numkeys;
- for(int key = 0; key < numkeys; key++)
- mP[key] = mesh->curve_keys[key];
+ for(int key = 0; key < numkeys; key++) {
+ mP[key] = float3_to_float4(mesh->curve_keys[key]);
+ mP[key].w = mesh->curve_radius[key];
+ }
}
}
}
@@ -872,7 +866,9 @@ void BlenderSync::sync_curves(Mesh *mesh,
if(!motion) {
/* Clear stored curve data */
mesh->curve_keys.clear();
- mesh->curves.clear();
+ mesh->curve_radius.clear();
+ mesh->curve_first_key.clear();
+ mesh->curve_shader.clear();
mesh->curve_attributes.clear();
}
@@ -889,7 +885,7 @@ void BlenderSync::sync_curves(Mesh *mesh,
int triangle_method = scene->curve_system_manager->triangle_method;
int resolution = scene->curve_system_manager->resolution;
size_t vert_num = mesh->verts.size();
- size_t tri_num = mesh->triangles.size();
+ size_t tri_num = mesh->num_triangles();
int used_res = 1;
/* extract particle hair data - should be combined with connecting to mesh later*/
@@ -950,11 +946,10 @@ void BlenderSync::sync_curves(Mesh *mesh,
else {
Attribute *attr_generated = mesh->curve_attributes.add(ATTR_STD_GENERATED);
float3 *generated = attr_generated->data_float3();
- size_t i = 0;
- foreach(Mesh::Curve& curve, mesh->curves) {
- float3 co = float4_to_float3(mesh->curve_keys[curve.first_key]);
- generated[i++] = co*size - loc;
+ 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;
}
}
}
diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp
index 4a0ad79f3ae..74fd4cb44a0 100644
--- a/intern/cycles/blender/blender_mesh.cpp
+++ b/intern/cycles/blender/blender_mesh.cpp
@@ -24,7 +24,6 @@
#include "blender_session.h"
#include "blender_util.h"
-#include "subd_mesh.h"
#include "subd_patch.h"
#include "subd_split.h"
@@ -335,44 +334,71 @@ static void attr_create_vertex_color(Scene *scene,
Mesh *mesh,
BL::Mesh& b_mesh,
const vector<int>& nverts,
- const vector<int>& face_flags)
+ const vector<int>& face_flags,
+ bool subdivision)
{
- BL::Mesh::tessface_vertex_colors_iterator l;
- for(b_mesh.tessface_vertex_colors.begin(l); l != b_mesh.tessface_vertex_colors.end(); ++l) {
- if(!mesh->need_attribute(scene, ustring(l->name().c_str())))
- continue;
+ if(subdivision) {
+ BL::Mesh::vertex_colors_iterator l;
- Attribute *attr = mesh->attributes.add(
- ustring(l->name().c_str()), TypeDesc::TypeColor, ATTR_ELEMENT_CORNER_BYTE);
+ 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;
- BL::MeshColorLayer::data_iterator c;
- uchar4 *cdata = attr->data_uchar4();
- size_t i = 0;
+ Attribute *attr = mesh->subd_attributes.add(ustring(l->name().c_str()),
+ TypeDesc::TypeColor,
+ ATTR_ELEMENT_CORNER_BYTE);
- for(l->data.begin(c); c != l->data.end(); ++c, ++i) {
- int tri_a[3], tri_b[3];
- face_split_tri_indices(nverts[i], face_flags[i], tri_a, tri_b);
+ BL::Mesh::polygons_iterator p;
+ uchar4 *cdata = attr->data_uchar4();
- uchar4 colors[4];
- colors[0] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color1())));
- colors[1] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color2())));
- colors[2] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color3())));
- if(nverts[i] == 4) {
- colors[3] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color4())));
+ 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());
+ *(cdata++) = color_float_to_byte(color_srgb_to_scene_linear(color));
+ }
}
+ }
+ }
+ else {
+ BL::Mesh::tessface_vertex_colors_iterator l;
+ for(b_mesh.tessface_vertex_colors.begin(l); l != b_mesh.tessface_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::MeshColorLayer::data_iterator c;
+ uchar4 *cdata = attr->data_uchar4();
+ size_t i = 0;
+
+ for(l->data.begin(c); c != l->data.end(); ++c, ++i) {
+ int tri_a[3], tri_b[3];
+ face_split_tri_indices(nverts[i], face_flags[i], tri_a, tri_b);
+
+ uchar4 colors[4];
+ colors[0] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color1())));
+ colors[1] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color2())));
+ colors[2] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color3())));
+ if(nverts[i] == 4) {
+ colors[3] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color4())));
+ }
- cdata[0] = colors[tri_a[0]];
- cdata[1] = colors[tri_a[1]];
- cdata[2] = colors[tri_a[2]];
+ cdata[0] = colors[tri_a[0]];
+ cdata[1] = colors[tri_a[1]];
+ cdata[2] = colors[tri_a[2]];
- if(nverts[i] == 4) {
- cdata[3] = colors[tri_b[0]];
- cdata[4] = colors[tri_b[1]];
- cdata[5] = colors[tri_b[2]];
- cdata += 6;
+ if(nverts[i] == 4) {
+ cdata[3] = colors[tri_b[0]];
+ cdata[4] = colors[tri_b[1]];
+ cdata[5] = colors[tri_b[2]];
+ cdata += 6;
+ }
+ else
+ cdata += 3;
}
- else
- cdata += 3;
}
}
}
@@ -382,9 +408,40 @@ static void attr_create_uv_map(Scene *scene,
Mesh *mesh,
BL::Mesh& b_mesh,
const vector<int>& nverts,
- const vector<int>& face_flags)
+ const vector<int>& face_flags,
+ bool subdivision)
{
- if(b_mesh.tessface_uv_textures.length() != 0) {
+ if(subdivision) {
+ 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 = b_mesh.uv_textures[i].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;
+
+ if(active_render)
+ attr = mesh->subd_attributes.add(std, name);
+ else
+ attr = mesh->subd_attributes.add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CORNER);
+
+ BL::Mesh::polygons_iterator p;
+ float3 *fdata = attr->data_float3();
+
+ 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_float3(l->data[p->loop_start() + j].uv());
+ }
+ }
+ }
+ }
+ }
+ else if(b_mesh.tessface_uv_textures.length() != 0) {
BL::Mesh::tessface_uv_textures_iterator l;
for(b_mesh.tessface_uv_textures.begin(l); l != b_mesh.tessface_uv_textures.end(); ++l) {
@@ -465,11 +522,13 @@ static void attr_create_uv_map(Scene *scene,
/* Create vertex pointiness attributes. */
static void attr_create_pointiness(Scene *scene,
Mesh *mesh,
- BL::Mesh& b_mesh)
+ BL::Mesh& b_mesh,
+ bool subdivision)
{
if(mesh->need_attribute(scene, ATTR_STD_POINTINESS)) {
const int numverts = b_mesh.vertices.length();
- Attribute *attr = mesh->attributes.add(ATTR_STD_POINTINESS);
+ AttributeSet& attributes = (subdivision)? mesh->subd_attributes: mesh->attributes;
+ Attribute *attr = attributes.add(ATTR_STD_POINTINESS);
float *data = attr->data_float();
int *counter = new int[numverts];
float *raw_data = new float[numverts];
@@ -532,31 +591,44 @@ static void attr_create_pointiness(Scene *scene,
static void create_mesh(Scene *scene,
Mesh *mesh,
BL::Mesh& b_mesh,
- const vector<Shader*>& used_shaders)
+ const vector<Shader*>& used_shaders,
+ bool subdivision=false)
{
/* count vertices and faces */
int numverts = b_mesh.vertices.length();
- int numfaces = b_mesh.tessfaces.length();
+ int numfaces = (!subdivision) ? b_mesh.tessfaces.length() : b_mesh.polygons.length();
int numtris = 0;
+ int numcorners = 0;
+ int numngons = 0;
bool use_loop_normals = b_mesh.use_auto_smooth();
BL::Mesh::vertices_iterator v;
BL::Mesh::tessfaces_iterator f;
+ BL::Mesh::polygons_iterator p;
- for(b_mesh.tessfaces.begin(f); f != b_mesh.tessfaces.end(); ++f) {
- int4 vi = get_int4(f->vertices_raw());
- numtris += (vi[3] == 0)? 1: 2;
+ if(!subdivision) {
+ for(b_mesh.tessfaces.begin(f); f != b_mesh.tessfaces.end(); ++f) {
+ int4 vi = get_int4(f->vertices_raw());
+ numtris += (vi[3] == 0)? 1: 2;
+ }
+ }
+ else {
+ for(b_mesh.polygons.begin(p); p != b_mesh.polygons.end(); ++p) {
+ numngons += (p->loop_total() == 4)? 0: 1;
+ numcorners += p->loop_total();
+ }
}
- /* reserve memory */
- mesh->reserve(numverts, numtris, 0, 0);
+ /* allocate memory */
+ mesh->reserve_mesh(numverts, numtris);
+ mesh->reserve_subd_faces(numfaces, numngons, numcorners);
/* create vertex coordinates and normals */
- int i = 0;
- for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v, ++i)
- mesh->verts[i] = get_float3(v->co());
+ for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v)
+ mesh->add_vertex(get_float3(v->co()));
- Attribute *attr_N = mesh->attributes.add(ATTR_STD_VERTEX_NORMAL);
+ 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)
@@ -565,7 +637,7 @@ static void create_mesh(Scene *scene,
/* create generated coordinates from undeformed coordinates */
if(mesh->need_attribute(scene, ATTR_STD_GENERATED)) {
- Attribute *attr = mesh->attributes.add(ATTR_STD_GENERATED);
+ Attribute *attr = attributes.add(ATTR_STD_GENERATED);
float3 loc, size;
mesh_texture_space(b_mesh, loc, size);
@@ -578,67 +650,103 @@ static void create_mesh(Scene *scene,
}
/* Create needed vertex attributes. */
- attr_create_pointiness(scene, mesh, b_mesh);
+ attr_create_pointiness(scene, mesh, b_mesh, subdivision);
/* create faces */
vector<int> nverts(numfaces);
vector<int> face_flags(numfaces, FACE_FLAG_NONE);
- int fi = 0, ti = 0;
-
- for(b_mesh.tessfaces.begin(f); f != b_mesh.tessfaces.end(); ++f, ++fi) {
- int4 vi = get_int4(f->vertices_raw());
- int n = (vi[3] == 0)? 3: 4;
- int shader = clamp(f->material_index(), 0, used_shaders.size()-1);
- bool smooth = f->use_smooth() || use_loop_normals;
-
- /* split vertices if normal is different
- *
- * note all vertex attributes must have been set here so we can split
- * and copy attributes in split_vertex without remapping later */
- if(use_loop_normals) {
- BL::Array<float, 12> loop_normals = f->split_normals();
-
- for(int i = 0; i < n; i++) {
- float3 loop_N = make_float3(loop_normals[i * 3], loop_normals[i * 3 + 1], loop_normals[i * 3 + 2]);
-
- if(N[vi[i]] != loop_N) {
- int new_vi = mesh->split_vertex(vi[i]);
-
- /* set new normal and vertex index */
- N = attr_N->data_float3();
- N[new_vi] = loop_N;
- vi[i] = new_vi;
+ int fi = 0;
+
+ if(!subdivision) {
+ for(b_mesh.tessfaces.begin(f); f != b_mesh.tessfaces.end(); ++f, ++fi) {
+ int4 vi = get_int4(f->vertices_raw());
+ int n = (vi[3] == 0)? 3: 4;
+ int shader = clamp(f->material_index(), 0, used_shaders.size()-1);
+ bool smooth = f->use_smooth() || use_loop_normals;
+
+ /* split vertices if normal is different
+ *
+ * note all vertex attributes must have been set here so we can split
+ * and copy attributes in split_vertex without remapping later */
+ if(use_loop_normals) {
+ BL::Array<float, 12> loop_normals = f->split_normals();
+
+ for(int i = 0; i < n; i++) {
+ float3 loop_N = make_float3(loop_normals[i * 3], loop_normals[i * 3 + 1], loop_normals[i * 3 + 2]);
+
+ if(N[vi[i]] != loop_N) {
+ int new_vi = mesh->split_vertex(vi[i]);
+
+ /* set new normal and vertex index */
+ N = attr_N->data_float3();
+ N[new_vi] = loop_N;
+ vi[i] = new_vi;
+ }
}
}
- }
- /* create triangles */
- if(n == 4) {
- if(is_zero(cross(mesh->verts[vi[1]] - mesh->verts[vi[0]], mesh->verts[vi[2]] - mesh->verts[vi[0]])) ||
- is_zero(cross(mesh->verts[vi[2]] - mesh->verts[vi[0]], mesh->verts[vi[3]] - mesh->verts[vi[0]])))
- {
- // TODO(mai): order here is probably wrong
- mesh->set_triangle(ti++, vi[0], vi[1], vi[3], shader, smooth, true);
- mesh->set_triangle(ti++, vi[2], vi[3], vi[1], shader, smooth, true);
- face_flags[fi] |= FACE_FLAG_DIVIDE_24;
+ /* create triangles */
+ if(n == 4) {
+ if(is_zero(cross(mesh->verts[vi[1]] - mesh->verts[vi[0]], mesh->verts[vi[2]] - mesh->verts[vi[0]])) ||
+ is_zero(cross(mesh->verts[vi[2]] - mesh->verts[vi[0]], mesh->verts[vi[3]] - mesh->verts[vi[0]])))
+ {
+ mesh->add_triangle(vi[0], vi[1], vi[3], shader, smooth);
+ mesh->add_triangle(vi[2], vi[3], vi[1], shader, smooth);
+ face_flags[fi] |= FACE_FLAG_DIVIDE_24;
+ }
+ else {
+ mesh->add_triangle(vi[0], vi[1], vi[2], shader, smooth);
+ mesh->add_triangle(vi[0], vi[2], vi[3], shader, smooth);
+ face_flags[fi] |= FACE_FLAG_DIVIDE_13;
+ }
}
else {
- mesh->set_triangle(ti++, vi[0], vi[1], vi[2], shader, smooth, true);
- mesh->set_triangle(ti++, vi[0], vi[2], vi[3], shader, smooth, true);
- face_flags[fi] |= FACE_FLAG_DIVIDE_13;
+ mesh->add_triangle(vi[0], vi[1], vi[2], shader, smooth);
}
+
+ nverts[fi] = n;
}
- else
- mesh->set_triangle(ti++, vi[0], vi[1], vi[2], shader, smooth, false);
+ }
+ else {
+ 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.reserve(n);
+ for(int i = 0; i < n; i++) {
+ vi[i] = b_mesh.loops[p->loop_start() + i].vertex_index();
+
+ /* split vertices if normal is different
+ *
+ * note all vertex attributes must have been set here so we can split
+ * and copy attributes in split_vertex without remapping later */
+ if(use_loop_normals) {
+ float3 loop_N = get_float3(b_mesh.loops[p->loop_start() + i].normal());
+
+ if(N[vi[i]] != loop_N) {
+ int new_vi = mesh->split_vertex(vi[i]);
+
+ /* set new normal and vertex index */
+ N = attr_N->data_float3();
+ N[new_vi] = loop_N;
+ vi[i] = new_vi;
+ }
+ }
+ }
- nverts[fi] = n;
+ /* 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_vertex_color(scene, mesh, b_mesh, nverts, face_flags);
- attr_create_uv_map(scene, mesh, b_mesh, nverts, face_flags);
+ attr_create_vertex_color(scene, mesh, b_mesh, nverts, face_flags, subdivision);
+ attr_create_uv_map(scene, mesh, b_mesh, nverts, face_flags, subdivision);
/* for volume objects, create a matrix to transform from object space to
* mesh texture space. this does not work with deformations but that can
@@ -658,16 +766,17 @@ static void create_subd_mesh(Scene *scene,
Mesh *mesh,
BL::Object& b_ob,
BL::Mesh& b_mesh,
- PointerRNA *cmesh,
const vector<Shader*>& used_shaders,
float dicing_rate,
int max_subdivisions)
{
- Mesh basemesh;
- create_mesh(scene, &basemesh, b_mesh, used_shaders);
+ create_mesh(scene, mesh, b_mesh, used_shaders, true);
- SubdParams sdparams(mesh, 0, true, false);
- sdparams.dicing_rate = max(0.1f, RNA_float_get(cmesh, "dicing_rate") * dicing_rate);
+ SubdParams sdparams(mesh);
+
+ 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;
scene->camera->update();
@@ -676,11 +785,48 @@ static void create_subd_mesh(Scene *scene,
/* tesselate */
DiagSplit dsplit(sdparams);
- basemesh.tessellate(&dsplit);
+ mesh->tessellate(&dsplit);
}
/* Sync */
+static void sync_mesh_fluid_motion(BL::Object& b_ob, Scene *scene, Mesh *mesh)
+{
+ if(scene->need_motion() == Scene::MOTION_NONE)
+ return;
+
+ BL::DomainFluidSettings b_fluid_domain = object_fluid_domain_find(b_ob);
+
+ 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;
+
+ /* 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);
+ }
+
+ /* 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;
+
+ 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::Object& b_ob,
bool object_updated,
bool hide_tris)
@@ -759,11 +905,12 @@ Mesh *BlenderSync::sync_mesh(BL::Object& b_ob,
/* create derived mesh */
PointerRNA cmesh = RNA_pointer_get(&b_ob_data.ptr, "cycles");
- vector<Mesh::Triangle> oldtriangle = mesh->triangles;
+ array<int> oldtriangle = mesh->triangles;
/* compares curve_keys rather than strands in order to handle quick hair
* adjustments in dynamic BVH - other methods could probably do this better*/
- vector<float4> oldcurve_keys = mesh->curve_keys;
+ array<float3> oldcurve_keys = mesh->curve_keys;
+ array<float> oldcurve_radius = mesh->curve_radius;
mesh->clear();
mesh->used_shaders = used_shaders;
@@ -780,20 +927,41 @@ Mesh *BlenderSync::sync_mesh(BL::Object& b_ob,
b_ob.update_from_editmode();
bool need_undeformed = mesh->need_attribute(scene, ATTR_STD_GENERATED);
- BL::Mesh b_mesh = object_to_mesh(b_data, b_ob, b_scene, true, !preview, need_undeformed);
+
+ mesh->subdivision_type = Mesh::SUBDIVISION_NONE;
+
+ 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(enabled && mod.type() == BL::Modifier::type_SUBSURF && RNA_int_get(&cobj, "use_adaptive_subdivision")) {
+ BL::SubsurfModifier subsurf(mod);
+
+ if(subsurf.subdivision_type() == BL::SubsurfModifier::subdivision_type_CATMULL_CLARK) {
+ mesh->subdivision_type = Mesh::SUBDIVISION_CATMULL_CLARK;
+ }
+ else {
+ mesh->subdivision_type = Mesh::SUBDIVISION_LINEAR;
+ }
+ }
+ }
+
+ BL::Mesh b_mesh = object_to_mesh(b_data, b_ob, b_scene, true, !preview, need_undeformed, mesh->subdivision_type);
if(b_mesh) {
if(render_layer.use_surfaces && !hide_tris) {
- if(cmesh.data && experimental && RNA_enum_get(&cmesh, "subdivision_type"))
- create_subd_mesh(scene, mesh, b_ob, b_mesh, &cmesh, used_shaders,
+ 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);
+ create_mesh(scene, mesh, b_mesh, used_shaders, false);
create_mesh_volume_attributes(scene, b_ob, mesh, b_scene.frame_current());
}
- if(render_layer.use_hair)
+ if(render_layer.use_hair && mesh->subdivision_type == Mesh::SUBDIVISION_NONE)
sync_curves(mesh, b_mesh, b_ob, false);
if(can_free_caches) {
@@ -801,7 +969,7 @@ Mesh *BlenderSync::sync_mesh(BL::Object& b_ob,
}
/* free derived mesh */
- b_data.meshes.remove(b_mesh);
+ b_data.meshes.remove(b_mesh, false);
}
}
mesh->geometry_flags = requested_geometry_flags;
@@ -821,20 +989,30 @@ Mesh *BlenderSync::sync_mesh(BL::Object& b_ob,
mesh->displacement_method = Mesh::DISPLACE_BOTH;
}
+ /* fluid motion */
+ sync_mesh_fluid_motion(b_ob, scene, mesh);
+
/* tag update */
bool rebuild = false;
if(oldtriangle.size() != mesh->triangles.size())
rebuild = true;
else if(oldtriangle.size()) {
- if(memcmp(&oldtriangle[0], &mesh->triangles[0], sizeof(Mesh::Triangle)*oldtriangle.size()) != 0)
+ if(memcmp(&oldtriangle[0], &mesh->triangles[0], sizeof(int)*oldtriangle.size()) != 0)
rebuild = true;
}
if(oldcurve_keys.size() != mesh->curve_keys.size())
rebuild = true;
else if(oldcurve_keys.size()) {
- if(memcmp(&oldcurve_keys[0], &mesh->curve_keys[0], sizeof(float4)*oldcurve_keys.size()) != 0)
+ if(memcmp(&oldcurve_keys[0], &mesh->curve_keys[0], sizeof(float3)*oldcurve_keys.size()) != 0)
+ rebuild = true;
+ }
+
+ if(oldcurve_radius.size() != mesh->curve_radius.size())
+ rebuild = true;
+ else if(oldcurve_radius.size()) {
+ if(memcmp(&oldcurve_radius[0], &mesh->curve_radius[0], sizeof(float)*oldcurve_radius.size()) != 0)
rebuild = true;
}
@@ -903,9 +1081,14 @@ void BlenderSync::sync_mesh_motion(BL::Object& b_ob,
* 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_scene, true, !preview, false);
+ b_mesh = object_to_mesh(b_data, b_ob, b_scene, true, !preview, false, false);
}
if(!b_mesh) {
@@ -931,8 +1114,8 @@ void BlenderSync::sync_mesh_motion(BL::Object& b_ob,
Attribute *attr_mP = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
if(attr_mP) {
- float4 *keys = &mesh->curve_keys[0];
- memcpy(attr_mP->data_float4() + time_index*numkeys, keys, sizeof(float4)*numkeys);
+ float3 *keys = &mesh->curve_keys[0];
+ memcpy(attr_mP->data_float3() + time_index*numkeys, keys, sizeof(float3)*numkeys);
}
}
@@ -1006,7 +1189,7 @@ void BlenderSync::sync_mesh_motion(BL::Object& b_ob,
sync_curves(mesh, b_mesh, b_ob, true, time_index);
/* free derived mesh */
- b_data.meshes.remove(b_mesh);
+ b_data.meshes.remove(b_mesh, false);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp
index 80768c096e3..4886735a18f 100644
--- a/intern/cycles/blender/blender_object.cpp
+++ b/intern/cycles/blender/blender_object.cpp
@@ -253,11 +253,20 @@ static bool object_boundbox_clip(Scene *scene,
boundbox[3 * i + 1],
boundbox[3 * i + 2]);
p = transform_point(&tfm, p);
- p = transform_point(&worldtondc, p);
- if(p.z >= -margin) {
+
+ 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 >= -margin) {
all_behind = false;
}
- p /= p.z;
bb_min = min(bb_min, p);
bb_max = max(bb_max, p);
}
@@ -720,12 +729,7 @@ void BlenderSync::sync_motion(BL::RenderSettings& b_render,
<< relative_time << ".";
/* fixed shutter time to get previous and next frame for motion pass */
- float shuttertime;
-
- if(scene->need_motion() == Scene::MOTION_PASS)
- shuttertime = 2.0f;
- else
- shuttertime = scene->camera->shuttertime;
+ float shuttertime = scene->motion_shutter_time();
/* compute frame and subframe time */
float time = frame_center + frame_center_delta + relative_time * shuttertime * 0.5f;
diff --git a/intern/cycles/blender/blender_particles.cpp b/intern/cycles/blender/blender_particles.cpp
index d1e702cfdc2..b9876cd604f 100644
--- a/intern/cycles/blender/blender_particles.cpp
+++ b/intern/cycles/blender/blender_particles.cpp
@@ -76,7 +76,7 @@ bool BlenderSync::sync_dupli_particle(BL::Object& b_ob,
pa.velocity = get_float3(b_pa.velocity());
pa.angular_velocity = get_float3(b_pa.angular_velocity());
- psys->particles.push_back(pa);
+ psys->particles.push_back_slow(pa);
if(object->particle_index != psys->particles.size() - 1)
scene->object_manager->tag_update(scene);
diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp
index d2cd9307bab..7b8317a50a7 100644
--- a/intern/cycles/blender/blender_shader.cpp
+++ b/intern/cycles/blender/blender_shader.cpp
@@ -127,82 +127,60 @@ static float3 get_node_output_vector(BL::Node& b_node, const string& name)
return make_float3(value[0], value[1], value[2]);
}
-static ShaderSocketType 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 SHADER_SOCKET_FLOAT;
+ return SocketType::FLOAT;
case BL::NodeSocket::type_INT:
- return SHADER_SOCKET_INT;
+ return SocketType::INT;
case BL::NodeSocket::type_VECTOR:
- return SHADER_SOCKET_VECTOR;
+ return SocketType::VECTOR;
case BL::NodeSocket::type_RGBA:
- return SHADER_SOCKET_COLOR;
+ return SocketType::COLOR;
case BL::NodeSocket::type_STRING:
- return SHADER_SOCKET_STRING;
+ return SocketType::STRING;
case BL::NodeSocket::type_SHADER:
- return SHADER_SOCKET_CLOSURE;
+ return SocketType::CLOSURE;
default:
- return SHADER_SOCKET_UNDEFINED;
+ return SocketType::UNDEFINED;
}
}
-#ifdef WITH_OSL
-static ShaderSocketType convert_osl_socket_type(OSL::OSLQuery& query,
- BL::NodeSocket& b_socket)
-{
- ShaderSocketType socket_type = convert_socket_type(b_socket);
- if(socket_type == SHADER_SOCKET_VECTOR) {
- /* TODO(sergey): Do we need compatible_name() here? */
- const OSL::OSLQuery::Parameter *param = query.getparam(b_socket.name());
- assert(param != NULL);
- if(param != NULL) {
- if(param->type.vecsemantics == TypeDesc::POINT) {
- socket_type = SHADER_SOCKET_POINT;
- }
- else if(param->type.vecsemantics == TypeDesc::NORMAL) {
- socket_type = SHADER_SOCKET_NORMAL;
- }
- }
- }
-
- return socket_type;
-}
-#endif /* WITH_OSL */
-
static void set_default_value(ShaderInput *input,
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 SHADER_SOCKET_FLOAT: {
- input->set(get_float(b_sock.ptr, "default_value"));
+ switch(input->type()) {
+ case SocketType::FLOAT: {
+ node->set(socket, get_float(b_sock.ptr, "default_value"));
break;
}
- case SHADER_SOCKET_INT: {
- input->set((float)get_int(b_sock.ptr, "default_value"));
+ case SocketType::INT: {
+ node->set(socket, get_int(b_sock.ptr, "default_value"));
break;
}
- case SHADER_SOCKET_COLOR: {
- input->set(float4_to_float3(get_float4(b_sock.ptr, "default_value")));
+ case SocketType::COLOR: {
+ node->set(socket, float4_to_float3(get_float4(b_sock.ptr, "default_value")));
break;
}
- case SHADER_SOCKET_NORMAL:
- case SHADER_SOCKET_POINT:
- case SHADER_SOCKET_VECTOR: {
- input->set(get_float3(b_sock.ptr, "default_value"));
+ case SocketType::NORMAL:
+ case SocketType::POINT:
+ case SocketType::VECTOR: {
+ node->set(socket, get_float3(b_sock.ptr, "default_value"));
break;
}
- case SHADER_SOCKET_STRING: {
- input->set((ustring)blender_absolute_path(b_data, b_id, get_string(b_sock.ptr, "default_value")));
+ case SocketType::STRING: {
+ node->set(socket, (ustring)blender_absolute_path(b_data, b_id, get_string(b_sock.ptr, "default_value")));
break;
}
-
- case SHADER_SOCKET_CLOSURE:
- case SHADER_SOCKET_UNDEFINED:
+ default:
break;
}
}
@@ -315,7 +293,7 @@ static ShaderNode *add_node(Scene *scene,
else if(b_node.is_a(&RNA_ShaderNodeMixRGB)) {
BL::ShaderNodeMixRGB b_mix_node(b_node);
MixNode *mix = new MixNode();
- mix->type = MixNode::type_enum[b_mix_node.blend_type()];
+ mix->type = (NodeMix)b_mix_node.blend_type();
mix->use_clamp = b_mix_node.use_clamp();
node = mix;
}
@@ -341,27 +319,27 @@ static ShaderNode *add_node(Scene *scene,
node = new HSVNode();
}
else if(b_node.is_a(&RNA_ShaderNodeRGBToBW)) {
- node = new ConvertNode(SHADER_SOCKET_COLOR, SHADER_SOCKET_FLOAT);
+ node = new RGBToBWNode();
}
else if(b_node.is_a(&RNA_ShaderNodeMath)) {
BL::ShaderNodeMath b_math_node(b_node);
MathNode *math = new MathNode();
- math->type = MathNode::type_enum[b_math_node.operation()];
+ 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 = VectorMathNode::type_enum[b_vector_math_node.operation()];
+ 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 = VectorTransformNode::type_enum[b_vector_transform_node.vector_type()];
- vtransform->convert_from = VectorTransformNode::convert_space_enum[b_vector_transform_node.convert_from()];
- vtransform->convert_to = VectorTransformNode::convert_space_enum[b_vector_transform_node.convert_to()];
+ 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)) {
@@ -410,13 +388,16 @@ static ShaderNode *add_node(Scene *scene,
switch(b_aniso_node.distribution()) {
case BL::ShaderNodeBsdfAnisotropic::distribution_BECKMANN:
- aniso->distribution = ustring("Beckmann");
+ aniso->distribution = CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID;
break;
case BL::ShaderNodeBsdfAnisotropic::distribution_GGX:
- aniso->distribution = ustring("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 = ustring("Ashikhmin-Shirley");
+ aniso->distribution = CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID;
break;
}
@@ -432,13 +413,13 @@ static ShaderNode *add_node(Scene *scene,
switch(b_subsurface_node.falloff()) {
case BL::ShaderNodeSubsurfaceScattering::falloff_CUBIC:
- subsurface->closure = CLOSURE_BSSRDF_CUBIC_ID;
+ subsurface->falloff = CLOSURE_BSSRDF_CUBIC_ID;
break;
case BL::ShaderNodeSubsurfaceScattering::falloff_GAUSSIAN:
- subsurface->closure = CLOSURE_BSSRDF_GAUSSIAN_ID;
+ subsurface->falloff = CLOSURE_BSSRDF_GAUSSIAN_ID;
break;
case BL::ShaderNodeSubsurfaceScattering::falloff_BURLEY:
- subsurface->closure = CLOSURE_BSSRDF_BURLEY_ID;
+ subsurface->falloff = CLOSURE_BSSRDF_BURLEY_ID;
break;
}
@@ -450,16 +431,19 @@ static ShaderNode *add_node(Scene *scene,
switch(b_glossy_node.distribution()) {
case BL::ShaderNodeBsdfGlossy::distribution_SHARP:
- glossy->distribution = ustring("Sharp");
+ glossy->distribution = CLOSURE_BSDF_REFLECTION_ID;
break;
case BL::ShaderNodeBsdfGlossy::distribution_BECKMANN:
- glossy->distribution = ustring("Beckmann");
+ glossy->distribution = CLOSURE_BSDF_MICROFACET_BECKMANN_ID;
break;
case BL::ShaderNodeBsdfGlossy::distribution_GGX:
- glossy->distribution = ustring("GGX");
+ glossy->distribution = CLOSURE_BSDF_MICROFACET_GGX_ID;
break;
case BL::ShaderNodeBsdfGlossy::distribution_ASHIKHMIN_SHIRLEY:
- glossy->distribution = ustring("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;
@@ -469,13 +453,16 @@ static ShaderNode *add_node(Scene *scene,
GlassBsdfNode *glass = new GlassBsdfNode();
switch(b_glass_node.distribution()) {
case BL::ShaderNodeBsdfGlass::distribution_SHARP:
- glass->distribution = ustring("Sharp");
+ glass->distribution = CLOSURE_BSDF_SHARP_GLASS_ID;
break;
case BL::ShaderNodeBsdfGlass::distribution_BECKMANN:
- glass->distribution = ustring("Beckmann");
+ glass->distribution = CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID;
break;
case BL::ShaderNodeBsdfGlass::distribution_GGX:
- glass->distribution = ustring("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;
@@ -485,13 +472,13 @@ static ShaderNode *add_node(Scene *scene,
RefractionBsdfNode *refraction = new RefractionBsdfNode();
switch(b_refraction_node.distribution()) {
case BL::ShaderNodeBsdfRefraction::distribution_SHARP:
- refraction->distribution = ustring("Sharp");
+ refraction->distribution = CLOSURE_BSDF_REFRACTION_ID;
break;
case BL::ShaderNodeBsdfRefraction::distribution_BECKMANN:
- refraction->distribution = ustring("Beckmann");
+ refraction->distribution = CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
break;
case BL::ShaderNodeBsdfRefraction::distribution_GGX:
- refraction->distribution = ustring("GGX");
+ refraction->distribution = CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
break;
}
node = refraction;
@@ -501,10 +488,10 @@ static ShaderNode *add_node(Scene *scene,
ToonBsdfNode *toon = new ToonBsdfNode();
switch(b_toon_node.component()) {
case BL::ShaderNodeBsdfToon::component_DIFFUSE:
- toon->component = ustring("Diffuse");
+ toon->component = CLOSURE_BSDF_DIFFUSE_TOON_ID;
break;
case BL::ShaderNodeBsdfToon::component_GLOSSY:
- toon->component = ustring("Glossy");
+ toon->component = CLOSURE_BSDF_GLOSSY_TOON_ID;
break;
}
node = toon;
@@ -514,10 +501,10 @@ static ShaderNode *add_node(Scene *scene,
HairBsdfNode *hair = new HairBsdfNode();
switch(b_hair_node.component()) {
case BL::ShaderNodeBsdfHair::component_Reflection:
- hair->component = ustring("Reflection");
+ hair->component = CLOSURE_BSDF_HAIR_REFLECTION_ID;
break;
case BL::ShaderNodeBsdfHair::component_Transmission:
- hair->component = ustring("Transmission");
+ hair->component = CLOSURE_BSDF_HAIR_TRANSMISSION_ID;
break;
}
node = hair;
@@ -587,62 +574,17 @@ static ShaderNode *add_node(Scene *scene,
if(scene->shader_manager->use_osl()) {
/* create script node */
BL::ShaderNodeScript b_script_node(b_node);
- OSLScriptNode *script_node = new OSLScriptNode();
OSLShaderManager *manager = (OSLShaderManager*)scene->shader_manager;
string bytecode_hash = b_script_node.bytecode_hash();
- /* Gather additional information from the shader, such as
- * input/output type info needed for proper node construction.
- */
- OSL::OSLQuery query;
- string absolute_filepath;
-
if(!bytecode_hash.empty()) {
- query.open_bytecode(b_script_node.bytecode());
+ node = manager->osl_node("", bytecode_hash, b_script_node.bytecode());
}
else {
- absolute_filepath = blender_absolute_path(b_data, b_ntree, b_script_node.filepath());
- OSLShaderManager::osl_query(query, absolute_filepath);
- }
- /* TODO(sergey): Add proper query info error parsing. */
-
- /* Generate inputs/outputs from node sockets
- *
- * Note: the node sockets are generated from OSL parameters,
- * so the names match those of the corresponding parameters exactly.
- *
- * Note 2: ShaderInput/ShaderOutput store shallow string copies only!
- * So we register them as ustring to ensure the pointer stays valid. */
- BL::Node::inputs_iterator b_input;
-
- for(b_script_node.inputs.begin(b_input); b_input != b_script_node.inputs.end(); ++b_input) {
- ShaderInput *input = script_node->add_input(ustring(b_input->name()).c_str(),
- convert_osl_socket_type(query, *b_input));
- set_default_value(input, *b_input, b_data, b_ntree);
- }
-
- BL::Node::outputs_iterator b_output;
-
- for(b_script_node.outputs.begin(b_output); b_output != b_script_node.outputs.end(); ++b_output) {
- script_node->add_output(ustring(b_output->name()).c_str(),
- convert_osl_socket_type(query, *b_output));
+ string absolute_filepath = blender_absolute_path(b_data, b_ntree, b_script_node.filepath());
+ node = manager->osl_node(absolute_filepath, "");
}
-
- /* load bytecode or filepath */
- if(!bytecode_hash.empty()) {
- /* loaded bytecode if not already done */
- if(!manager->shader_test_loaded(bytecode_hash))
- manager->shader_load_bytecode(bytecode_hash, b_script_node.bytecode());
-
- script_node->bytecode_hash = bytecode_hash;
- }
- else {
- /* set filepath */
- script_node->filepath = absolute_filepath;
- }
-
- node = script_node;
}
#else
(void)b_data;
@@ -689,14 +631,14 @@ static ShaderNode *add_node(Scene *scene,
/* TODO(sergey): Does not work properly when we change builtin type. */
if(b_image.is_updated()) {
scene->image_manager->tag_reload_image(
- image->filename,
+ image->filename.string(),
image->builtin_data,
get_image_interpolation(b_image_node),
get_image_extension(b_image_node));
}
}
- image->color_space = ImageTextureNode::color_space_enum[(int)b_image_node.color_space()];
- image->projection = ImageTextureNode::projection_enum[(int)b_image_node.projection()];
+ 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();
@@ -735,15 +677,15 @@ static ShaderNode *add_node(Scene *scene,
/* TODO(sergey): Does not work properly when we change builtin type. */
if(b_image.is_updated()) {
scene->image_manager->tag_reload_image(
- env->filename,
+ env->filename.string(),
env->builtin_data,
get_image_interpolation(b_env_node),
EXTENSION_REPEAT);
}
}
- env->color_space = EnvironmentTextureNode::color_space_enum[(int)b_env_node.color_space()];
+ env->color_space = (NodeImageColorSpace)b_env_node.color_space();
env->interpolation = get_image_interpolation(b_env_node);
- env->projection = EnvironmentTextureNode::projection_enum[(int)b_env_node.projection()];
+ 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;
@@ -751,7 +693,7 @@ static ShaderNode *add_node(Scene *scene,
else if(b_node.is_a(&RNA_ShaderNodeTexGradient)) {
BL::ShaderNodeTexGradient b_gradient_node(b_node);
GradientTextureNode *gradient = new GradientTextureNode();
- gradient->type = GradientTextureNode::type_enum[(int)b_gradient_node.gradient_type()];
+ 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;
@@ -759,7 +701,7 @@ static ShaderNode *add_node(Scene *scene,
else if(b_node.is_a(&RNA_ShaderNodeTexVoronoi)) {
BL::ShaderNodeTexVoronoi b_voronoi_node(b_node);
VoronoiTextureNode *voronoi = new VoronoiTextureNode();
- voronoi->coloring = VoronoiTextureNode::coloring_enum[(int)b_voronoi_node.coloring()];
+ voronoi->coloring = (NodeVoronoiColoring)b_voronoi_node.coloring();
BL::TexMapping b_texture_mapping(b_voronoi_node.texture_mapping());
get_tex_mapping(&voronoi->tex_mapping, b_texture_mapping);
node = voronoi;
@@ -775,8 +717,8 @@ static ShaderNode *add_node(Scene *scene,
else if(b_node.is_a(&RNA_ShaderNodeTexWave)) {
BL::ShaderNodeTexWave b_wave_node(b_node);
WaveTextureNode *wave = new WaveTextureNode();
- wave->type = WaveTextureNode::type_enum[(int)b_wave_node.wave_type()];
- wave->profile = WaveTextureNode::profile_enum[(int)b_wave_node.wave_profile()];
+ 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;
@@ -809,7 +751,7 @@ static ShaderNode *add_node(Scene *scene,
else if(b_node.is_a(&RNA_ShaderNodeTexMusgrave)) {
BL::ShaderNodeTexMusgrave b_musgrave_node(b_node);
MusgraveTextureNode *musgrave = new MusgraveTextureNode();
- musgrave->type = MusgraveTextureNode::type_enum[(int)b_musgrave_node.musgrave_type()];
+ 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;
@@ -827,7 +769,7 @@ static ShaderNode *add_node(Scene *scene,
else if(b_node.is_a(&RNA_ShaderNodeTexSky)) {
BL::ShaderNodeTexSky b_sky_node(b_node);
SkyTextureNode *sky = new SkyTextureNode();
- sky->type = SkyTextureNode::type_enum[(int)b_sky_node.sky_type()];
+ 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();
@@ -838,15 +780,15 @@ static ShaderNode *add_node(Scene *scene,
else if(b_node.is_a(&RNA_ShaderNodeNormalMap)) {
BL::ShaderNodeNormalMap b_normal_map_node(b_node);
NormalMapNode *nmap = new NormalMapNode();
- nmap->space = NormalMapNode::space_enum[(int)b_normal_map_node.space()];
+ 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 = TangentNode::direction_type_enum[(int)b_tangent_node.direction_type()];
- tangent->axis = TangentNode::axis_enum[(int)b_tangent_node.axis()];
+ 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;
}
@@ -861,8 +803,7 @@ static ShaderNode *add_node(Scene *scene,
BL::ShaderNodeTexPointDensity b_point_density_node(b_node);
PointDensityTextureNode *point_density = new PointDensityTextureNode();
point_density->filename = b_point_density_node.name();
- point_density->space =
- PointDensityTextureNode::space_enum[(int)b_point_density_node.space()];
+ 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;
@@ -873,7 +814,7 @@ static ShaderNode *add_node(Scene *scene,
if(true) {
b_point_density_node.cache_point_density(b_scene, settings);
scene->image_manager->tag_reload_image(
- point_density->filename,
+ point_density->filename.string(),
point_density->builtin_data,
point_density->interpolation,
EXTENSION_CLIP);
@@ -1023,7 +964,7 @@ static void add_nodes(Scene *scene,
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());
- ShaderSocketType to_socket_type = convert_socket_type(to_socket);
+ SocketType::Type to_socket_type = convert_socket_type(to_socket);
ConvertNode *proxy = new ConvertNode(to_socket_type, to_socket_type, true);
input_map[b_link->from_socket().ptr.data] = proxy->inputs[0];
@@ -1046,7 +987,7 @@ static void add_nodes(Scene *scene,
* 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) {
- ShaderSocketType input_type = convert_socket_type(*b_input);
+ SocketType::Type input_type = convert_socket_type(*b_input);
ConvertNode *proxy = new ConvertNode(input_type, input_type, true);
graph->add(proxy);
@@ -1058,7 +999,7 @@ static void add_nodes(Scene *scene,
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) {
- ShaderSocketType output_type = convert_socket_type(*b_output);
+ SocketType::Type output_type = convert_socket_type(*b_output);
ConvertNode *proxy = new ConvertNode(output_type, output_type, true);
graph->add(proxy);
@@ -1227,13 +1168,12 @@ void BlenderSync::sync_materials(bool update_all)
add_nodes(scene, b_engine, b_data, b_scene, !preview, graph, b_ntree);
}
else {
- ShaderNode *closure, *out;
-
- closure = graph->add(new DiffuseBsdfNode());
- closure->input("Color")->value = get_float3(b_mat->diffuse_color());
- out = graph->output();
+ DiffuseBsdfNode *diffuse = new DiffuseBsdfNode();
+ diffuse->color = get_float3(b_mat->diffuse_color());
+ graph->add(diffuse);
- graph->connect(closure->output("BSDF"), out->input("Surface"));
+ ShaderNode *out = graph->output();
+ graph->connect(diffuse->output("BSDF"), out->input("Surface"));
}
/* settings */
@@ -1276,13 +1216,12 @@ void BlenderSync::sync_world(bool update_all)
shader->volume_interpolation_method = get_volume_interpolation(cworld);
}
else if(b_world) {
- ShaderNode *closure, *out;
-
- closure = graph->add(new BackgroundNode());
- closure->input("Color")->value = get_float3(b_world.horizon_color());
- out = graph->output();
+ BackgroundNode *background = new BackgroundNode();
+ background->color = get_float3(b_world.horizon_color());
+ graph->add(background);
- graph->connect(closure->output("Background"), out->input("Surface"));
+ ShaderNode *out = graph->output();
+ graph->connect(background->output("Background"), out->input("Surface"));
}
if(b_world) {
@@ -1361,7 +1300,6 @@ void BlenderSync::sync_lamps(bool update_all)
add_nodes(scene, b_engine, b_data, b_scene, !preview, graph, b_ntree);
}
else {
- ShaderNode *closure, *out;
float strength = 1.0f;
if(b_lamp->type() == BL::Lamp::type_POINT ||
@@ -1371,12 +1309,13 @@ void BlenderSync::sync_lamps(bool update_all)
strength = 100.0f;
}
- closure = graph->add(new EmissionNode());
- closure->input("Color")->value = get_float3(b_lamp->color());
- closure->input("Strength")->value.x = strength;
- out = graph->output();
+ EmissionNode *emission = new EmissionNode();
+ emission->color = get_float3(b_lamp->color());
+ emission->strength = strength;
+ graph->add(emission);
- graph->connect(closure->output("Emission"), out->input("Surface"));
+ ShaderNode *out = graph->output();
+ graph->connect(emission->output("Emission"), out->input("Surface"));
}
shader->set_graph(graph);
diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp
index 33084f1c163..e7e57b2be36 100644
--- a/intern/cycles/blender/blender_sync.cpp
+++ b/intern/cycles/blender/blender_sync.cpp
@@ -492,6 +492,7 @@ SceneParams BlenderSync::get_scene_params(BL::Scene& b_scene,
SceneParams::BVH_STATIC);
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");
if(background && params.shadingsystem != SHADINGSYSTEM_OSL)
params.persistent_data = r.use_persistent_data();
diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h
index d690adb5662..b8b9597914e 100644
--- a/intern/cycles/blender/blender_sync.h
+++ b/intern/cycles/blender/blender_sync.h
@@ -131,7 +131,9 @@ private:
Transform& tfm,
bool *use_portal);
void sync_background_light(bool use_portal);
- void sync_mesh_motion(BL::Object& b_ob, Object *object, float motion_time);
+ void sync_mesh_motion(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,
diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h
index e23d8bf4e2d..d5dbaba094b 100644
--- a/intern/cycles/blender/blender_util.h
+++ b/intern/cycles/blender/blender_util.h
@@ -45,14 +45,39 @@ static inline BL::Mesh object_to_mesh(BL::BlendData& data,
BL::Scene& scene,
bool apply_modifiers,
bool render,
- bool calc_undeformed)
+ bool calc_undeformed,
+ bool subdivision)
{
+ bool subsurf_mod_show_render;
+ bool subsurf_mod_show_viewport;
+
+ if(subdivision) {
+ 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_render();
+
+ subsurf_mod.show_render(false);
+ subsurf_mod.show_viewport(false);
+
+ }
+
BL::Mesh me = data.meshes.new_from_object(scene, object, apply_modifiers, (render)? 2: 1, false, calc_undeformed);
+
+ if(subdivision) {
+ 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);
+ }
+
if((bool)me) {
if(me.use_auto_smooth()) {
me.calc_normals_split();
}
- me.calc_tessface(true);
+ if(!subdivision) {
+ me.calc_tessface(true);
+ }
}
return me;
}
@@ -98,11 +123,12 @@ static inline void curvemapping_minmax(/*const*/ BL::CurveMapping& cumap,
}
static inline void curvemapping_to_array(BL::CurveMapping& cumap,
- float *data,
+ 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);
@@ -518,6 +544,23 @@ static inline BL::SmokeDomainSettings object_smoke_domain_find(BL::Object& b_ob)
return BL::SmokeDomainSettings(PointerRNA_NULL);
}
+static inline BL::DomainFluidSettings object_fluid_domain_find(BL::Object b_ob)
+{
+ 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();
+
+ if(fss.type() == BL::FluidSettings::type_DOMAIN)
+ return (BL::DomainFluidSettings)b_fmd.settings();
+ }
+ }
+
+ return BL::DomainFluidSettings(PointerRNA_NULL);
+}
+
/* ID Map
*
* Utility class to keep in sync with blender data.
diff --git a/intern/cycles/bvh/CMakeLists.txt b/intern/cycles/bvh/CMakeLists.txt
index 5729fa6113d..92e48f0d87f 100644
--- a/intern/cycles/bvh/CMakeLists.txt
+++ b/intern/cycles/bvh/CMakeLists.txt
@@ -19,6 +19,7 @@ set(SRC
bvh_node.cpp
bvh_sort.cpp
bvh_split.cpp
+ bvh_unaligned.cpp
)
set(SRC_HEADERS
@@ -29,6 +30,7 @@ set(SRC_HEADERS
bvh_params.h
bvh_sort.h
bvh_split.h
+ bvh_unaligned.h
)
include_directories(${INC})
diff --git a/intern/cycles/bvh/bvh.cpp b/intern/cycles/bvh/bvh.cpp
index 5c474c8c3e9..1bb3e95c810 100644
--- a/intern/cycles/bvh/bvh.cpp
+++ b/intern/cycles/bvh/bvh.cpp
@@ -24,6 +24,7 @@
#include "bvh_build.h"
#include "bvh_node.h"
#include "bvh_params.h"
+#include "bvh_unaligned.h"
#include "util_debug.h"
#include "util_foreach.h"
@@ -121,57 +122,66 @@ void BVH::refit(Progress& progress)
/* Triangles */
-void BVH::pack_triangle(int idx, float4 storage[3])
+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];
- const int *vidx = mesh->triangles[tidx].v;
- const float3* vpos = &mesh->verts[0];
- float3 v0 = vpos[vidx[0]];
- float3 v1 = vpos[vidx[1]];
- float3 v2 = vpos[vidx[2]];
-
- storage[0] = float3_to_float4(v0);
- storage[1] = float3_to_float4(v1);
- storage[2] = float3_to_float4(v2);
+ 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()
{
- int nsize = TRI_NODE_SIZE;
- size_t tidx_size = pack.prim_index.size();
-
- pack.tri_storage.clear();
- pack.tri_storage.resize(tidx_size * nsize);
+ 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) {
- float4 storage[3];
+ int tob = pack.prim_object[i];
+ Object *ob = objects[tob];
- if(pack.prim_type[i] & PRIMITIVE_TRIANGLE) {
- pack_triangle(i, storage);
+ 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 {
- /* Avoid use of uninitialized memory. */
- memset(&storage, 0, sizeof(storage));
+ pack.prim_tri_index[i] = -1;
}
- memcpy(&pack.tri_storage[i * nsize], storage, sizeof(float4)*3);
-
- int tob = pack.prim_object[i];
- Object *ob = objects[tob];
pack.prim_visibility[i] = ob->visibility;
if(pack.prim_type[i] & PRIMITIVE_ALL_CURVE)
pack.prim_visibility[i] |= PATH_RAY_CURVE;
}
else {
- memset(&pack.tri_storage[i * nsize], 0, sizeof(float4)*3);
+ pack.prim_tri_index[i] = -1;
pack.prim_visibility[i] = 0;
}
}
@@ -183,13 +193,13 @@ 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. */
- bool use_qbvh = params.use_qbvh;
- size_t nsize = (use_qbvh)? BVH_QNODE_SIZE: BVH_NODE_SIZE;
- size_t nsize_leaf = (use_qbvh)? BVH_QNODE_LEAF_SIZE: BVH_NODE_LEAF_SIZE;
+ * top level BVH, adjusting indexes and offsets where appropriate.
+ */
+ const bool use_qbvh = params.use_qbvh;
- /* adjust primitive index to point to the triangle in the global array, for
- * meshes with transform applied and already in the top level BVH */
+ /* 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)
@@ -208,10 +218,10 @@ void BVH::pack_instances(size_t nodes_size, size_t leaf_nodes_size)
/* reserve */
size_t prim_index_size = pack.prim_index.size();
- size_t tri_storage_size = pack.tri_storage.size();
+ size_t prim_tri_verts_size = pack.prim_tri_verts.size();
size_t pack_prim_index_offset = prim_index_size;
- size_t pack_tri_storage_offset = tri_storage_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;
@@ -225,7 +235,7 @@ void BVH::pack_instances(size_t nodes_size, size_t leaf_nodes_size)
if(mesh->need_build_bvh()) {
if(mesh_map.find(mesh) == mesh_map.end()) {
prim_index_size += bvh->pack.prim_index.size();
- tri_storage_size += bvh->pack.tri_storage.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();
@@ -240,7 +250,8 @@ void BVH::pack_instances(size_t nodes_size, size_t leaf_nodes_size)
pack.prim_type.resize(prim_index_size);
pack.prim_object.resize(prim_index_size);
pack.prim_visibility.resize(prim_index_size);
- pack.tri_storage.resize(tri_storage_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());
@@ -249,7 +260,8 @@ void BVH::pack_instances(size_t nodes_size, size_t leaf_nodes_size)
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_tri_storage = (pack.tri_storage.size())? &pack.tri_storage[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;
@@ -277,8 +289,8 @@ void BVH::pack_instances(size_t nodes_size, size_t leaf_nodes_size)
BVH *bvh = mesh->bvh;
- int noffset = nodes_offset/nsize;
- int noffset_leaf = nodes_leaf_offset/nsize_leaf;
+ int noffset = nodes_offset;
+ int noffset_leaf = nodes_leaf_offset;
int mesh_tri_offset = mesh->tri_offset;
int mesh_curve_offset = mesh->curve_offset;
@@ -290,18 +302,24 @@ void BVH::pack_instances(size_t nodes_size, size_t leaf_nodes_size)
mesh_map[mesh] = pack.object_node[object_offset-1];
- /* merge primitive and object indexes */
+ /* 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];
for(size_t i = 0; i < bvh_prim_index_size; i++) {
- if(bvh->pack.prim_type[i] & PRIMITIVE_ALL_CURVE)
+ if(bvh->pack.prim_type[i] & PRIMITIVE_ALL_CURVE) {
pack_prim_index[pack_prim_index_offset] = bvh_prim_index[i] + mesh_curve_offset;
- else
+ 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];
@@ -310,50 +328,64 @@ void BVH::pack_instances(size_t nodes_size, size_t leaf_nodes_size)
}
}
- /* merge triangle intersection data */
- if(bvh->pack.tri_storage.size()) {
- memcpy(pack_tri_storage + pack_tri_storage_offset,
- &bvh->pack.tri_storage[0],
- bvh->pack.tri_storage.size()*sizeof(float4));
- pack_tri_storage_offset += bvh->pack.tri_storage.size();
+ /* 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+=nsize_leaf, j++) {
+ 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 < nsize_leaf; ++j) {
+ 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 += nsize_leaf;
+ pack_leaf_nodes_offset += BVH_NODE_LEAF_SIZE;
}
}
if(bvh->pack.nodes.size()) {
- /* For QBVH we're packing a child bbox into 6 float4,
- * and for regular BVH they're packed into 3 float4.
- */
- size_t nsize_bbox = (use_qbvh)? 6: 3;
int4 *bvh_nodes = &bvh->pack.nodes[0];
- size_t bvh_nodes_size = bvh->pack.nodes.size();
+ 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) {
+ nsize = use_qbvh
+ ? BVH_UNALIGNED_QNODE_SIZE
+ : BVH_UNALIGNED_NODE_SIZE;
+ nsize_bbox = (use_qbvh)? 13: 0;
+ }
+ else {
+ nsize = (use_qbvh)? BVH_QNODE_SIZE: BVH_NODE_SIZE;
+ nsize_bbox = (use_qbvh)? 7: 0;
+ }
- for(size_t i = 0, j = 0; i < bvh_nodes_size; i+=nsize, j++) {
- memcpy(pack_nodes + pack_nodes_offset, bvh_nodes + i, nsize_bbox*sizeof(int4));
+ memcpy(pack_nodes + pack_nodes_offset,
+ bvh_nodes + i,
+ nsize_bbox*sizeof(int4));
- /* modify offsets into arrays */
+ /* Modify offsets into arrays */
int4 data = bvh_nodes[i + nsize_bbox];
- data.x += (data.x < 0)? -noffset_leaf: noffset;
- data.y += (data.y < 0)? -noffset_leaf: noffset;
+ data.z += (data.z < 0)? -noffset_leaf: noffset;
+ data.w += (data.w < 0)? -noffset_leaf: noffset;
if(use_qbvh) {
- 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;
}
pack_nodes[pack_nodes_offset + nsize_bbox] = data;
@@ -366,6 +398,7 @@ void BVH::pack_instances(size_t nodes_size, size_t leaf_nodes_size)
sizeof(int4) * (nsize - (nsize_bbox+1)));
pack_nodes_offset += nsize;
+ i += nsize;
}
}
@@ -377,12 +410,20 @@ void BVH::pack_instances(size_t nodes_size, size_t leaf_nodes_size)
/* Regular BVH */
+static bool node_bvh_is_unaligned(const BVHNode *node)
+{
+ const BVHNode *node0 = node->get_child(0),
+ *node1 = node->get_child(1);
+ return node0->is_unaligned() || node1->is_unaligned();
+}
+
RegularBVH::RegularBVH(const BVHParams& params_, const vector<Object*>& objects_)
: BVH(params_, objects_)
{
}
-void RegularBVH::pack_leaf(const BVHStackEntry& e, const LeafNode *leaf)
+void RegularBVH::pack_leaf(const BVHStackEntry& e,
+ const LeafNode *leaf)
{
float4 data[BVH_NODE_LEAF_SIZE];
memset(data, 0, sizeof(data));
@@ -401,54 +442,130 @@ void RegularBVH::pack_leaf(const BVHStackEntry& e, const LeafNode *leaf)
data[0].w = __uint_as_float(pack.prim_type[leaf->m_lo]);
}
- memcpy(&pack.leaf_nodes[e.idx * BVH_NODE_LEAF_SIZE], data, sizeof(float4)*BVH_NODE_LEAF_SIZE);
+ memcpy(&pack.leaf_nodes[e.idx], data, sizeof(float4)*BVH_NODE_LEAF_SIZE);
+}
+
+void RegularBVH::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);
+ }
}
-void RegularBVH::pack_inner(const BVHStackEntry& e, const BVHStackEntry& e0, const BVHStackEntry& e1)
+void RegularBVH::pack_aligned_inner(const BVHStackEntry& e,
+ const BVHStackEntry& e0,
+ const BVHStackEntry& e1)
{
- pack_node(e.idx, e0.node->m_bounds, e1.node->m_bounds, e0.encodeIdx(), e1.encodeIdx(), e0.node->m_visibility, e1.node->m_visibility);
+ pack_aligned_node(e.idx,
+ e0.node->m_bounds, e1.node->m_bounds,
+ e0.encodeIdx(), e1.encodeIdx(),
+ e0.node->m_visibility, e1.node->m_visibility);
}
-void RegularBVH::pack_node(int idx, const BoundBox& b0, const BoundBox& b1, int c0, int c1, uint visibility0, uint visibility1)
+void RegularBVH::pack_aligned_node(int idx,
+ const BoundBox& b0,
+ const BoundBox& b1,
+ int c0, int c1,
+ uint visibility0, uint visibility1)
{
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)),
- make_int4(c0, c1, visibility0, visibility1)
};
- memcpy(&pack.nodes[idx * BVH_NODE_SIZE], data, sizeof(int4)*BVH_NODE_SIZE);
+ memcpy(&pack.nodes[idx], data, sizeof(int4)*BVH_NODE_SIZE);
}
-void RegularBVH::pack_nodes(const BVHNode *root)
+void RegularBVH::pack_unaligned_inner(const BVHStackEntry& e,
+ const BVHStackEntry& e0,
+ const BVHStackEntry& e1)
{
- size_t tot_node_size = root->getSubtreeSize(BVH_STAT_NODE_COUNT);
- size_t leaf_node_size = root->getSubtreeSize(BVH_STAT_LEAF_COUNT);
- size_t node_size = tot_node_size - leaf_node_size;
+ pack_unaligned_node(e.idx,
+ e0.node->get_aligned_space(),
+ e1.node->get_aligned_space(),
+ e0.node->m_bounds,
+ e1.node->m_bounds,
+ e0.encodeIdx(), e1.encodeIdx(),
+ e0.node->m_visibility, e1.node->m_visibility);
+}
- /* resize arrays */
- pack.nodes.clear();
+void RegularBVH::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)
+{
+ 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);
+}
- /* for top level BVH, first merge existing BVH's so we know the offsets */
+void RegularBVH::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*BVH_NODE_SIZE,
- leaf_node_size*BVH_NODE_LEAF_SIZE);
+ pack_instances(node_size, num_leaf_nodes*BVH_NODE_LEAF_SIZE);
}
else {
- pack.nodes.resize(node_size*BVH_NODE_SIZE);
- pack.leaf_nodes.resize(leaf_node_size*BVH_NODE_LEAF_SIZE);
+ 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())
+ if(root->is_leaf()) {
stack.push_back(BVHStackEntry(root, nextLeafNodeIdx++));
- else
- stack.push_back(BVHStackEntry(root, nextNodeIdx++));
+ }
+ else {
+ stack.push_back(BVHStackEntry(root, nextNodeIdx));
+ nextNodeIdx += node_bvh_is_unaligned(root)
+ ? BVH_UNALIGNED_NODE_SIZE
+ : BVH_NODE_SIZE;
+ }
while(stack.size()) {
BVHStackEntry e = stack.back();
@@ -456,20 +573,31 @@ void RegularBVH::pack_nodes(const BVHNode *root)
if(e.node->is_leaf()) {
/* leaf node */
- const LeafNode* leaf = reinterpret_cast<const LeafNode*>(e.node);
+ const LeafNode *leaf = reinterpret_cast<const LeafNode*>(e.node);
pack_leaf(e, leaf);
}
else {
/* innner node */
- int idx0 = (e.node->get_child(0)->is_leaf())? (nextLeafNodeIdx++) : (nextNodeIdx++);
- int idx1 = (e.node->get_child(1)->is_leaf())? (nextLeafNodeIdx++) : (nextNodeIdx++);
- stack.push_back(BVHStackEntry(e.node->get_child(0), idx0));
- stack.push_back(BVHStackEntry(e.node->get_child(1), idx1));
+ 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 += node_bvh_is_unaligned(e.node->get_child(i))
+ ? 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;
}
@@ -486,7 +614,7 @@ void RegularBVH::refit_nodes()
void RegularBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility)
{
if(leaf) {
- int4 *data = &pack.leaf_nodes[idx*BVH_NODE_LEAF_SIZE];
+ int4 *data = &pack.leaf_nodes[idx];
int c0 = data[0].x;
int c1 = data[0].y;
/* refit leaf node */
@@ -506,10 +634,10 @@ void RegularBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility
if(pack.prim_type[prim] & PRIMITIVE_ALL_CURVE) {
/* curves */
int str_offset = (params.top_level)? mesh->curve_offset: 0;
- const Mesh::Curve& curve = mesh->curves[pidx - str_offset];
+ 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], bbox);
+ curve.bounds_grow(k, &mesh->curve_keys[0], &mesh->curve_radius[0], bbox);
visibility |= PATH_RAY_CURVE;
@@ -520,17 +648,17 @@ void RegularBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility
if(attr) {
size_t mesh_size = mesh->curve_keys.size();
size_t steps = mesh->motion_steps - 1;
- float4 *key_steps = attr->data_float4();
+ float3 *key_steps = attr->data_float3();
for(size_t i = 0; i < steps; i++)
- curve.bounds_grow(k, key_steps + i*mesh_size, bbox);
+ 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;
- const Mesh::Triangle& triangle = mesh->triangles[pidx - tri_offset];
+ Mesh::Triangle triangle = mesh->get_triangle(pidx - tri_offset);
const float3 *vpos = &mesh->verts[0];
triangle.bounds_grow(vpos, bbox);
@@ -560,14 +688,12 @@ void RegularBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility
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 * BVH_NODE_LEAF_SIZE],
- leaf_data,
- sizeof(float4)*BVH_NODE_LEAF_SIZE);
+ memcpy(&pack.leaf_nodes[idx], leaf_data, sizeof(float4)*BVH_NODE_LEAF_SIZE);
}
else {
- int4 *data = &pack.nodes[idx*BVH_NODE_SIZE];
- int c0 = data[3].x;
- int c1 = data[3].y;
+ int4 *data = &pack.nodes[idx];
+ int c0 = data[0].z;
+ int c1 = data[0].w;
/* refit inner node, set bbox from children */
BoundBox bbox0 = BoundBox::empty, bbox1 = BoundBox::empty;
uint visibility0 = 0, visibility1 = 0;
@@ -575,7 +701,7 @@ void RegularBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility
refit_node((c0 < 0)? -c0-1: c0, (c0 < 0), bbox0, visibility0);
refit_node((c1 < 0)? -c1-1: c1, (c1 < 0), bbox1, visibility1);
- pack_node(idx, bbox0, bbox1, c0, c1, visibility0, visibility1);
+ pack_aligned_node(idx, bbox0, bbox1, c0, c1, visibility0, visibility1);
bbox.grow(bbox0);
bbox.grow(bbox1);
@@ -585,6 +711,33 @@ void RegularBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility
/* QBVH */
+/* Can we avoid this somehow or make more generic?
+ *
+ * Perhaps we can merge nodes in actual tree and make our
+ * life easier all over the place.
+ */
+static bool node_qbvh_is_unaligned(const BVHNode *node)
+{
+ const BVHNode *node0 = node->get_child(0),
+ *node1 = node->get_child(1);
+ bool has_unaligned = false;
+ if(node0->is_leaf()) {
+ has_unaligned |= node0->is_unaligned();
+ }
+ else {
+ has_unaligned |= node0->get_child(0)->is_unaligned();
+ has_unaligned |= node0->get_child(1)->is_unaligned();
+ }
+ if(node1->is_leaf()) {
+ has_unaligned |= node1->is_unaligned();
+ }
+ else {
+ has_unaligned |= node1->get_child(0)->is_unaligned();
+ has_unaligned |= node1->get_child(1)->is_unaligned();
+ }
+ return has_unaligned;
+}
+
QBVH::QBVH(const BVHParams& params_, const vector<Object*>& objects_)
: BVH(params_, objects_)
{
@@ -610,66 +763,153 @@ void QBVH::pack_leaf(const BVHStackEntry& e, const LeafNode *leaf)
data[0].w = __uint_as_float(pack.prim_type[leaf->m_lo]);
}
- memcpy(&pack.leaf_nodes[e.idx * BVH_QNODE_LEAF_SIZE], data, sizeof(float4)*BVH_QNODE_LEAF_SIZE);
+ memcpy(&pack.leaf_nodes[e.idx], data, sizeof(float4)*BVH_QNODE_LEAF_SIZE);
+}
+
+void QBVH::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);
+ }
}
-void QBVH::pack_inner(const BVHStackEntry& e, const BVHStackEntry *en, int num)
+void QBVH::pack_aligned_inner(const BVHStackEntry& e,
+ const BVHStackEntry *en,
+ int num)
{
float4 data[BVH_QNODE_SIZE];
+ memset(data, 0, sizeof(data));
+ data[0].x = __uint_as_float(e.node->m_visibility & ~PATH_RAY_NODE_UNALIGNED);
for(int i = 0; i < num; i++) {
float3 bb_min = en[i].node->m_bounds.min;
float3 bb_max = en[i].node->m_bounds.max;
- data[0][i] = bb_min.x;
- data[1][i] = bb_max.x;
- data[2][i] = bb_min.y;
- data[3][i] = bb_max.y;
- data[4][i] = bb_min.z;
- data[5][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[6][i] = __int_as_float(en[i].encodeIdx());
+ data[7][i] = __int_as_float(en[i].encodeIdx());
}
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[0][i] = FLT_MAX;
- data[1][i] = -FLT_MAX;
+ data[1][i] = FLT_MAX;
+ data[2][i] = -FLT_MAX;
- data[2][i] = FLT_MAX;
- data[3][i] = -FLT_MAX;
+ data[3][i] = FLT_MAX;
+ data[4][i] = -FLT_MAX;
- data[4][i] = FLT_MAX;
- data[5][i] = -FLT_MAX;
+ data[5][i] = FLT_MAX;
+ data[6][i] = -FLT_MAX;
- data[6][i] = __int_as_float(0);
+ data[7][i] = __int_as_float(0);
}
- memcpy(&pack.nodes[e.idx * BVH_QNODE_SIZE], data, sizeof(float4)*BVH_QNODE_SIZE);
+ memcpy(&pack.nodes[e.idx], data, sizeof(float4)*BVH_QNODE_SIZE);
+}
+
+void QBVH::pack_unaligned_inner(const BVHStackEntry& e,
+ const BVHStackEntry *en,
+ int num)
+{
+ float4 data[BVH_UNALIGNED_QNODE_SIZE];
+ memset(data, 0, sizeof(data));
+
+ data[0].x = __uint_as_float(e.node->m_visibility | PATH_RAY_NODE_UNALIGNED);
+
+ for(int i = 0; i < num; i++) {
+ Transform space = BVHUnaligned::compute_node_transform(
+ en[i].node->m_bounds,
+ en[i].node->get_aligned_space());
+
+ 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[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[13][i] = __int_as_float(en[i].encodeIdx());
+ }
+
+ 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 j = 1; j < 13; ++j) {
+ data[j][i] = 0.0f;
+ }
+ data[13][i] = __int_as_float(0);
+ }
+
+ memcpy(&pack.nodes[e.idx], data, sizeof(float4)*BVH_UNALIGNED_QNODE_SIZE);
}
/* Quad SIMD Nodes */
void QBVH::pack_nodes(const BVHNode *root)
{
- size_t tot_node_size = root->getSubtreeSize(BVH_STAT_QNODE_COUNT);
- size_t leaf_node_size = root->getSubtreeSize(BVH_STAT_LEAF_COUNT);
- size_t node_size = tot_node_size - leaf_node_size;
-
- /* resize arrays */
+ /* Calculate size of the arrays required. */
+ const size_t num_nodes = root->getSubtreeSize(BVH_STAT_QNODE_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_QNODE_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 */
+ /* For top level BVH, first merge existing BVH's so we know the offsets. */
if(params.top_level) {
- pack_instances(node_size*BVH_QNODE_SIZE,
- leaf_node_size*BVH_QNODE_LEAF_SIZE);
+ pack_instances(node_size, num_leaf_nodes*BVH_QNODE_LEAF_SIZE);
}
else {
- pack.nodes.resize(node_size*BVH_QNODE_SIZE);
- pack.leaf_nodes.resize(leaf_node_size*BVH_QNODE_LEAF_SIZE);
+ pack.nodes.resize(node_size);
+ pack.leaf_nodes.resize(num_leaf_nodes*BVH_QNODE_LEAF_SIZE);
}
int nextNodeIdx = 0, nextLeafNodeIdx = 0;
@@ -680,7 +920,10 @@ void QBVH::pack_nodes(const BVHNode *root)
stack.push_back(BVHStackEntry(root, nextLeafNodeIdx++));
}
else {
- stack.push_back(BVHStackEntry(root, nextNodeIdx++));
+ stack.push_back(BVHStackEntry(root, nextNodeIdx));
+ nextNodeIdx += node_qbvh_is_unaligned(root)
+ ? BVH_UNALIGNED_QNODE_SIZE
+ : BVH_QNODE_SIZE;
}
while(stack.size()) {
@@ -689,19 +932,17 @@ void QBVH::pack_nodes(const BVHNode *root)
if(e.node->is_leaf()) {
/* leaf node */
- const LeafNode* leaf = reinterpret_cast<const LeafNode*>(e.node);
+ const LeafNode *leaf = reinterpret_cast<const LeafNode*>(e.node);
pack_leaf(e, leaf);
}
else {
- /* inner node */
+ /* Inner node. */
const BVHNode *node = e.node;
const BVHNode *node0 = node->get_child(0);
const BVHNode *node1 = node->get_child(1);
-
- /* collect nodes */
+ /* Collect nodes. */
const BVHNode *nodes[4];
int numnodes = 0;
-
if(node0->is_leaf()) {
nodes[numnodes++] = node0;
}
@@ -709,7 +950,6 @@ void QBVH::pack_nodes(const BVHNode *root)
nodes[numnodes++] = node0->get_child(0);
nodes[numnodes++] = node0->get_child(1);
}
-
if(node1->is_leaf()) {
nodes[numnodes++] = node1;
}
@@ -717,25 +957,26 @@ void QBVH::pack_nodes(const BVHNode *root)
nodes[numnodes++] = node1->get_child(0);
nodes[numnodes++] = node1->get_child(1);
}
-
- /* push entries on the stack */
- for(int i = 0; i < numnodes; i++) {
+ /* Push entries on the stack. */
+ for(int i = 0; i < numnodes; ++i) {
int idx;
if(nodes[i]->is_leaf()) {
idx = nextLeafNodeIdx++;
}
else {
- idx = nextNodeIdx++;
+ idx = nextNodeIdx;
+ nextNodeIdx += node_qbvh_is_unaligned(nodes[i])
+ ? BVH_UNALIGNED_QNODE_SIZE
+ : BVH_QNODE_SIZE;
}
stack.push_back(BVHStackEntry(nodes[i], idx));
}
-
- /* set node */
+ /* Set node. */
pack_inner(e, &stack[stack.size()-numnodes], numnodes);
}
}
-
- /* root index to start traversal at, to handle case of single leaf node */
+ 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;
}
@@ -751,7 +992,7 @@ void QBVH::refit_nodes()
void QBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility)
{
if(leaf) {
- int4 *data = &pack.leaf_nodes[idx*BVH_QNODE_LEAF_SIZE];
+ int4 *data = &pack.leaf_nodes[idx];
int4 c = data[0];
/* Refit leaf node. */
for(int prim = c.x; prim < c.y; prim++) {
@@ -770,10 +1011,10 @@ void QBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility)
if(pack.prim_type[prim] & PRIMITIVE_ALL_CURVE) {
/* Curves. */
int str_offset = (params.top_level)? mesh->curve_offset: 0;
- const Mesh::Curve& curve = mesh->curves[pidx - str_offset];
+ 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], bbox);
+ curve.bounds_grow(k, &mesh->curve_keys[0], &mesh->curve_radius[0], bbox);
visibility |= PATH_RAY_CURVE;
@@ -784,17 +1025,17 @@ void QBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility)
if(attr) {
size_t mesh_size = mesh->curve_keys.size();
size_t steps = mesh->motion_steps - 1;
- float4 *key_steps = attr->data_float4();
+ float3 *key_steps = attr->data_float3();
for(size_t i = 0; i < steps; i++)
- curve.bounds_grow(k, key_steps + i*mesh_size, bbox);
+ 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;
- const Mesh::Triangle& triangle = mesh->triangles[pidx - tri_offset];
+ Mesh::Triangle triangle = mesh->get_triangle(pidx - tri_offset);
const float3 *vpos = &mesh->verts[0];
triangle.bounds_grow(vpos, bbox);
@@ -833,13 +1074,18 @@ void QBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility)
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 * BVH_QNODE_LEAF_SIZE],
- leaf_data,
- sizeof(float4)*BVH_QNODE_LEAF_SIZE);
+ memcpy(&pack.leaf_nodes[idx], leaf_data, sizeof(float4)*BVH_QNODE_LEAF_SIZE);
}
else {
- int4 *data = &pack.nodes[idx*BVH_QNODE_SIZE];
- int4 c = data[6];
+ 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,
@@ -858,21 +1104,62 @@ void QBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility)
}
}
- float4 inner_data[BVH_QNODE_SIZE];
- for(int i = 0; i < 4; ++i) {
- float3 bb_min = child_bbox[i].min;
- float3 bb_max = child_bbox[i].max;
- inner_data[0][i] = bb_min.x;
- inner_data[1][i] = bb_max.x;
- inner_data[2][i] = bb_min.y;
- inner_data[3][i] = bb_max.y;
- inner_data[4][i] = bb_min.z;
- inner_data[5][i] = bb_max.z;
- inner_data[6][i] = __int_as_float(c[i]);
+ /* TODO(sergey): To be de-duplicated with pack_inner(),
+ * but for that need some sort of pack_node(). which operates with
+ * direct data, not stack element.
+ */
+ if(is_unaligned) {
+ Transform aligned_space = transform_identity();
+ float4 inner_data[BVH_UNALIGNED_QNODE_SIZE];
+ inner_data[0] = make_float4(
+ __int_as_float(visibility | PATH_RAY_NODE_UNALIGNED),
+ 0.0f,
+ 0.0f,
+ 0.0f);
+ for(int i = 0; i < 4; ++i) {
+ Transform space = BVHUnaligned::compute_node_transform(
+ child_bbox[i],
+ aligned_space);
+ inner_data[1][i] = space.x.x;
+ inner_data[2][i] = space.x.y;
+ inner_data[3][i] = space.x.z;
+
+ inner_data[4][i] = space.y.x;
+ inner_data[5][i] = space.y.y;
+ inner_data[6][i] = space.y.z;
+
+ inner_data[7][i] = space.z.x;
+ inner_data[8][i] = space.z.y;
+ inner_data[9][i] = space.z.z;
+
+ inner_data[10][i] = space.x.w;
+ inner_data[11][i] = space.y.w;
+ inner_data[12][i] = space.z.w;
+
+ inner_data[13][i] = __int_as_float(c[i]);
+ }
+ memcpy(&pack.nodes[idx], inner_data, sizeof(float4)*BVH_UNALIGNED_QNODE_SIZE);
+ }
+ else {
+ float4 inner_data[BVH_QNODE_SIZE];
+ inner_data[0] = make_float4(
+ __int_as_float(visibility & ~PATH_RAY_NODE_UNALIGNED),
+ 0.0f,
+ 0.0f,
+ 0.0f);
+ for(int i = 0; i < 4; ++i) {
+ float3 bb_min = child_bbox[i].min;
+ float3 bb_max = child_bbox[i].max;
+ inner_data[1][i] = bb_min.x;
+ inner_data[2][i] = bb_max.x;
+ inner_data[3][i] = bb_min.y;
+ inner_data[4][i] = bb_max.y;
+ inner_data[5][i] = bb_min.z;
+ inner_data[6][i] = bb_max.z;
+ inner_data[7][i] = __int_as_float(c[i]);
+ }
+ memcpy(&pack.nodes[idx], inner_data, sizeof(float4)*BVH_QNODE_SIZE);
}
- memcpy(&pack.nodes[idx * BVH_QNODE_SIZE],
- inner_data,
- sizeof(float4)*BVH_QNODE_SIZE);
}
}
diff --git a/intern/cycles/bvh/bvh.h b/intern/cycles/bvh/bvh.h
index 6076c25ca31..16752076f6a 100644
--- a/intern/cycles/bvh/bvh.h
+++ b/intern/cycles/bvh/bvh.h
@@ -35,11 +35,14 @@ class Progress;
#define BVH_NODE_SIZE 4
#define BVH_NODE_LEAF_SIZE 1
-#define BVH_QNODE_SIZE 7
+#define BVH_QNODE_SIZE 8
#define BVH_QNODE_LEAF_SIZE 1
#define BVH_ALIGN 4096
#define TRI_NODE_SIZE 3
+#define BVH_UNALIGNED_NODE_SIZE 7
+#define BVH_UNALIGNED_QNODE_SIZE 14
+
/* Packed BVH
*
* BVH stored as it will be used for traversal on the rendering device. */
@@ -52,8 +55,10 @@ struct PackedBVH {
array<int4> leaf_nodes;
/* object index to BVH node index mapping for instances */
array<int> object_node;
- /* Aligned triangle storage for fatser lookup in the kernel. */
- array<float4> tri_storage;
+ /* 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 */
@@ -91,7 +96,7 @@ public:
protected:
BVH(const BVHParams& params, const vector<Object*>& objects);
- /* triangles and strands*/
+ /* triangles and strands */
void pack_primitives();
void pack_triangle(int idx, float4 storage[3]);
@@ -115,9 +120,32 @@ protected:
/* pack */
void pack_nodes(const BVHNode *root);
- void pack_leaf(const BVHStackEntry& e, const LeafNode *leaf);
- void pack_inner(const BVHStackEntry& e, const BVHStackEntry& e0, const BVHStackEntry& e1);
- void pack_node(int idx, const BoundBox& b0, const BoundBox& b1, int c0, int c1, uint visibility0, uint visibility1);
+
+ 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_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();
@@ -136,9 +164,17 @@ protected:
/* pack */
void pack_nodes(const BVHNode *root);
+
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_unaligned_inner(const BVHStackEntry& e,
+ const BVHStackEntry *en,
+ int num);
+
/* refit */
void refit_nodes();
void refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility);
diff --git a/intern/cycles/bvh/bvh_binning.cpp b/intern/cycles/bvh/bvh_binning.cpp
index b07e870d759..5ddd7349f7b 100644
--- a/intern/cycles/bvh/bvh_binning.cpp
+++ b/intern/cycles/bvh/bvh_binning.cpp
@@ -52,12 +52,35 @@ __forceinline int get_best_dimension(const float4& bestSAH)
/* BVH Object Binning */
-BVHObjectBinning::BVHObjectBinning(const BVHRange& job, BVHReference *prims)
-: BVHRange(job), splitSAH(FLT_MAX), dim(0), pos(0)
+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)
{
+ 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);
+ 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 */
@@ -79,30 +102,34 @@ BVHObjectBinning::BVHObjectBinning(const BVHRange& job, BVHReference *prims)
const BVHReference& prim0 = prims[start() + i + 0];
const BVHReference& prim1 = prims[start() + i + 1];
- int4 bin0 = get_bin(prim0.bounds());
- int4 bin1 = get_bin(prim1.bounds());
+ 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(prim0.bounds());
- int b01 = (int)extract<1>(bin0); bin_count[b01][1]++; bin_bounds[b01][1].grow(prim0.bounds());
- int b02 = (int)extract<2>(bin0); bin_count[b02][2]++; bin_bounds[b02][2].grow(prim0.bounds());
+ 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(prim1.bounds());
- int b11 = (int)extract<1>(bin1); bin_count[b11][1]++; bin_bounds[b11][1].grow(prim1.bounds());
- int b12 = (int)extract<2>(bin1); bin_count[b12][2]++; bin_bounds[b12][2].grow(prim1.bounds());
+ 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];
- int4 bin0 = get_bin(prim0.bounds());
+ 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(prim0.bounds());
- int b01 = (int)extract<1>(bin0); bin_count[b01][1]++; bin_bounds[b01][1].grow(prim0.bounds());
- int b02 = (int)extract<2>(bin0); bin_count[b02][2]++; bin_bounds[b02][2].grow(prim0.bounds());
+ 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);
}
}
@@ -151,17 +178,19 @@ BVHObjectBinning::BVHObjectBinning(const BVHRange& job, BVHReference *prims)
bestSAH = min(sah,bestSAH);
}
- int4 mask = float3_to_float4(cent_bounds().size()) <= make_float4(0.0f);
+ 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());
+ 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();
@@ -176,10 +205,12 @@ void BVHObjectBinning::split(BVHReference* prims, BVHObjectBinning& left_o, BVHO
prefetch_L2(&prims[start() + l + 8]);
prefetch_L2(&prims[start() + r - 8]);
- const BVHReference& prim = prims[start() + l];
+ 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(center)[dim] < pos) {
+ if(get_bin(unaligned_center)[dim] < pos) {
lgeom_bounds.grow(prim.bounds());
lcent_bounds.grow(center);
l++;
@@ -191,7 +222,6 @@ void BVHObjectBinning::split(BVHReference* prims, BVHObjectBinning& left_o, BVHO
r--;
}
}
-
/* finish */
if(l != 0 && N-1-r != 0) {
right_o = BVHObjectBinning(BVHRange(rgeom_bounds, rcent_bounds, start() + l, N-1-r), prims);
diff --git a/intern/cycles/bvh/bvh_binning.h b/intern/cycles/bvh/bvh_binning.h
index 60742157055..52955f70151 100644
--- a/intern/cycles/bvh/bvh_binning.h
+++ b/intern/cycles/bvh/bvh_binning.h
@@ -19,11 +19,14 @@
#define __BVH_BINNING_H__
#include "bvh_params.h"
+#include "bvh_unaligned.h"
#include "util_types.h"
CCL_NAMESPACE_BEGIN
+class BVHBuild;
+
/* Single threaded object binner. Finds the split with the best SAH heuristic
* by testing for each dimension multiple partitionings for regular spaced
* partition locations. A partitioning for a partition location is computed,
@@ -34,10 +37,18 @@ CCL_NAMESPACE_BEGIN
class BVHObjectBinning : public BVHRange
{
public:
- __forceinline BVHObjectBinning() {}
- BVHObjectBinning(const BVHRange& job, BVHReference *prims);
+ __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;
+ 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 */
@@ -48,13 +59,20 @@ protected:
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 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);
@@ -64,7 +82,7 @@ protected:
/* 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));
+ return make_int4((c - cent_bounds_.min)*scale - make_float3(0.5f));
}
/* compute the number of blocks occupied for each dimension. */
@@ -78,6 +96,17 @@ protected:
{
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
diff --git a/intern/cycles/bvh/bvh_build.cpp b/intern/cycles/bvh/bvh_build.cpp
index 76a1bfa2bfe..67ffb6853d6 100644
--- a/intern/cycles/bvh/bvh_build.cpp
+++ b/intern/cycles/bvh/bvh_build.cpp
@@ -33,6 +33,7 @@
#include "util_stack_allocator.h"
#include "util_simd.h"
#include "util_time.h"
+#include "util_queue.h"
CCL_NAMESPACE_BEGIN
@@ -99,7 +100,8 @@ BVHBuild::BVHBuild(const vector<Object*>& objects_,
prim_object(prim_object_),
params(params_),
progress(progress_),
- progress_start_time(0.0)
+ progress_start_time(0.0),
+ unaligned_heuristic(objects_)
{
spatial_min_overlap = 0.0f;
}
@@ -112,68 +114,74 @@ BVHBuild::~BVHBuild()
void BVHBuild::add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh, int i)
{
- Attribute *attr_mP = NULL;
-
- if(mesh->has_motion_blur())
- attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+ if(params.primitive_mask & PRIMITIVE_ALL_TRIANGLE) {
+ Attribute *attr_mP = NULL;
- for(uint j = 0; j < mesh->triangles.size(); j++) {
- Mesh::Triangle t = mesh->triangles[j];
- BoundBox bounds = BoundBox::empty;
- PrimitiveType type = PRIMITIVE_TRIANGLE;
+ if(mesh->has_motion_blur())
+ attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+
+ size_t num_triangles = mesh->num_triangles();
+ for(uint j = 0; j < num_triangles; j++) {
+ Mesh::Triangle t = mesh->get_triangle(j);
+ BoundBox bounds = BoundBox::empty;
+ PrimitiveType type = PRIMITIVE_TRIANGLE;
- t.bounds_grow(&mesh->verts[0], bounds);
+ t.bounds_grow(&mesh->verts[0], bounds);
- /* motion triangles */
- if(attr_mP) {
- size_t mesh_size = mesh->verts.size();
- size_t steps = mesh->motion_steps - 1;
- float3 *vert_steps = attr_mP->data_float3();
+ /* motion triangles */
+ if(attr_mP) {
+ size_t mesh_size = mesh->verts.size();
+ size_t steps = mesh->motion_steps - 1;
+ float3 *vert_steps = attr_mP->data_float3();
- for(size_t i = 0; i < steps; i++)
- t.bounds_grow(vert_steps + i*mesh_size, bounds);
+ for(size_t i = 0; i < steps; i++)
+ t.bounds_grow(vert_steps + i*mesh_size, bounds);
- type = PRIMITIVE_MOTION_TRIANGLE;
- }
+ type = PRIMITIVE_MOTION_TRIANGLE;
+ }
- if(bounds.valid()) {
- references.push_back(BVHReference(bounds, j, i, type));
- root.grow(bounds);
- center.grow(bounds.center2());
+ if(bounds.valid()) {
+ references.push_back(BVHReference(bounds, j, i, type));
+ root.grow(bounds);
+ center.grow(bounds.center2());
+ }
}
}
- Attribute *curve_attr_mP = NULL;
+ if(params.primitive_mask & PRIMITIVE_ALL_CURVE) {
+ Attribute *curve_attr_mP = NULL;
- if(mesh->has_motion_blur())
- curve_attr_mP = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+ if(mesh->has_motion_blur())
+ curve_attr_mP = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
- for(uint j = 0; j < mesh->curves.size(); j++) {
- Mesh::Curve curve = mesh->curves[j];
- PrimitiveType type = PRIMITIVE_CURVE;
+ size_t num_curves = mesh->num_curves();
+ for(uint j = 0; j < num_curves; j++) {
+ Mesh::Curve curve = mesh->get_curve(j);
+ PrimitiveType type = PRIMITIVE_CURVE;
- for(int k = 0; k < curve.num_keys - 1; k++) {
- BoundBox bounds = BoundBox::empty;
- curve.bounds_grow(k, &mesh->curve_keys[0], bounds);
+ for(int k = 0; k < curve.num_keys - 1; k++) {
+ BoundBox bounds = BoundBox::empty;
+ curve.bounds_grow(k, &mesh->curve_keys[0], &mesh->curve_radius[0], bounds);
- /* motion curve */
- if(curve_attr_mP) {
- size_t mesh_size = mesh->curve_keys.size();
- size_t steps = mesh->motion_steps - 1;
- float4 *key_steps = curve_attr_mP->data_float4();
+ /* motion curve */
+ if(curve_attr_mP) {
+ size_t mesh_size = mesh->curve_keys.size();
+ size_t steps = mesh->motion_steps - 1;
+ float3 *key_steps = curve_attr_mP->data_float3();
- for(size_t i = 0; i < steps; i++)
- curve.bounds_grow(k, key_steps + i*mesh_size, bounds);
+ for(size_t i = 0; i < steps; i++)
+ curve.bounds_grow(k, key_steps + i*mesh_size, &mesh->curve_radius[0], bounds);
- type = PRIMITIVE_MOTION_CURVE;
- }
+ type = PRIMITIVE_MOTION_CURVE;
+ }
- if(bounds.valid()) {
- int packed_type = PRIMITIVE_PACK_SEGMENT(type, k);
-
- references.push_back(BVHReference(bounds, j, i, packed_type));
- root.grow(bounds);
- center.grow(bounds.center2());
+ if(bounds.valid()) {
+ int packed_type = PRIMITIVE_PACK_SEGMENT(type, k);
+
+ references.push_back(BVHReference(bounds, j, i, packed_type));
+ root.grow(bounds);
+ center.grow(bounds.center2());
+ }
}
}
}
@@ -188,10 +196,10 @@ void BVHBuild::add_reference_object(BoundBox& root, BoundBox& center, Object *ob
static size_t count_curve_segments(Mesh *mesh)
{
- size_t num = 0, num_curves = mesh->curves.size();
+ size_t num = 0, num_curves = mesh->num_curves();
for(size_t i = 0; i < num_curves; i++)
- num += mesh->curves[i].num_keys - 1;
+ num += mesh->get_curve(i).num_keys - 1;
return num;
}
@@ -203,16 +211,27 @@ void BVHBuild::add_references(BVHRange& root)
foreach(Object *ob, objects) {
if(params.top_level) {
+ if(!ob->is_traceable()) {
+ continue;
+ }
if(!ob->mesh->is_instanced()) {
- num_alloc_references += ob->mesh->triangles.size();
- num_alloc_references += count_curve_segments(ob->mesh);
+ 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 {
- num_alloc_references += ob->mesh->triangles.size();
- num_alloc_references += count_curve_segments(ob->mesh);
+ 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);
+ }
}
}
@@ -224,6 +243,10 @@ void BVHBuild::add_references(BVHRange& root)
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
@@ -326,11 +349,13 @@ BVHNode* BVHBuild::run()
VLOG(1) << "BVH build statistics:\n"
<< " Build time: " << time_dt() - build_start_time << "\n"
<< " Total number of nodes: "
- << rootnode->getSubtreeSize(BVH_STAT_NODE_COUNT) << "\n"
+ << string_human_readable_number(rootnode->getSubtreeSize(BVH_STAT_NODE_COUNT)) << "\n"
<< " Number of inner nodes: "
- << rootnode->getSubtreeSize(BVH_STAT_INNER_COUNT) << "\n"
+ << string_human_readable_number(rootnode->getSubtreeSize(BVH_STAT_INNER_COUNT)) << "\n"
<< " Number of leaf nodes: "
- << rootnode->getSubtreeSize(BVH_STAT_LEAF_COUNT) << "\n"
+ << 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()
@@ -436,10 +461,11 @@ BVHNode* BVHBuild::build_node(const BVHObjectBinning& range, int level)
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 */
+ /* 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 */
+ /* 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))
{
@@ -447,28 +473,70 @@ BVHNode* BVHBuild::build_node(const BVHObjectBinning& range, int level)
}
}
- /* perform split */
+ BVHObjectBinning unaligned_range;
+ float unalignedSplitSAH = FLT_MAX;
+ float unalignedLeafSAH = FLT_MAX;
+ Transform aligned_space;
+ 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);
+ }
+ }
+ }
+
+ /* Perform split. */
BVHObjectBinning left, right;
- range.split(&references[0], left, right);
+ if(unalignedSplitSAH < splitSAH) {
+ unaligned_range.split(&references[0], left, right);
+ }
+ else {
+ range.split(&references[0], left, right);
+ }
- /* create inner node. */
- InnerNode *inner;
+ BoundBox bounds;
+ if(unalignedSplitSAH < splitSAH) {
+ 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(range.bounds(), leftnode, rightnode);
+ inner = new InnerNode(bounds, leftnode, rightnode);
}
else {
- /* threaded build */
- inner = new InnerNode(range.bounds());
+ /* 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(unalignedSplitSAH < splitSAH) {
+ inner->set_aligned_space(aligned_space);
+ }
+
return inner;
}
@@ -507,16 +575,54 @@ BVHNode* BVHBuild::build_node(const BVHRange& range,
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;
+ 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. */
+ }
/* Do split. */
BVHRange left, right;
- split.split(this, left, right, range);
+ if(unalignedSplitSAH < splitSAH) {
+ 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(unalignedSplitSAH < splitSAH) {
+ 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. */
@@ -530,11 +636,11 @@ BVHNode* BVHBuild::build_node(const BVHRange& range,
/* Build right node. */
BVHNode *rightnode = build_node(right, &copy, level + 1, thread_id);
- inner = new InnerNode(range.bounds(), leftnode, rightnode);
+ inner = new InnerNode(bounds, leftnode, rightnode);
}
else {
/* Threaded build. */
- inner = new InnerNode(range.bounds());
+ inner = new InnerNode(bounds);
task_pool.push(new BVHSpatialSplitBuildTask(this,
inner,
0,
@@ -551,6 +657,10 @@ BVHNode* BVHBuild::build_node(const BVHRange& range,
true);
}
+ if(unalignedSplitSAH < splitSAH) {
+ inner->set_aligned_space(aligned_space);
+ }
+
return inner;
}
@@ -607,6 +717,7 @@ BVHNode* BVHBuild::create_leaf_node(const BVHRange& range,
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<BVHReference, LeafStackAllocator> p_ref[PRIMITIVE_NUM_TOTAL];
/* TODO(sergey): In theory we should be able to store references. */
typedef StackAllocator<256, BVHReference> LeafReferenceStackAllocator;
@@ -625,6 +736,7 @@ BVHNode* BVHBuild::create_leaf_node(const BVHRange& range,
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());
@@ -665,16 +777,38 @@ BVHNode* BVHBuild::create_leaf_node(const BVHRange& range,
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(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(alignment_found) {
+ /* Need to recalculate leaf bounds with new alignment. */
+ leaf_node->m_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->m_bounds.grow(ref_bounds);
+ }
+ /* Set alignment space. */
+ leaf_node->set_aligned_space(aligned_space);
}
- leaves[num_leaves++] = new LeafNode(bounds[i],
- visibility[i],
- start_index,
- start_index + num);
+ leaves[num_leaves++] = leaf_node;
start_index += num;
}
}
@@ -756,6 +890,9 @@ BVHNode* BVHBuild::create_leaf_node(const BVHRange& range,
++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
diff --git a/intern/cycles/bvh/bvh_build.h b/intern/cycles/bvh/bvh_build.h
index a015b89d72f..64180349935 100644
--- a/intern/cycles/bvh/bvh_build.h
+++ b/intern/cycles/bvh/bvh_build.h
@@ -22,6 +22,7 @@
#include "bvh.h"
#include "bvh_binning.h"
+#include "bvh_unaligned.h"
#include "util_boundbox.h"
#include "util_task.h"
@@ -59,13 +60,14 @@ protected:
friend class BVHSpatialSplit;
friend class BVHBuildTask;
friend class BVHSpatialSplitBuildTask;
+ friend class BVHObjectBinning;
- /* adding references */
+ /* Adding references. */
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 */
+ /* Building. */
BVHNode *build_node(const BVHRange& range,
vector<BVHReference> *references,
int level,
@@ -78,7 +80,7 @@ protected:
bool range_within_max_leaf_size(const BVHRange& range,
const vector<BVHReference>& references) const;
- /* threads */
+ /* Threads. */
enum { THREAD_TASK_SIZE = 4096 };
void thread_build_node(InnerNode *node,
int child,
@@ -92,41 +94,44 @@ protected:
int thread_id);
thread_mutex build_mutex;
- /* progress */
+ /* Progress. */
void progress_update();
- /* tree rotations */
+ /* Tree rotations. */
void rotate(BVHNode *node, int max_depth);
void rotate(BVHNode *node, int max_depth, int iterations);
- /* objects and primitive references */
+ /* Objects and primitive references. */
vector<Object*> objects;
vector<BVHReference> references;
int num_original_references;
- /* output primitive indexes and objects */
+ /* Output primitive indexes and objects. */
array<int>& prim_type;
array<int>& prim_index;
array<int>& prim_object;
- /* build parameters */
+ /* Build parameters. */
BVHParams params;
- /* progress reporting */
+ /* Progress reporting. */
Progress& progress;
double progress_start_time;
size_t progress_count;
size_t progress_total;
size_t progress_original_total;
- /* spatial splitting */
+ /* Spatial splitting. */
float spatial_min_overlap;
vector<BVHSpatialStorage> spatial_storage;
size_t spatial_free_index;
thread_spin_lock spatial_spin_lock;
- /* threads */
+ /* Threads. */
TaskPool task_pool;
+
+ /* Unaligned building. */
+ BVHUnaligned unaligned_heuristic;
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/bvh/bvh_node.cpp b/intern/cycles/bvh/bvh_node.cpp
index 8294690da7d..f5cd699bdf4 100644
--- a/intern/cycles/bvh/bvh_node.cpp
+++ b/intern/cycles/bvh/bvh_node.cpp
@@ -61,6 +61,76 @@ int BVHNode::getSubtreeSize(BVH_STAT stat) const
}
}
return cnt;
+ 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_INNER_QNODE_COUNT:
+ {
+ bool has_unaligned = false;
+ for(int i = 0; i < num_children(); i++) {
+ BVHNode *node = get_child(i);
+ if(node->is_leaf()) {
+ has_unaligned |= node->is_unaligned();
+ }
+ else {
+ for(int j = 0; j < node->num_children(); j++) {
+ cnt += node->get_child(j)->getSubtreeSize(stat);
+ has_unaligned |= node->get_child(j)->is_unaligned();
+ }
+ }
+ }
+ cnt += has_unaligned? 0: 1;
+ }
+ return cnt;
+ case BVH_STAT_UNALIGNED_INNER_QNODE_COUNT:
+ {
+ bool has_unaligned = false;
+ for(int i = 0; i < num_children(); i++) {
+ BVHNode *node = get_child(i);
+ if(node->is_leaf()) {
+ has_unaligned |= node->is_unaligned();
+ }
+ else {
+ for(int j = 0; j < node->num_children(); j++) {
+ cnt += node->get_child(j)->getSubtreeSize(stat);
+ has_unaligned |= node->get_child(j)->is_unaligned();
+ }
+ }
+ }
+ cnt += has_unaligned? 1: 0;
+ }
+ return cnt;
+ 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;
default:
assert(0); /* unknown mode */
}
diff --git a/intern/cycles/bvh/bvh_node.h b/intern/cycles/bvh/bvh_node.h
index d476fb917ed..f2965a785e6 100644
--- a/intern/cycles/bvh/bvh_node.h
+++ b/intern/cycles/bvh/bvh_node.h
@@ -31,6 +31,14 @@ enum BVH_STAT {
BVH_STAT_TRIANGLE_COUNT,
BVH_STAT_CHILDNODE_COUNT,
BVH_STAT_QNODE_COUNT,
+ BVH_STAT_ALIGNED_COUNT,
+ BVH_STAT_UNALIGNED_COUNT,
+ BVH_STAT_ALIGNED_INNER_COUNT,
+ BVH_STAT_UNALIGNED_INNER_COUNT,
+ BVH_STAT_ALIGNED_INNER_QNODE_COUNT,
+ BVH_STAT_UNALIGNED_INNER_QNODE_COUNT,
+ BVH_STAT_ALIGNED_LEAF_COUNT,
+ BVH_STAT_UNALIGNED_LEAF_COUNT,
};
class BVHParams;
@@ -38,16 +46,41 @@ class BVHParams;
class BVHNode
{
public:
- BVHNode()
+ BVHNode() : m_is_unaligned(false),
+ m_aligned_space(NULL)
{
}
- virtual ~BVHNode() {}
+ virtual ~BVHNode()
+ {
+ delete m_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;
+ bool is_unaligned() const { return m_is_unaligned; }
+
+ inline void set_aligned_space(const Transform& aligned_space)
+ {
+ m_is_unaligned = true;
+ if (m_aligned_space == NULL) {
+ m_aligned_space = new Transform(aligned_space);
+ }
+ else {
+ *m_aligned_space = aligned_space;
+ }
+ }
+
+ inline Transform get_aligned_space() const
+ {
+ if(m_aligned_space == NULL) {
+ return transform_identity();
+ }
+ return *m_aligned_space;
+ }
BoundBox m_bounds;
uint m_visibility;
@@ -58,12 +91,20 @@ public:
void deleteSubtree();
uint update_visibility();
+
+ bool m_is_unaligned;
+
+ // TODO(sergey): Can be stored as 3x3 matrix, but better to have some
+ // utilities and type defines in util_transform first.
+ Transform *m_aligned_space;
};
class InnerNode : public BVHNode
{
public:
- InnerNode(const BoundBox& bounds, BVHNode* child0, BVHNode* child1)
+ InnerNode(const BoundBox& bounds,
+ BVHNode* child0,
+ BVHNode* child1)
{
m_bounds = bounds;
children[0] = child0;
diff --git a/intern/cycles/bvh/bvh_params.h b/intern/cycles/bvh/bvh_params.h
index cf683df1b31..2e698a80742 100644
--- a/intern/cycles/bvh/bvh_params.h
+++ b/intern/cycles/bvh/bvh_params.h
@@ -20,6 +20,8 @@
#include "util_boundbox.h"
+#include "kernel_types.h"
+
CCL_NAMESPACE_BEGIN
/* BVH Parameters */
@@ -31,6 +33,9 @@ public:
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;
@@ -46,6 +51,14 @@ public:
/* QBVH */
bool use_qbvh;
+ /* 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;
+
/* fixed parameters */
enum {
MAX_DEPTH = 64,
@@ -58,6 +71,8 @@ public:
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;
@@ -69,6 +84,9 @@ public:
top_level = false;
use_qbvh = false;
+ use_unaligned_nodes = false;
+
+ primitive_mask = PRIMITIVE_ALL;
}
/* SAH costs */
diff --git a/intern/cycles/bvh/bvh_sort.cpp b/intern/cycles/bvh/bvh_sort.cpp
index e9032c61c3b..e5bcf9995bf 100644
--- a/intern/cycles/bvh/bvh_sort.cpp
+++ b/intern/cycles/bvh/bvh_sort.cpp
@@ -26,23 +26,27 @@ CCL_NAMESPACE_BEGIN
static const int BVH_SORT_THRESHOLD = 4096;
-/* Silly workaround for float extended precision that happens when compiling
- * on x86, due to one float staying in 80 bit precision register and the other
- * not, which causes the strictly weak ordering to break.
- */
-#if !defined(__i386__)
-# define NO_EXTENDED_PRECISION
-#else
-# define NO_EXTENDED_PRECISION volatile
-#endif
-
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)
+ {
+ }
- explicit BVHReferenceCompare(int dim_)
+ __forceinline BoundBox get_prim_bounds(const BVHReference& prim) const
{
- dim = dim_;
+ return (aligned_space != NULL)
+ ? unaligned_heuristic->compute_aligned_prim_boundbox(
+ prim, *aligned_space)
+ : prim.bounds();
}
/* Compare two references.
@@ -52,8 +56,10 @@ public:
__forceinline int compare(const BVHReference& ra,
const BVHReference& rb) const
{
- NO_EXTENDED_PRECISION float ca = ra.bounds().min[dim] + ra.bounds().max[dim];
- NO_EXTENDED_PRECISION float cb = rb.bounds().min[dim] + rb.bounds().max[dim];
+ 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;
@@ -171,10 +177,15 @@ static void bvh_reference_sort_threaded(TaskPool *task_pool,
}
}
-void bvh_reference_sort(int start, int end, BVHReference *data, int dim)
+void bvh_reference_sort(int start,
+ int end,
+ BVHReference *data,
+ int dim,
+ const BVHUnaligned *unaligned_heuristic,
+ const Transform *aligned_space)
{
const int count = end - start;
- BVHReferenceCompare compare(dim);
+ 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
diff --git a/intern/cycles/bvh/bvh_sort.h b/intern/cycles/bvh/bvh_sort.h
index 18aafb5f1ff..b49ca02eb60 100644
--- a/intern/cycles/bvh/bvh_sort.h
+++ b/intern/cycles/bvh/bvh_sort.h
@@ -20,7 +20,15 @@
CCL_NAMESPACE_BEGIN
-void bvh_reference_sort(int start, int end, BVHReference *data, int dim);
+class BVHUnaligned;
+struct Transform;
+
+void bvh_reference_sort(int start,
+ int end,
+ BVHReference *data,
+ int dim,
+ const BVHUnaligned *unaligned_heuristic = NULL,
+ const Transform *aligned_space = NULL);
CCL_NAMESPACE_END
diff --git a/intern/cycles/bvh/bvh_split.cpp b/intern/cycles/bvh/bvh_split.cpp
index 8084975565e..d0d5fbe5a7a 100644
--- a/intern/cycles/bvh/bvh_split.cpp
+++ b/intern/cycles/bvh/bvh_split.cpp
@@ -32,14 +32,18 @@ BVHObjectSplit::BVHObjectSplit(BVHBuild *builder,
BVHSpatialStorage *storage,
const BVHRange& range,
vector<BVHReference> *references,
- float nodeSAH)
+ 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)
+ references_(references),
+ unaligned_heuristic_(unaligned_heuristic),
+ aligned_space_(aligned_space)
{
const BVHReference *ref_ptr = &references_->at(range.start());
float min_sah = FLT_MAX;
@@ -51,12 +55,15 @@ BVHObjectSplit::BVHObjectSplit(BVHBuild *builder,
bvh_reference_sort(range.start(),
range.end(),
&references_->at(0),
- dim);
+ 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--) {
- right_bounds.grow(ref_ptr[i].bounds());
+ BoundBox prim_bounds = get_prim_bounds(ref_ptr[i]);
+ right_bounds.grow(prim_bounds);
storage_->right_bounds[i - 1] = right_bounds;
}
@@ -64,7 +71,8 @@ BVHObjectSplit::BVHObjectSplit(BVHBuild *builder,
BoundBox left_bounds = BoundBox::empty;
for(int i = 1; i < range.size(); i++) {
- left_bounds.grow(ref_ptr[i - 1].bounds());
+ 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 +
@@ -88,16 +96,37 @@ 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);
+ 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(this->left_bounds, range.start(), this->num_left);
- right = BVHRange(this->right_bounds, left.end(), range.size() - this->num_left);
-
+ left = BVHRange(effective_left_bounds, range.start(), this->num_left);
+ right = BVHRange(effective_right_bounds, left.end(), num_right);
}
/* Spatial Split */
@@ -106,16 +135,31 @@ BVHSpatialSplit::BVHSpatialSplit(const BVHBuild& builder,
BVHSpatialStorage *storage,
const BVHRange& range,
vector<BVHReference> *references,
- float nodeSAH)
+ float nodeSAH,
+ const BVHUnaligned *unaligned_heuristic,
+ const Transform *aligned_space)
: sah(FLT_MAX),
dim(0),
pos(0.0f),
storage_(storage),
- references_(references)
+ references_(references),
+ unaligned_heuristic_(unaligned_heuristic),
+ aligned_space_(aligned_space)
{
/* initialize bins. */
- float3 origin = range.bounds().min;
- float3 binSize = (range.bounds().max - origin) * (1.0f / (float)BVHParams::NUM_SPATIAL_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++) {
@@ -131,8 +175,9 @@ BVHSpatialSplit::BVHSpatialSplit(const BVHBuild& builder,
/* chop references into bins. */
for(unsigned int refIdx = range.start(); refIdx < range.end(); refIdx++) {
const BVHReference& ref = references_->at(refIdx);
- float3 firstBinf = (ref.bounds().min - origin) * invBinSize;
- float3 lastBinf = (ref.bounds().max - origin) * invBinSize;
+ 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);
@@ -140,7 +185,10 @@ BVHSpatialSplit::BVHSpatialSplit(const BVHBuild& builder,
lastBin = clamp(lastBin, firstBin, BVHParams::NUM_SPATIAL_BINS - 1);
for(int dim = 0; dim < 3; dim++) {
- BVHReference currRef = ref;
+ 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;
@@ -209,14 +257,15 @@ void BVHSpatialSplit::split(BVHBuild *builder,
BoundBox right_bounds = BoundBox::empty;
for(int i = left_end; i < right_start; i++) {
- if(refs[i].bounds().max[this->dim] <= this->pos) {
+ 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(refs[i].bounds());
+ left_bounds.grow(prim_bounds);
swap(refs[i], refs[left_end++]);
}
- else if(refs[i].bounds().min[this->dim] >= this->pos) {
+ else if(prim_bounds.min[this->dim] >= this->pos) {
/* entirely on the right-hand side */
- right_bounds.grow(refs[i].bounds());
+ right_bounds.grow(prim_bounds);
swap(refs[i--], refs[--right_start]);
}
}
@@ -231,8 +280,12 @@ void BVHSpatialSplit::split(BVHBuild *builder,
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, refs[left_end], this->dim, this->pos);
+ 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.
@@ -240,8 +293,8 @@ void BVHSpatialSplit::split(BVHBuild *builder,
BoundBox ldb = left_bounds; // Duplicate: new left-hand bounds.
BoundBox rdb = right_bounds; // Duplicate: new right-hand bounds.
- lub.grow(refs[left_end].bounds());
- rub.grow(refs[left_end].bounds());
+ lub.grow(curr_ref.bounds());
+ rub.grow(curr_ref.bounds());
ldb.grow(lref.bounds());
rdb.grow(rref.bounds());
@@ -280,6 +333,17 @@ void BVHSpatialSplit::split(BVHBuild *builder,
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);
}
@@ -292,14 +356,16 @@ void BVHSpatialSplit::split_triangle_primitive(const Mesh *mesh,
BoundBox& left_bounds,
BoundBox& right_bounds)
{
- const int *inds = mesh->triangles[prim_index].v;
+ Mesh::Triangle t = mesh->get_triangle(prim_index);
const float3 *verts = &mesh->verts[0];
- float3 v1 = tfm ? transform_point(tfm, verts[inds[2]]) : verts[inds[2]];
+ 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 = inds[i];
+ 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];
@@ -329,17 +395,18 @@ void BVHSpatialSplit::split_curve_primitive(const Mesh *mesh,
BoundBox& right_bounds)
{
/* curve split: NOTE - Currently ignores curve width and needs to be fixed.*/
- const int k0 = mesh->curves[prim_index].first_key + segment_index;
+ Mesh::Curve curve = mesh->get_curve(prim_index);
+ const int k0 = curve.first_key + segment_index;
const int k1 = k0 + 1;
- const float4& key0 = mesh->curve_keys[k0];
- const float4& key1 = mesh->curve_keys[k1];
- float3 v0 = float4_to_float3(key0);
- float3 v1 = float4_to_float3(key1);
+ 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];
@@ -405,7 +472,7 @@ void BVHSpatialSplit::split_object_reference(const Object *object,
BoundBox& right_bounds)
{
Mesh *mesh = object->mesh;
- for(int tri_idx = 0; tri_idx < mesh->triangles.size(); ++tri_idx) {
+ for(int tri_idx = 0; tri_idx < mesh->num_triangles(); ++tri_idx) {
split_triangle_primitive(mesh,
&object->tfm,
tri_idx,
@@ -414,8 +481,8 @@ void BVHSpatialSplit::split_object_reference(const Object *object,
left_bounds,
right_bounds);
}
- for(int curve_idx = 0; curve_idx < mesh->curves.size(); ++curve_idx) {
- Mesh::Curve &curve = mesh->curves[curve_idx];
+ 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)
@@ -474,6 +541,7 @@ void BVHSpatialSplit::split_reference(const BVHBuild& builder,
/* intersect with original bounds. */
left_bounds.max[dim] = pos;
right_bounds.min[dim] = pos;
+
left_bounds.intersect(ref.bounds());
right_bounds.intersect(ref.bounds());
diff --git a/intern/cycles/bvh/bvh_split.h b/intern/cycles/bvh/bvh_split.h
index aea8b2565e0..dbdb51f1a5b 100644
--- a/intern/cycles/bvh/bvh_split.h
+++ b/intern/cycles/bvh/bvh_split.h
@@ -24,6 +24,7 @@
CCL_NAMESPACE_BEGIN
class BVHBuild;
+struct Transform;
/* Object Split */
@@ -41,7 +42,9 @@ public:
BVHSpatialStorage *storage,
const BVHRange& range,
vector<BVHReference> *references,
- float nodeSAH);
+ float nodeSAH,
+ const BVHUnaligned *unaligned_heuristic = NULL,
+ const Transform *aligned_space = NULL);
void split(BVHRange& left,
BVHRange& right,
@@ -50,6 +53,19 @@ public:
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 */
@@ -70,7 +86,9 @@ public:
BVHSpatialStorage *storage,
const BVHRange& range,
vector<BVHReference> *references,
- float nodeSAH);
+ float nodeSAH,
+ const BVHUnaligned *unaligned_heuristic = NULL,
+ const Transform *aligned_space = NULL);
void split(BVHBuild *builder,
BVHRange& left,
@@ -87,6 +105,8 @@ public:
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.
@@ -132,6 +152,27 @@ protected:
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 */
@@ -148,19 +189,40 @@ public:
bool no_split;
+ BoundBox bounds;
+
+ BVHMixedSplit() {}
+
__forceinline BVHMixedSplit(BVHBuild *builder,
BVHSpatialStorage *storage,
const BVHRange& range,
vector<BVHReference> *references,
- int level)
+ 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 = range.bounds().safe_area();
+ 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);
+ 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;
@@ -171,7 +233,9 @@ public:
storage,
range,
references,
- nodeSAH);
+ nodeSAH,
+ unaligned_heuristic,
+ aligned_space);
}
}
@@ -181,7 +245,10 @@ public:
builder->range_within_max_leaf_size(range, *references));
}
- __forceinline void split(BVHBuild *builder, BVHRange& left, BVHRange& right, const BVHRange& range)
+ __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);
@@ -193,4 +260,3 @@ public:
CCL_NAMESPACE_END
#endif /* __BVH_SPLIT_H__ */
-
diff --git a/intern/cycles/bvh/bvh_unaligned.cpp b/intern/cycles/bvh/bvh_unaligned.cpp
new file mode 100644
index 00000000000..a876c670914
--- /dev/null
+++ b/intern/cycles/bvh/bvh_unaligned.cpp
@@ -0,0 +1,178 @@
+/*
+ * Copyright 2011-2016 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include "bvh_unaligned.h"
+
+#include "mesh.h"
+#include "object.h"
+
+#include "bvh_binning.h"
+#include "bvh_params.h"
+
+#include "util_boundbox.h"
+#include "util_debug.h"
+#include "util_transform.h"
+
+CCL_NAMESPACE_BEGIN
+
+
+BVHUnaligned::BVHUnaligned(const vector<Object*>& objects)
+ : objects_(objects)
+{
+}
+
+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();
+}
+
+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();
+}
+
+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;
+}
+
+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 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 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;
+}
+
+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;
+}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/bvh/bvh_unaligned.h b/intern/cycles/bvh/bvh_unaligned.h
new file mode 100644
index 00000000000..4d0872f4a39
--- /dev/null
+++ b/intern/cycles/bvh/bvh_unaligned.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2011-2016 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __BVH_UNALIGNED_H__
+#define __BVH_UNALIGNED_H__
+
+#include "util_vector.h"
+
+CCL_NAMESPACE_BEGIN
+
+class BoundBox;
+class BVHObjectBinning;
+class BVHRange;
+class BVHReference;
+struct Transform;
+class Object;
+
+/* Helper class to perform calculations needed for unaligned nodes. */
+class BVHUnaligned {
+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 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 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_;
+};
+
+CCL_NAMESPACE_END
+
+#endif /* __BVH_UNALIGNED_H__ */
+
diff --git a/intern/cycles/device/device_cpu.cpp b/intern/cycles/device/device_cpu.cpp
index 275ee028eb4..aed86d8d853 100644
--- a/intern/cycles/device/device_cpu.cpp
+++ b/intern/cycles/device/device_cpu.cpp
@@ -155,7 +155,9 @@ public:
InterpolationType interpolation,
ExtensionType extension)
{
- VLOG(1) << "Texture allocate: " << name << ", " << mem.memory_size() << " bytes.";
+ VLOG(1) << "Texture allocate: " << name << ", "
+ << string_human_readable_number(mem.memory_size()) << " bytes. ("
+ << string_human_readable_size(mem.memory_size()) << ")";
kernel_tex_copy(&kernel_globals,
name,
mem.data_pointer,
diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp
index 9a78d055580..2d404918a38 100644
--- a/intern/cycles/device/device_cuda.cpp
+++ b/intern/cycles/device/device_cuda.cpp
@@ -493,7 +493,9 @@ public:
InterpolationType interpolation,
ExtensionType extension)
{
- VLOG(1) << "Texture allocate: " << name << ", " << mem.memory_size() << " bytes.";
+ VLOG(1) << "Texture allocate: " << name << ", "
+ << string_human_readable_number(mem.memory_size()) << " bytes. ("
+ << string_human_readable_size(mem.memory_size()) << ")";
/* Check if we are on sm_30 or above.
* We use arrays and bindles textures for storage there */
@@ -1366,6 +1368,7 @@ void device_cuda_info(vector<DeviceInfo>& devices)
/* if device has a kernel timeout, assume it is used for display */
if(cuDeviceGetAttribute(&attr, CU_DEVICE_ATTRIBUTE_KERNEL_EXEC_TIMEOUT, num) == CUDA_SUCCESS && attr == 1) {
+ info.description += " (Display)";
info.display_device = true;
display_devices.push_back(info);
}
diff --git a/intern/cycles/device/device_memory.h b/intern/cycles/device/device_memory.h
index 8c32d03135e..5b5b4dc6802 100644
--- a/intern/cycles/device/device_memory.h
+++ b/intern/cycles/device/device_memory.h
@@ -150,6 +150,11 @@ template<> struct device_type_traits<float4> {
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;
+};
+
template<> struct device_type_traits<half4> {
static const DataType data_type = TYPE_HALF;
static const int num_elements = 4;
diff --git a/intern/cycles/device/device_multi.cpp b/intern/cycles/device/device_multi.cpp
index 434d0085d39..c4f8d9e16e0 100644
--- a/intern/cycles/device/device_multi.cpp
+++ b/intern/cycles/device/device_multi.cpp
@@ -175,7 +175,9 @@ public:
interpolation,
ExtensionType extension)
{
- VLOG(1) << "Texture allocate: " << name << ", " << mem.memory_size() << " bytes.";
+ VLOG(1) << "Texture allocate: " << name << ", "
+ << string_human_readable_number(mem.memory_size()) << " bytes. ("
+ << string_human_readable_size(mem.memory_size()) << ")";
foreach(SubDevice& sub, devices) {
mem.device_pointer = 0;
diff --git a/intern/cycles/device/device_network.cpp b/intern/cycles/device/device_network.cpp
index cf4a05de8fc..3eb5ad2d2db 100644
--- a/intern/cycles/device/device_network.cpp
+++ b/intern/cycles/device/device_network.cpp
@@ -168,7 +168,9 @@ public:
InterpolationType interpolation,
ExtensionType extension)
{
- VLOG(1) << "Texture allocate: " << name << ", " << mem.memory_size() << " bytes.";
+ VLOG(1) << "Texture allocate: " << name << ", "
+ << string_human_readable_number(mem.memory_size()) << " bytes. ("
+ << string_human_readable_size(mem.memory_size()) << ")";
thread_scoped_lock lock(rpc_lock);
diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp
index 1b4e5421b5a..50490f3a20e 100644
--- a/intern/cycles/device/device_opencl.cpp
+++ b/intern/cycles/device/device_opencl.cpp
@@ -795,7 +795,7 @@ public:
bool load_binary(const string& /*kernel_path*/,
const string& clbin,
- string custom_kernel_build_options,
+ const string& custom_kernel_build_options,
cl_program *program,
const string *debug_src = NULL)
{
@@ -848,7 +848,7 @@ public:
}
bool build_kernel(cl_program *kernel_program,
- string custom_kernel_build_options,
+ const string& custom_kernel_build_options,
const string *debug_src = NULL)
{
string build_options;
@@ -881,30 +881,39 @@ public:
return true;
}
- bool compile_kernel(const string& kernel_path,
- string source,
- string custom_kernel_build_options,
+ bool compile_kernel(const string& kernel_name,
+ const string& kernel_path,
+ const string& source,
+ const string& custom_kernel_build_options,
cl_program *kernel_program,
const string *debug_src = NULL)
{
- /* we compile kernels consisting of many files. unfortunately opencl
+ /* 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, kernel_path);
+ * so we force recompile on changes by adding the md5 hash of all files.
+ */
+ string inlined_source = path_source_replace_includes(source,
+ kernel_path);
- if(debug_src)
- path_write_text(*debug_src, source);
+ if(debug_src) {
+ path_write_text(*debug_src, inlined_source);
+ }
- size_t source_len = source.size();
- const char *source_str = source.c_str();
+ size_t source_len = inlined_source.size();
+ const char *source_str = inlined_source.c_str();
- *kernel_program = clCreateProgramWithSource(cxContext, 1, &source_str, &source_len, &ciErr);
+ *kernel_program = clCreateProgramWithSource(cxContext,
+ 1,
+ &source_str,
+ &source_len,
+ &ciErr);
- if(opencl_error(ciErr))
+ if(opencl_error(ciErr)) {
return false;
+ }
double starttime = time_dt();
- printf("Compiling OpenCL kernel ...\n");
+ printf("Compiling %s OpenCL kernel ...\n", kernel_name.c_str());
/* TODO(sergey): Report which kernel is being compiled
* as well (megakernel or which of split kernels etc..).
*/
@@ -1004,7 +1013,8 @@ public:
string init_kernel_source = "#include \"kernels/opencl/kernel.cl\" // " + kernel_md5 + "\n";
/* If does not exist or loading binary failed, compile kernel. */
- if(!compile_kernel(kernel_path,
+ if(!compile_kernel("base_kernel",
+ kernel_path,
init_kernel_source,
build_flags,
&cpProgram,
@@ -1187,7 +1197,9 @@ public:
InterpolationType /*interpolation*/,
ExtensionType /*extension*/)
{
- VLOG(1) << "Texture allocate: " << name << ", " << mem.memory_size() << " bytes.";
+ VLOG(1) << "Texture allocate: " << name << ", "
+ << string_human_readable_number(mem.memory_size()) << " bytes. ("
+ << string_human_readable_size(mem.memory_size()) << ")";
mem_alloc(mem, MEM_READ_ONLY);
mem_copy_to(mem);
assert(mem_map.find(name) == mem_map.end());
@@ -1222,18 +1234,28 @@ public:
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);
-
- /* try to divide evenly over 2 dimensions */
+
+ /* Try to divide evenly over 2 dimensions. */
size_t sqrt_workgroup_size = max((size_t)sqrt((double)workgroup_size), 1);
size_t local_size[2] = {sqrt_workgroup_size, sqrt_workgroup_size};
- /* some implementations have max size 1 on 2nd dimension */
+ /* 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)};
+ 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));
@@ -1318,48 +1340,49 @@ public:
else
kernel = ckShaderKernel;
- for(int sample = 0; sample < task.num_samples; sample++) {
-
- if(task.get_cancel())
- break;
-
- cl_int d_sample = sample;
-
- cl_uint start_arg_index =
- kernel_set_args(kernel,
- 0,
- d_data,
- d_input,
- d_output);
+ cl_uint start_arg_index =
+ kernel_set_args(kernel,
+ 0,
+ d_data,
+ d_input,
+ d_output);
- if(task.shader_eval_type < SHADER_EVAL_BAKE) {
- start_arg_index += kernel_set_args(kernel,
- start_arg_index,
- d_output_luma);
- }
+ if(task.shader_eval_type < SHADER_EVAL_BAKE) {
+ start_arg_index += kernel_set_args(kernel,
+ start_arg_index,
+ d_output_luma);
+ }
#define KERNEL_TEX(type, ttype, name) \
- set_kernel_arg_mem(kernel, &start_arg_index, #name);
+ set_kernel_arg_mem(kernel, &start_arg_index, #name);
#include "kernel_textures.h"
#undef KERNEL_TEX
+ 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_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,
- d_sample);
+ 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);
}
}
@@ -1681,7 +1704,8 @@ public:
string init_kernel_source = "#include \"kernels/opencl/kernel.cl\" // " +
kernel_md5 + "\n";
/* If does not exist or loading binary failed, compile kernel. */
- if(!compile_kernel(kernel_path,
+ if(!compile_kernel("mega_kernel",
+ kernel_path,
init_kernel_source,
custom_kernel_build_options,
&path_trace_program,
@@ -2065,30 +2089,33 @@ public:
/* TODO(sergey): Seems really close to load_kernel(),
* could it be de-duplicated?
*/
- bool load_split_kernel(string kernel_path,
- string kernel_init_source,
- string clbin,
- string custom_kernel_build_options,
+ bool load_split_kernel(const string& kernel_name,
+ const string& kernel_path,
+ const string& kernel_init_source,
+ const string& clbin,
+ const string& custom_kernel_build_options,
cl_program *program,
const string *debug_src = NULL)
{
- if(!opencl_version_check())
+ if(!opencl_version_check()) {
return false;
+ }
- clbin = path_user_get(path_join("cache", clbin));
+ string cache_clbin = path_user_get(path_join("cache", clbin));
/* If exists already, try use it. */
- if(path_exists(clbin) && load_binary(kernel_path,
- clbin,
- custom_kernel_build_options,
- program,
- debug_src))
+ if(path_exists(cache_clbin) && load_binary(kernel_path,
+ cache_clbin,
+ custom_kernel_build_options,
+ program,
+ debug_src))
{
/* Kernel loaded from binary. */
}
else {
/* If does not exist or loading binary failed, compile kernel. */
- if(!compile_kernel(kernel_path,
+ if(!compile_kernel(kernel_name,
+ kernel_path,
kernel_init_source,
custom_kernel_build_options,
program,
@@ -2097,7 +2124,7 @@ public:
return false;
}
/* Save binary for reuse. */
- if(!save_binary(program, clbin)) {
+ if(!save_binary(program, cache_clbin)) {
return false;
}
}
@@ -2195,7 +2222,10 @@ public:
clsrc = path_user_get(path_join("cache", clsrc)); \
debug_src = &clsrc; \
} \
- if(!load_split_kernel(kernel_path, kernel_init_source, clbin, \
+ if(!load_split_kernel(#name, \
+ kernel_path, \
+ kernel_init_source, \
+ clbin, \
build_options, \
&GLUE(name, _program), \
debug_src)) \
diff --git a/intern/cycles/graph/node.cpp b/intern/cycles/graph/node.cpp
index d482577b73b..3c228a716d5 100644
--- a/intern/cycles/graph/node.cpp
+++ b/intern/cycles/graph/node.cpp
@@ -36,12 +36,8 @@ Node::Node(const NodeType *type_, ustring name_)
}
/* initialize default values */
- typedef unordered_map<ustring, SocketType, ustringHash> map_type;
- foreach(const map_type::value_type& it, type->inputs) {
- const SocketType& socket = it.second;
- const void *src = socket.default_value;
- void *dst = ((char*)this) + socket.struct_offset;
- memcpy(dst, src, socket.size());
+ foreach(const SocketType& socket, type->inputs) {
+ set_default_value(socket);
}
}
@@ -86,6 +82,12 @@ void Node::set(const SocketType& input, int value)
get_socket_value<int>(this, input) = value;
}
+void Node::set(const SocketType& input, uint value)
+{
+ assert(input.type == SocketType::UINT);
+ get_socket_value<uint>(this, input) = value;
+}
+
void Node::set(const SocketType& input, float value)
{
assert(input.type == SocketType::FLOAT);
@@ -104,6 +106,11 @@ void Node::set(const SocketType& input, float3 value)
get_socket_value<float3>(this, input) = value;
}
+void Node::set(const SocketType& input, const char *value)
+{
+ set(input, ustring(value));
+}
+
void Node::set(const SocketType& input, ustring value)
{
if(input.type == SocketType::STRING) {
@@ -197,6 +204,12 @@ int Node::get_int(const SocketType& input) const
return get_socket_value<int>(this, input);
}
+uint Node::get_uint(const SocketType& input) const
+{
+ assert(input.type == SocketType::UINT);
+ return get_socket_value<uint>(this, input);
+}
+
float Node::get_float(const SocketType& input) const
{
assert(input.type == SocketType::FLOAT);
@@ -292,7 +305,8 @@ const array<Node*>& Node::get_node_array(const SocketType& input) const
return get_socket_value<array<Node*> >(this, input);
}
-/* default values */
+/* generic value operations */
+
bool Node::has_default_value(const SocketType& input) const
{
const void *src = input.default_value;
@@ -300,6 +314,48 @@ bool Node::has_default_value(const SocketType& input) const
return memcmp(dst, src, input.size()) == 0;
}
+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());
+}
+
+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());
+ }
+}
+
template<typename T>
static bool is_array_equal(const Node *node, const Node *other, const SocketType& socket)
{
@@ -308,48 +364,43 @@ static bool is_array_equal(const Node *node, const Node *other, const SocketType
return *a == *b;
}
-/* modified */
-bool Node::modified(const Node& other)
+bool Node::equals_value(const Node& other, const SocketType& socket) const
+{
+ if(socket.is_array()) {
+ switch(socket.type) {
+ 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);
+ default: assert(0); return true;
+ }
+ }
+ else {
+ const void *a = ((char*)this) + socket.struct_offset;
+ const void *b = ((char*)&other) + socket.struct_offset;
+ return (memcmp(a, b, socket.size()) == 0);
+ }
+}
+
+/* equals */
+
+bool Node::equals(const Node& other) const
{
assert(type == other.type);
- typedef unordered_map<ustring, SocketType, ustringHash> map_type;
- foreach(const map_type::value_type& it, type->inputs) {
- const SocketType& socket = it.second;
-
- if(socket.is_array()) {
- bool equal = true;
-
- switch(socket.type)
- {
- case SocketType::BOOLEAN_ARRAY: equal = is_array_equal<bool>(this, &other, socket); break;
- case SocketType::FLOAT_ARRAY: equal = is_array_equal<float>(this, &other, socket); break;
- case SocketType::INT_ARRAY: equal = is_array_equal<int>(this, &other, socket); break;
- case SocketType::COLOR_ARRAY: equal = is_array_equal<float3>(this, &other, socket); break;
- case SocketType::VECTOR_ARRAY: equal = is_array_equal<float3>(this, &other, socket); break;
- case SocketType::POINT_ARRAY: equal = is_array_equal<float3>(this, &other, socket); break;
- case SocketType::NORMAL_ARRAY: equal = is_array_equal<float3>(this, &other, socket); break;
- case SocketType::POINT2_ARRAY: equal = is_array_equal<float2>(this, &other, socket); break;
- case SocketType::STRING_ARRAY: equal = is_array_equal<ustring>(this, &other, socket); break;
- case SocketType::TRANSFORM_ARRAY: equal = is_array_equal<Transform>(this, &other, socket); break;
- case SocketType::NODE_ARRAY: equal = is_array_equal<void*>(this, &other, socket); break;
- default: assert(0); break;
- }
-
- if(!equal) {
- return true;
- }
- }
- else {
- const void *a = ((char*)this) + socket.struct_offset;
- const void *b = ((char*)&other) + socket.struct_offset;
- if(memcmp(a, b, socket.size()) != 0) {
- return true;
- }
- }
+ foreach(const SocketType& socket, type->inputs) {
+ if(!equals_value(other, socket))
+ return false;
}
- return false;
+ return true;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/graph/node.h b/intern/cycles/graph/node.h
index 33971fa714a..64410f4539b 100644
--- a/intern/cycles/graph/node.h
+++ b/intern/cycles/graph/node.h
@@ -38,9 +38,11 @@ struct 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);
@@ -59,6 +61,7 @@ struct Node
/* 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;
@@ -76,11 +79,14 @@ struct Node
const array<Transform>& get_transform_array(const SocketType& input) const;
const array<Node*>& get_node_array(const SocketType& input) const;
- /* default values */
+ /* 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);
- /* modified */
- bool modified(const Node& other);
+ /* equals */
+ bool equals(const Node& other) const;
ustring name;
const NodeType *type;
diff --git a/intern/cycles/graph/node_type.cpp b/intern/cycles/graph/node_type.cpp
index dc879655d7f..5b98de778ad 100644
--- a/intern/cycles/graph/node_type.cpp
+++ b/intern/cycles/graph/node_type.cpp
@@ -41,6 +41,7 @@ size_t SocketType::size(Type type)
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);
@@ -88,6 +89,7 @@ ustring SocketType::type_name(Type type)
ustring("boolean"),
ustring("float"),
ustring("int"),
+ ustring("uint"),
ustring("color"),
ustring("vector"),
ustring("point"),
@@ -114,9 +116,15 @@ ustring SocketType::type_name(Type type)
return names[(int)type];
}
+bool SocketType::is_float3(Type type)
+{
+ return (type == COLOR || type == VECTOR || type == POINT || type == NORMAL);
+}
+
/* Node Type */
-NodeType::NodeType()
+NodeType::NodeType(Type type_)
+: type(type_)
{
}
@@ -137,7 +145,7 @@ void NodeType::register_input(ustring name, ustring ui_name, SocketType::Type ty
socket.enum_values = enum_values;
socket.node_type = node_type;
socket.flags = flags | extra_flags;
- inputs[name] = socket;
+ inputs.push_back(socket);
}
void NodeType::register_output(ustring name, ustring ui_name, SocketType::Type type)
@@ -151,7 +159,29 @@ void NodeType::register_output(ustring name, ustring ui_name, SocketType::Type t
socket.enum_values = NULL;
socket.node_type = NULL;
socket.flags = SocketType::LINKABLE;
- outputs[name] = socket;
+ outputs.push_back(socket);
+}
+
+const SocketType *NodeType::find_input(ustring name) const
+{
+ foreach(const SocketType& socket, inputs) {
+ if(socket.name == name) {
+ return &socket;
+ }
+ }
+
+ return NULL;
+}
+
+const SocketType *NodeType::find_output(ustring name) const
+{
+ foreach(const SocketType& socket, outputs) {
+ if(socket.name == name) {
+ return &socket;
+ }
+ }
+
+ return NULL;
}
/* Node Type Registry */
@@ -162,7 +192,7 @@ unordered_map<ustring, NodeType, ustringHash>& NodeType::types()
return _types;
}
-NodeType *NodeType::add(const char *name_, CreateFunc create_)
+NodeType *NodeType::add(const char *name_, CreateFunc create_, Type type_)
{
ustring name(name_);
@@ -172,7 +202,7 @@ NodeType *NodeType::add(const char *name_, CreateFunc create_)
return NULL;
}
- types()[name] = NodeType();
+ types()[name] = NodeType(type_);
NodeType *type = &types()[name];
type->name = name;
diff --git a/intern/cycles/graph/node_type.h b/intern/cycles/graph/node_type.h
index 82ddd29da33..60c3244028d 100644
--- a/intern/cycles/graph/node_type.h
+++ b/intern/cycles/graph/node_type.h
@@ -21,6 +21,7 @@
#include "util_map.h"
#include "util_param.h"
#include "util_string.h"
+#include "util_vector.h"
CCL_NAMESPACE_BEGIN
@@ -38,6 +39,7 @@ struct SocketType
BOOLEAN,
FLOAT,
INT,
+ UINT,
COLOR,
VECTOR,
POINT,
@@ -94,13 +96,19 @@ struct SocketType
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
{
- explicit NodeType();
+ enum Type {
+ NONE,
+ SHADER
+ };
+
+ explicit NodeType(Type type = NONE);
~NodeType();
void register_input(ustring name, ustring ui_name, SocketType::Type type,
@@ -110,15 +118,18 @@ struct NodeType
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;
+
typedef Node *(*CreateFunc)(const NodeType *type);
- typedef unordered_map<ustring, SocketType, ustringHash> SocketMap;
ustring name;
- SocketMap inputs;
- SocketMap outputs;
+ Type type;
+ std::vector<SocketType> inputs;
+ std::vector<SocketType> outputs;
CreateFunc create;
- static NodeType *add(const char *name, 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();
};
@@ -144,7 +155,7 @@ const NodeType *structname::register_type()
#define SOCKET_DEFINE(name, ui_name, default_value, datatype, TYPE, flags, ...) \
{ \
static datatype defval = default_value; \
- assert(SOCKET_SIZEOF(T, name) == sizeof(datatype)); \
+ 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__); \
}
@@ -152,6 +163,8 @@ const NodeType *structname::register_type()
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__)
+#define SOCKET_UINT(name, ui_name, default_value, ...) \
+ 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__)
#define SOCKET_COLOR(name, ui_name, default_value, ...) \
diff --git a/intern/cycles/graph/node_xml.cpp b/intern/cycles/graph/node_xml.cpp
index fe06a243998..590e09645ed 100644
--- a/intern/cycles/graph/node_xml.cpp
+++ b/intern/cycles/graph/node_xml.cpp
@@ -58,9 +58,7 @@ void xml_read_node(XMLReader& reader, Node *node, pugi::xml_node xml_node)
node->name = ustring(name_attr.value());
}
- foreach(const NodeType::SocketMap::value_type& it, node->type->inputs) {
- const SocketType& socket = it.second;
-
+ foreach(const SocketType& socket, node->type->inputs) {
if(socket.type == SocketType::CLOSURE || socket.type == SocketType::UNDEFINED) {
continue;
}
@@ -110,6 +108,11 @@ void xml_read_node(XMLReader& reader, Node *node, pugi::xml_node xml_node)
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;
@@ -117,8 +120,9 @@ void xml_read_node(XMLReader& reader, Node *node, pugi::xml_node xml_node)
array<int> value;
value.resize(tokens.size());
- for(size_t i = 0; i < value.size(); i++)
+ for(size_t i = 0; i < value.size(); i++) {
value[i] = (int)atoi(attr.value());
+ }
node->set(socket, value);
break;
}
@@ -127,7 +131,7 @@ void xml_read_node(XMLReader& reader, Node *node, pugi::xml_node xml_node)
case SocketType::POINT:
case SocketType::NORMAL:
{
- array<float> value;
+ array<float3> value;
xml_read_float_array<3>(value, attr);
if(value.size() == 1) {
node->set(socket, value[0]);
@@ -161,11 +165,21 @@ void xml_read_node(XMLReader& reader, Node *node, pugi::xml_node xml_node)
break;
}
case SocketType::STRING:
- case SocketType::ENUM:
{
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;
@@ -173,8 +187,9 @@ void xml_read_node(XMLReader& reader, Node *node, pugi::xml_node xml_node)
array<ustring> value;
value.resize(tokens.size());
- for(size_t i = 0; i < value.size(); i++)
+ for(size_t i = 0; i < value.size(); i++) {
value[i] = ustring(tokens[i]);
+ }
node->set(socket, value);
break;
}
@@ -245,9 +260,7 @@ pugi::xml_node xml_write_node(Node *node, pugi::xml_node xml_root)
xml_node.append_attribute("name") = node->name.c_str();
- foreach(const NodeType::SocketMap::value_type& it, node->type->inputs) {
- const SocketType& socket = it.second;
-
+ foreach(const SocketType& socket, node->type->inputs) {
if(socket.type == SocketType::CLOSURE || socket.type == SocketType::UNDEFINED) {
continue;
}
@@ -302,6 +315,11 @@ pugi::xml_node xml_write_node(Node *node, pugi::xml_node xml_root)
attr = node->get_int(socket);
break;
}
+ case SocketType::UINT:
+ {
+ attr = node->get_uint(socket);
+ break;
+ }
case SocketType::INT_ARRAY:
{
std::stringstream ss;
diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt
index b8f8aa03510..28695a2ebf9 100644
--- a/intern/cycles/kernel/CMakeLists.txt
+++ b/intern/cycles/kernel/CMakeLists.txt
@@ -28,6 +28,22 @@ set(SRC
kernels/cuda/kernel.cu
)
+set(SRC_BVH_HEADERS
+ bvh/bvh.h
+ bvh/bvh_nodes.h
+ bvh/bvh_shadow_all.h
+ bvh/bvh_subsurface.h
+ bvh/bvh_traversal.h
+ bvh/bvh_volume.h
+ bvh/bvh_volume_all.h
+ bvh/qbvh_nodes.h
+ bvh/qbvh_shadow_all.h
+ bvh/qbvh_subsurface.h
+ bvh/qbvh_traversal.h
+ bvh/qbvh_volume.h
+ bvh/qbvh_volume_all.h
+)
+
set(SRC_HEADERS
kernel_accumulate.h
kernel_bake.h
@@ -71,11 +87,14 @@ set(SRC_KERNELS_CPU_HEADERS
)
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
@@ -102,6 +121,7 @@ set(SRC_SVM_HEADERS
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
@@ -125,6 +145,7 @@ set(SRC_SVM_HEADERS
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
@@ -141,23 +162,12 @@ set(SRC_SVM_HEADERS
set(SRC_GEOM_HEADERS
geom/geom.h
geom/geom_attribute.h
- geom/geom_bvh.h
- geom/geom_bvh_shadow.h
- geom/geom_bvh_subsurface.h
- geom/geom_bvh_traversal.h
- geom/geom_bvh_volume.h
- geom/geom_bvh_volume_all.h
geom/geom_curve.h
geom/geom_motion_curve.h
geom/geom_motion_triangle.h
geom/geom_object.h
geom/geom_primitive.h
- geom/geom_qbvh.h
- geom/geom_qbvh_shadow.h
- geom/geom_qbvh_subsurface.h
- geom/geom_qbvh_traversal.h
- geom/geom_qbvh_volume.h
- geom/geom_qbvh_volume_all.h
+ geom/geom_subd_triangle.h
geom/geom_triangle.h
geom/geom_triangle_intersect.h
geom/geom_volume.h
@@ -213,7 +223,14 @@ if(WITH_CYCLES_CUDA_BINARIES)
endif()
# build for each arch
- set(cuda_sources kernels/cuda/kernel.cu ${SRC_HEADERS} ${SRC_SVM_HEADERS} ${SRC_GEOM_HEADERS} ${SRC_CLOSURE_HEADERS} ${SRC_UTIL_HEADERS})
+ set(cuda_sources kernels/cuda/kernel.cu
+ ${SRC_HEADERS}
+ ${SRC_BVH_HEADERS}
+ ${SRC_SVM_HEADERS}
+ ${SRC_GEOM_HEADERS}
+ ${SRC_CLOSURE_HEADERS}
+ ${SRC_UTIL_HEADERS}
+ )
set(cuda_cubins)
macro(CYCLES_CUDA_KERNEL_ADD arch experimental)
@@ -238,6 +255,7 @@ if(WITH_CYCLES_CUDA_BINARIES)
OUTPUT ${cuda_cubin}
COMMAND ${CUDA_NVCC_EXECUTABLE}
-arch=${arch}
+ ${CUDA_NVCC_FLAGS}
-m${CUDA_BITS}
--cubin ${CMAKE_CURRENT_SOURCE_DIR}/kernels/cuda/kernel.cu
-o ${CMAKE_CURRENT_BINARY_DIR}/${cuda_cubin}
@@ -312,6 +330,7 @@ add_library(cycles_kernel
${SRC}
${SRC_HEADERS}
${SRC_KERNELS_CPU_HEADERS}
+ ${SRC_BVH_HEADERS}
${SRC_CLOSURE_HEADERS}
${SRC_SVM_HEADERS}
${SRC_GEOM_HEADERS}
@@ -346,6 +365,7 @@ delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_next_iteratio
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_sum_all_radiance.cl" ${CYCLES_INSTALL_PATH}/kernel/kernels/opencl)
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/cuda/kernel.cu" ${CYCLES_INSTALL_PATH}/kernel/kernels/cuda)
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_HEADERS}" ${CYCLES_INSTALL_PATH}/kernel)
+delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_BVH_HEADERS}" ${CYCLES_INSTALL_PATH}/kernel/bvh)
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_CLOSURE_HEADERS}" ${CYCLES_INSTALL_PATH}/kernel/closure)
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_SVM_HEADERS}" ${CYCLES_INSTALL_PATH}/kernel/svm)
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_GEOM_HEADERS}" ${CYCLES_INSTALL_PATH}/kernel/geom)
diff --git a/intern/cycles/kernel/geom/geom_bvh.h b/intern/cycles/kernel/bvh/bvh.h
index 9eadc97386c..59881738195 100644
--- a/intern/cycles/kernel/geom/geom_bvh.h
+++ b/intern/cycles/kernel/bvh/bvh.h
@@ -35,6 +35,13 @@ CCL_NAMESPACE_BEGIN
# define ccl_device_intersect ccl_device_inline
#endif
+/* bottom-most stack entry, indicating the end of traversal */
+#define ENTRYPOINT_SENTINEL 0x76543210
+
+/* 64 object BVH + 64 mesh BVH + 64 object node splitting */
+#define BVH_STACK_SIZE 192
+#define BVH_QSTACK_SIZE 384
+
/* BVH intersection function variations */
#define BVH_INSTANCING 1
@@ -48,73 +55,97 @@ CCL_NAMESPACE_BEGIN
#define BVH_FEATURE(f) (((BVH_FUNCTION_FEATURES) & (f)) != 0)
+/* Debugging heleprs */
+#ifdef __KERNEL_DEBUG__
+# define BVH_DEBUG_INIT() \
+ do { \
+ isect->num_traversal_steps = 0; \
+ isect->num_traversed_instances = 0; \
+ } while(0)
+# define BVH_DEBUG_NEXT_STEP() \
+ do { \
+ ++isect->num_traversal_steps; \
+ } while(0)
+# define BVH_DEBUG_NEXT_INSTANCE() \
+ do { \
+ ++isect->num_traversed_instances; \
+ } while(0)
+#else /* __KERNEL_DEBUG__ */
+# define BVH_DEBUG_INIT()
+# define BVH_DEBUG_NEXT_STEP()
+# define BVH_DEBUG_NEXT_INSTANCE()
+#endif /* __KERNEL_DEBUG__ */
+
+
/* Common QBVH functions. */
#ifdef __QBVH__
-# include "geom_qbvh.h"
+# include "qbvh_nodes.h"
#endif
/* Regular BVH traversal */
+#include "bvh_nodes.h"
+
#define BVH_FUNCTION_NAME bvh_intersect
#define BVH_FUNCTION_FEATURES 0
-#include "geom_bvh_traversal.h"
+#include "bvh_traversal.h"
#if defined(__INSTANCING__)
# define BVH_FUNCTION_NAME bvh_intersect_instancing
# define BVH_FUNCTION_FEATURES BVH_INSTANCING
-# include "geom_bvh_traversal.h"
+# include "bvh_traversal.h"
#endif
#if defined(__HAIR__)
# define BVH_FUNCTION_NAME bvh_intersect_hair
# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR|BVH_HAIR_MINIMUM_WIDTH
-# include "geom_bvh_traversal.h"
+# include "bvh_traversal.h"
#endif
#if defined(__OBJECT_MOTION__)
# define BVH_FUNCTION_NAME bvh_intersect_motion
# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_MOTION
-# include "geom_bvh_traversal.h"
+# include "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
-# include "geom_bvh_traversal.h"
+# include "bvh_traversal.h"
#endif
/* Subsurface scattering BVH traversal */
#if defined(__SUBSURFACE__)
# define BVH_FUNCTION_NAME bvh_intersect_subsurface
-# define BVH_FUNCTION_FEATURES 0
-# include "geom_bvh_subsurface.h"
+# define BVH_FUNCTION_FEATURES BVH_HAIR
+# include "bvh_subsurface.h"
#endif
#if defined(__SUBSURFACE__) && defined(__OBJECT_MOTION__)
# define BVH_FUNCTION_NAME bvh_intersect_subsurface_motion
-# define BVH_FUNCTION_FEATURES BVH_MOTION
-# include "geom_bvh_subsurface.h"
+# define BVH_FUNCTION_FEATURES BVH_MOTION|BVH_HAIR
+# include "bvh_subsurface.h"
#endif
/* Volume BVH traversal */
#if defined(__VOLUME__)
# define BVH_FUNCTION_NAME bvh_intersect_volume
-# define BVH_FUNCTION_FEATURES 0
-# include "geom_bvh_volume.h"
+# define BVH_FUNCTION_FEATURES BVH_HAIR
+# include "bvh_volume.h"
#endif
#if defined(__VOLUME__) && defined(__INSTANCING__)
# define BVH_FUNCTION_NAME bvh_intersect_volume_instancing
-# define BVH_FUNCTION_FEATURES BVH_INSTANCING
-# include "geom_bvh_volume.h"
+# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR
+# include "bvh_volume.h"
#endif
#if defined(__VOLUME__) && defined(__OBJECT_MOTION__)
# define BVH_FUNCTION_NAME bvh_intersect_volume_motion
-# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_MOTION
-# include "geom_bvh_volume.h"
+# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_MOTION|BVH_HAIR
+# include "bvh_volume.h"
#endif
/* Record all intersections - Shadow BVH traversal */
@@ -122,51 +153,51 @@ CCL_NAMESPACE_BEGIN
#if defined(__SHADOW_RECORD_ALL__)
# define BVH_FUNCTION_NAME bvh_intersect_shadow_all
# define BVH_FUNCTION_FEATURES 0
-# include "geom_bvh_shadow.h"
+# include "bvh_shadow_all.h"
#endif
#if defined(__SHADOW_RECORD_ALL__) && defined(__INSTANCING__)
# define BVH_FUNCTION_NAME bvh_intersect_shadow_all_instancing
# define BVH_FUNCTION_FEATURES BVH_INSTANCING
-# include "geom_bvh_shadow.h"
+# include "bvh_shadow_all.h"
#endif
#if defined(__SHADOW_RECORD_ALL__) && defined(__HAIR__)
# define BVH_FUNCTION_NAME bvh_intersect_shadow_all_hair
# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR
-# include "geom_bvh_shadow.h"
+# include "bvh_shadow_all.h"
#endif
#if defined(__SHADOW_RECORD_ALL__) && defined(__OBJECT_MOTION__)
# define BVH_FUNCTION_NAME bvh_intersect_shadow_all_motion
# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_MOTION
-# include "geom_bvh_shadow.h"
+# include "bvh_shadow_all.h"
#endif
#if defined(__SHADOW_RECORD_ALL__) && 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
-# include "geom_bvh_shadow.h"
+# include "bvh_shadow_all.h"
#endif
/* Record all intersections - Volume BVH traversal */
#if defined(__VOLUME_RECORD_ALL__)
# define BVH_FUNCTION_NAME bvh_intersect_volume_all
-# define BVH_FUNCTION_FEATURES 0
-# include "geom_bvh_volume_all.h"
+# define BVH_FUNCTION_FEATURES BVH_HAIR
+# include "bvh_volume_all.h"
#endif
#if defined(__VOLUME_RECORD_ALL__) && defined(__INSTANCING__)
# define BVH_FUNCTION_NAME bvh_intersect_volume_all_instancing
-# define BVH_FUNCTION_FEATURES BVH_INSTANCING
-# include "geom_bvh_volume_all.h"
+# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR
+# include "bvh_volume_all.h"
#endif
#if defined(__VOLUME_RECORD_ALL__) && defined(__OBJECT_MOTION__)
# define BVH_FUNCTION_NAME bvh_intersect_volume_all_motion
-# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_MOTION
-# include "geom_bvh_volume_all.h"
+# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_MOTION|BVH_HAIR
+# include "bvh_volume_all.h"
#endif
#undef BVH_FEATURE
diff --git a/intern/cycles/kernel/bvh/bvh_nodes.h b/intern/cycles/kernel/bvh/bvh_nodes.h
new file mode 100644
index 00000000000..db2275b0ff8
--- /dev/null
+++ b/intern/cycles/kernel/bvh/bvh_nodes.h
@@ -0,0 +1,656 @@
+/*
+ * Copyright 2011-2016, Blender Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// TODO(sergey): Look into avoid use of full Transform and use 3x3 matrix and
+// 3-vector which might be faster.
+ccl_device_inline Transform bvh_unaligned_node_fetch_space(KernelGlobals *kg,
+ 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);
+ space.w = make_float4(0.0f, 0.0f, 0.0f, 1.0f);
+ return space;
+}
+
+#if !defined(__KERNEL_SSE2__)
+ccl_device_inline int bvh_aligned_node_intersect(KernelGlobals *kg,
+ const float3 P,
+ const float3 idir,
+ const float t,
+ const int node_addr,
+ const uint visibility,
+ 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(min(c0lox, c0hix), min(c0loy, c0hiy), min(c0loz, c0hiz), 0.0f);
+ float c0max = min4(max(c0lox, c0hix), max(c0loy, c0hiy), max(c0loz, c0hiz), t);
+
+ 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(min(c1lox, c1hix), min(c1loy, c1hiy), min(c1loz, c1hiz), 0.0f);
+ float c1max = min4(max(c1lox, c1hix), max(c1loy, c1hiy), max(c1loz, c1hiz), t);
+
+ 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_inline int bvh_aligned_node_intersect_robust(KernelGlobals *kg,
+ const float3 P,
+ const float3 idir,
+ const float t,
+ const float difl,
+ const float extmax,
+ const int node_addr,
+ const uint visibility,
+ 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(min(c0lox, c0hix), min(c0loy, c0hiy), min(c0loz, c0hiz), 0.0f);
+ float c0max = min4(max(c0lox, c0hix), max(c0loy, c0hiy), max(c0loz, c0hiz), t);
+
+ 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(min(c1lox, c1hix), min(c1loy, c1hiy), min(c1loz, c1hiz), 0.0f);
+ float c1max = min4(max(c1lox, c1hix), max(c1loy, c1hiy), max(c1loz, c1hiz), t);
+
+ 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_inline 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;
+}
+
+ccl_device_inline 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;
+ }
+}
+
+ccl_device_inline int bvh_unaligned_node_intersect(KernelGlobals *kg,
+ const float3 P,
+ const float3 dir,
+ const float3 idir,
+ const float t,
+ const int node_addr,
+ 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;
+}
+
+ccl_device_inline int bvh_unaligned_node_intersect_robust(KernelGlobals *kg,
+ const float3 P,
+ const float3 dir,
+ const float3 idir,
+ const float t,
+ const float difl,
+ const float extmax,
+ const int node_addr,
+ 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;
+}
+
+ccl_device_inline int bvh_node_intersect(KernelGlobals *kg,
+ const float3 P,
+ const float3 dir,
+ const float3 idir,
+ const float t,
+ const int node_addr,
+ 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);
+ }
+}
+
+ccl_device_inline int bvh_node_intersect_robust(KernelGlobals *kg,
+ const float3 P,
+ const float3 dir,
+ const float3 idir,
+ const float t,
+ const float difl,
+ const float extmax,
+ const int node_addr,
+ 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);
+ }
+}
+#else /* !defined(__KERNEL_SSE2__) */
+
+int ccl_device_inline 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));
+
+ /* 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];
+
+ /* 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];
+
+ 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;
+# else
+ return mask & 3;
+# endif
+}
+
+int ccl_device_inline 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);
+
+# 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;
+# else
+ return mask & 3;
+# endif
+}
+
+int ccl_device_inline bvh_unaligned_node_intersect(KernelGlobals *kg,
+ const float3 P,
+ const float3 dir,
+ 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(tnear_x, tnear_y, tnear_z, isect_near);
+ const ssef tfar = min4(tfar_x, tfar_y, tfar_z, isect_far);
+ 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;
+# else
+ return mask & 3;
+# endif
+}
+
+int ccl_device_inline bvh_unaligned_node_intersect_robust(KernelGlobals *kg,
+ const float3 P,
+ const float3 dir,
+ 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(tnear_x, tnear_y, tnear_z, isect_near);
+ const ssef tfar = min4(tfar_x, tfar_y, tfar_z, isect_far);
+ 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;
+# else
+ return mask & 3;
+# endif
+}
+
+ccl_device_inline int bvh_node_intersect(KernelGlobals *kg,
+ 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],
+ const int node_addr,
+ 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);
+ }
+}
+
+ccl_device_inline 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 ssef Psplat[3],
+ const ssef idirsplat[3],
+ const shuffle_swap_t shufflexyz[3],
+ const float difl,
+ const float extmax,
+ const int node_addr,
+ 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);
+ }
+}
+#endif /* !defined(__KERNEL_SSE2__) */
diff --git a/intern/cycles/kernel/geom/geom_bvh_shadow.h b/intern/cycles/kernel/bvh/bvh_shadow_all.h
index 4005489f77d..1d6fa303d3e 100644
--- a/intern/cycles/kernel/geom/geom_bvh_shadow.h
+++ b/intern/cycles/kernel/bvh/bvh_shadow_all.h
@@ -18,7 +18,13 @@
*/
#ifdef __QBVH__
-# include "geom_qbvh_shadow.h"
+# include "qbvh_shadow_all.h"
+#endif
+
+#if BVH_FEATURE(BVH_HAIR)
+# define NODE_INTERSECT bvh_node_intersect
+#else
+# define NODE_INTERSECT bvh_aligned_node_intersect
#endif
/* This is a template BVH traversal function, where various features can be
@@ -41,14 +47,14 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
* - likely and unlikely for if() statements
* - test restrict attribute for pointers
*/
-
+
/* traversal stack in CUDA thread-local memory */
- int traversalStack[BVH_STACK_SIZE];
- traversalStack[0] = ENTRYPOINT_SENTINEL;
+ int traversal_stack[BVH_STACK_SIZE];
+ traversal_stack[0] = ENTRYPOINT_SENTINEL;
/* traversal variables in registers */
- int stackPtr = 0;
- int nodeAddr = kernel_data.bvh.root;
+ int stack_ptr = 0;
+ int node_addr = kernel_data.bvh.root;
/* ray parameters in registers */
const float tmax = ray->t;
@@ -72,9 +78,12 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
#if defined(__KERNEL_SSE2__)
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];
+# if BVH_FEATURE(BVH_HAIR)
+ ssef tnear(0.0f), tfar(isect_t);
+# endif
shuffle_swap_t shufflexyz[3];
Psplat[0] = ssef(P.x);
@@ -93,130 +102,87 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
do {
do {
/* traverse internal nodes */
- while(nodeAddr >= 0 && nodeAddr != ENTRYPOINT_SENTINEL) {
- bool traverseChild0, traverseChild1;
- int nodeAddrChild1;
+ while(node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) {
+ int node_addr_ahild1, traverse_mask;
+ float dist[2];
+ float4 cnodes = kernel_tex_fetch(__bvh_nodes, node_addr+0);
#if !defined(__KERNEL_SSE2__)
- /* Intersect two child bounding boxes, non-SSE version */
- float t = isect_t;
-
- /* fetch node data */
- float4 node0 = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+0);
- float4 node1 = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+1);
- float4 node2 = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+2);
- float4 cnodes = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+3);
-
- /* intersect ray against child nodes */
- NO_EXTENDED_PRECISION float c0lox = (node0.x - P.x) * idir.x;
- NO_EXTENDED_PRECISION float c0hix = (node0.z - P.x) * idir.x;
- NO_EXTENDED_PRECISION float c0loy = (node1.x - P.y) * idir.y;
- NO_EXTENDED_PRECISION float c0hiy = (node1.z - P.y) * idir.y;
- NO_EXTENDED_PRECISION float c0loz = (node2.x - P.z) * idir.z;
- NO_EXTENDED_PRECISION float c0hiz = (node2.z - P.z) * idir.z;
- NO_EXTENDED_PRECISION float c0min = max4(min(c0lox, c0hix), min(c0loy, c0hiy), min(c0loz, c0hiz), 0.0f);
- NO_EXTENDED_PRECISION float c0max = min4(max(c0lox, c0hix), max(c0loy, c0hiy), max(c0loz, c0hiz), t);
-
- NO_EXTENDED_PRECISION float c1lox = (node0.y - P.x) * idir.x;
- NO_EXTENDED_PRECISION float c1hix = (node0.w - P.x) * idir.x;
- NO_EXTENDED_PRECISION float c1loy = (node1.y - P.y) * idir.y;
- NO_EXTENDED_PRECISION float c1hiy = (node1.w - P.y) * idir.y;
- NO_EXTENDED_PRECISION float c1loz = (node2.y - P.z) * idir.z;
- NO_EXTENDED_PRECISION float c1hiz = (node2.w - P.z) * idir.z;
- NO_EXTENDED_PRECISION float c1min = max4(min(c1lox, c1hix), min(c1loy, c1hiy), min(c1loz, c1hiz), 0.0f);
- NO_EXTENDED_PRECISION float c1max = min4(max(c1lox, c1hix), max(c1loy, c1hiy), max(c1loz, c1hiz), t);
-
- /* decide which nodes to traverse next */
-# ifdef __VISIBILITY_FLAG__
- /* this visibility test gives a 5% performance hit, how to solve? */
- traverseChild0 = (c0max >= c0min) && (__float_as_uint(cnodes.z) & PATH_RAY_SHADOW);
- traverseChild1 = (c1max >= c1min) && (__float_as_uint(cnodes.w) & PATH_RAY_SHADOW);
-# else
- traverseChild0 = (c0max >= c0min);
- traverseChild1 = (c1max >= c1min);
+ traverse_mask = NODE_INTERSECT(kg,
+ P,
+# if BVH_FEATURE(BVH_HAIR)
+ dir,
# endif
-
+ idir,
+ isect_t,
+ node_addr,
+ PATH_RAY_SHADOW,
+ dist);
#else // __KERNEL_SSE2__
- /* Intersect two child bounding boxes, SSE3 version adapted from Embree */
-
- /* fetch node data */
- const ssef *bvh_nodes = (ssef*)kg->__bvh_nodes.data + nodeAddr*BVH_NODE_SIZE;
- const float4 cnodes = ((float4*)bvh_nodes)[3];
-
- /* intersect ray against child nodes */
- const ssef tminmaxx = (shuffle_swap(bvh_nodes[0], shufflexyz[0]) - Psplat[0]) * idirsplat[0];
- const ssef tminmaxy = (shuffle_swap(bvh_nodes[1], shufflexyz[1]) - Psplat[1]) * idirsplat[1];
- const ssef tminmaxz = (shuffle_swap(bvh_nodes[2], shufflexyz[2]) - Psplat[2]) * idirsplat[2];
-
- /* calculate { c0min, c1min, -c0max, -c1max} */
- const ssef minmax = max(max(tminmaxx, tminmaxy), max(tminmaxz, tsplat));
- const ssef tminmax = minmax ^ pn;
- const sseb lrhit = tminmax <= shuffle<2, 3, 0, 1>(tminmax);
-
- /* decide which nodes to traverse next */
-# ifdef __VISIBILITY_FLAG__
- /* this visibility test gives a 5% performance hit, how to solve? */
- traverseChild0 = (movemask(lrhit) & 1) && (__float_as_uint(cnodes.z) & PATH_RAY_SHADOW);
- traverseChild1 = (movemask(lrhit) & 2) && (__float_as_uint(cnodes.w) & PATH_RAY_SHADOW);
-# else
- traverseChild0 = (movemask(lrhit) & 1);
- traverseChild1 = (movemask(lrhit) & 2);
+ traverse_mask = NODE_INTERSECT(kg,
+ P,
+ dir,
+# if BVH_FEATURE(BVH_HAIR)
+ tnear,
+ tfar,
# endif
+ tsplat,
+ Psplat,
+ idirsplat,
+ shufflexyz,
+ node_addr,
+ PATH_RAY_SHADOW,
+ dist);
#endif // __KERNEL_SSE2__
- nodeAddr = __float_as_int(cnodes.x);
- nodeAddrChild1 = __float_as_int(cnodes.y);
-
- if(traverseChild0 && traverseChild1) {
- /* both children were intersected, push the farther one */
-#if !defined(__KERNEL_SSE2__)
- bool closestChild1 = (c1min < c0min);
-#else
- bool closestChild1 = tminmax[1] < tminmax[0];
-#endif
+ node_addr = __float_as_int(cnodes.z);
+ node_addr_ahild1 = __float_as_int(cnodes.w);
- if(closestChild1) {
- int tmp = nodeAddr;
- nodeAddr = nodeAddrChild1;
- nodeAddrChild1 = 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_ahild1;
+ node_addr_ahild1 = tmp;
}
- ++stackPtr;
- kernel_assert(stackPtr < BVH_STACK_SIZE);
- traversalStack[stackPtr] = nodeAddrChild1;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_STACK_SIZE);
+ traversal_stack[stack_ptr] = node_addr_ahild1;
}
else {
- /* one child was intersected */
- if(traverseChild1) {
- nodeAddr = nodeAddrChild1;
+ /* One child was intersected. */
+ if(traverse_mask == 2) {
+ node_addr = node_addr_ahild1;
}
- else if(!traverseChild0) {
- /* neither child was intersected */
- nodeAddr = traversalStack[stackPtr];
- --stackPtr;
+ 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(nodeAddr < 0) {
- float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-nodeAddr-1)*BVH_NODE_LEAF_SIZE);
- int primAddr = __float_as_int(leaf.x);
+ 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(primAddr >= 0) {
+ if(prim_addr >= 0) {
#endif
- const int primAddr2 = __float_as_int(leaf.y);
+ 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 */
- nodeAddr = traversalStack[stackPtr];
- --stackPtr;
+ node_addr = traversal_stack[stack_ptr];
+ --stack_ptr;
/* primitive intersection */
- while(primAddr < primAddr2) {
- kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ while(prim_addr < prim_addr2) {
+ kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
bool hit;
@@ -226,22 +192,57 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
switch(p_type) {
case PRIMITIVE_TRIANGLE: {
- hit = triangle_intersect(kg, &isect_precalc, isect_array, P, PATH_RAY_SHADOW, object, primAddr);
+ hit = triangle_intersect(kg,
+ &isect_precalc,
+ isect_array,
+ P,
+ PATH_RAY_SHADOW,
+ object,
+ prim_addr);
break;
}
#if BVH_FEATURE(BVH_MOTION)
case PRIMITIVE_MOTION_TRIANGLE: {
- hit = motion_triangle_intersect(kg, isect_array, P, dir, ray->time, PATH_RAY_SHADOW, object, primAddr);
+ 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: {
- if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
- hit = bvh_cardinal_curve_intersect(kg, isect_array, P, dir, PATH_RAY_SHADOW, object, primAddr, ray->time, type, NULL, 0, 0);
- else
- hit = bvh_curve_intersect(kg, isect_array, P, dir, PATH_RAY_SHADOW, object, primAddr, ray->time, type, NULL, 0, 0);
+ if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE) {
+ hit = bvh_cardinal_curve_intersect(kg,
+ isect_array,
+ P,
+ dir,
+ PATH_RAY_SHADOW,
+ object,
+ prim_addr,
+ ray->time,
+ type,
+ NULL,
+ 0, 0);
+ }
+ else {
+ hit = bvh_curve_intersect(kg,
+ isect_array,
+ P,
+ dir,
+ PATH_RAY_SHADOW,
+ object,
+ prim_addr,
+ ray->time,
+ type,
+ NULL,
+ 0, 0);
+ }
break;
}
#endif
@@ -293,13 +294,13 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
isect_array->t = isect_t;
}
- primAddr++;
+ prim_addr++;
}
}
#if BVH_FEATURE(BVH_INSTANCING)
else {
/* instance push */
- object = kernel_tex_fetch(__prim_object, -primAddr-1);
+ object = kernel_tex_fetch(__prim_object, -prim_addr-1);
# if BVH_FEATURE(BVH_MOTION)
bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &isect_t, &ob_itfm);
@@ -317,21 +318,24 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
Psplat[2] = ssef(P.z);
tsplat = ssef(0.0f, 0.0f, -isect_t, -isect_t);
+# if BVH_FEATURE(BVH_HAIR)
+ tfar = ssef(isect_t);
+# endif
gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
# endif
- ++stackPtr;
- kernel_assert(stackPtr < BVH_STACK_SIZE);
- traversalStack[stackPtr] = ENTRYPOINT_SENTINEL;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_STACK_SIZE);
+ traversal_stack[stack_ptr] = ENTRYPOINT_SENTINEL;
- nodeAddr = kernel_tex_fetch(__object_node, object);
+ node_addr = kernel_tex_fetch(__object_node, object);
}
}
#endif /* FEATURE(BVH_INSTANCING) */
- } while(nodeAddr != ENTRYPOINT_SENTINEL);
+ } while(node_addr != ENTRYPOINT_SENTINEL);
#if BVH_FEATURE(BVH_INSTANCING)
- if(stackPtr >= 0) {
+ if(stack_ptr >= 0) {
kernel_assert(object != OBJECT_NONE);
if(num_hits_in_instance) {
@@ -369,15 +373,18 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
Psplat[2] = ssef(P.z);
tsplat = ssef(0.0f, 0.0f, -isect_t, -isect_t);
+# if BVH_FEATURE(BVH_HAIR)
+ tfar = ssef(isect_t);
+# endif
gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
# endif
object = OBJECT_NONE;
- nodeAddr = traversalStack[stackPtr];
- --stackPtr;
+ node_addr = traversal_stack[stack_ptr];
+ --stack_ptr;
}
#endif /* FEATURE(BVH_INSTANCING) */
- } while(nodeAddr != ENTRYPOINT_SENTINEL);
+ } while(node_addr != ENTRYPOINT_SENTINEL);
return false;
}
@@ -410,3 +417,4 @@ ccl_device_inline bool BVH_FUNCTION_NAME(KernelGlobals *kg,
#undef BVH_FUNCTION_NAME
#undef BVH_FUNCTION_FEATURES
+#undef NODE_INTERSECT
diff --git a/intern/cycles/kernel/geom/geom_bvh_subsurface.h b/intern/cycles/kernel/bvh/bvh_subsurface.h
index 915e9415c93..18978efcfa3 100644
--- a/intern/cycles/kernel/geom/geom_bvh_subsurface.h
+++ b/intern/cycles/kernel/bvh/bvh_subsurface.h
@@ -18,7 +18,13 @@
*/
#ifdef __QBVH__
-# include "geom_qbvh_subsurface.h"
+# include "qbvh_subsurface.h"
+#endif
+
+#if BVH_FEATURE(BVH_HAIR)
+# define NODE_INTERSECT bvh_node_intersect
+#else
+# define NODE_INTERSECT bvh_aligned_node_intersect
#endif
/* This is a template BVH traversal function for subsurface scattering, where
@@ -44,12 +50,12 @@ ccl_device void BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
*/
/* traversal stack in CUDA thread-local memory */
- int traversalStack[BVH_STACK_SIZE];
- traversalStack[0] = ENTRYPOINT_SENTINEL;
+ int traversal_stack[BVH_STACK_SIZE];
+ traversal_stack[0] = ENTRYPOINT_SENTINEL;
/* traversal variables in registers */
- int stackPtr = 0;
- int nodeAddr = kernel_tex_fetch(__object_node, subsurface_object);
+ int stack_ptr = 0;
+ int node_addr = kernel_tex_fetch(__object_node, subsurface_object);
/* ray parameters in registers */
float3 P = ray->P;
@@ -84,6 +90,9 @@ ccl_device void BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
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);
+# endif
shuffle_swap_t shufflexyz[3];
Psplat[0] = ssef(P.x);
@@ -100,127 +109,94 @@ ccl_device void BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
/* traversal loop */
do {
- do
- {
+ do {
/* traverse internal nodes */
- while(nodeAddr >= 0 && nodeAddr != ENTRYPOINT_SENTINEL)
- {
- bool traverseChild0, traverseChild1;
- int nodeAddrChild1;
+ 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__)
- /* Intersect two child bounding boxes, non-SSE version */
- float t = isect_t;
-
- /* fetch node data */
- float4 node0 = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+0);
- float4 node1 = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+1);
- float4 node2 = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+2);
- float4 cnodes = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+3);
-
- /* intersect ray against child nodes */
- NO_EXTENDED_PRECISION float c0lox = (node0.x - P.x) * idir.x;
- NO_EXTENDED_PRECISION float c0hix = (node0.z - P.x) * idir.x;
- NO_EXTENDED_PRECISION float c0loy = (node1.x - P.y) * idir.y;
- NO_EXTENDED_PRECISION float c0hiy = (node1.z - P.y) * idir.y;
- NO_EXTENDED_PRECISION float c0loz = (node2.x - P.z) * idir.z;
- NO_EXTENDED_PRECISION float c0hiz = (node2.z - P.z) * idir.z;
- NO_EXTENDED_PRECISION float c0min = max4(min(c0lox, c0hix), min(c0loy, c0hiy), min(c0loz, c0hiz), 0.0f);
- NO_EXTENDED_PRECISION float c0max = min4(max(c0lox, c0hix), max(c0loy, c0hiy), max(c0loz, c0hiz), t);
-
- NO_EXTENDED_PRECISION float c1lox = (node0.y - P.x) * idir.x;
- NO_EXTENDED_PRECISION float c1hix = (node0.w - P.x) * idir.x;
- NO_EXTENDED_PRECISION float c1loy = (node1.y - P.y) * idir.y;
- NO_EXTENDED_PRECISION float c1hiy = (node1.w - P.y) * idir.y;
- NO_EXTENDED_PRECISION float c1loz = (node2.y - P.z) * idir.z;
- NO_EXTENDED_PRECISION float c1hiz = (node2.w - P.z) * idir.z;
- NO_EXTENDED_PRECISION float c1min = max4(min(c1lox, c1hix), min(c1loy, c1hiy), min(c1loz, c1hiz), 0.0f);
- NO_EXTENDED_PRECISION float c1max = min4(max(c1lox, c1hix), max(c1loy, c1hiy), max(c1loz, c1hiz), t);
-
- /* decide which nodes to traverse next */
- traverseChild0 = (c0max >= c0min);
- traverseChild1 = (c1max >= c1min);
-
+ traverse_mask = NODE_INTERSECT(kg,
+ P,
+# if BVH_FEATURE(BVH_HAIR)
+ dir,
+# endif
+ idir,
+ isect_t,
+ node_addr,
+ PATH_RAY_ALL_VISIBILITY,
+ dist);
#else // __KERNEL_SSE2__
- /* Intersect two child bounding boxes, SSE3 version adapted from Embree */
-
- /* fetch node data */
- const ssef *bvh_nodes = (ssef*)kg->__bvh_nodes.data + nodeAddr*BVH_NODE_SIZE;
- const float4 cnodes = ((float4*)bvh_nodes)[3];
-
- /* intersect ray against child nodes */
- const ssef tminmaxx = (shuffle_swap(bvh_nodes[0], shufflexyz[0]) - Psplat[0]) * idirsplat[0];
- const ssef tminmaxy = (shuffle_swap(bvh_nodes[1], shufflexyz[1]) - Psplat[1]) * idirsplat[1];
- const ssef tminmaxz = (shuffle_swap(bvh_nodes[2], shufflexyz[2]) - Psplat[2]) * idirsplat[2];
-
- /* calculate { c0min, c1min, -c0max, -c1max} */
- const ssef minmax = max(max(tminmaxx, tminmaxy), max(tminmaxz, tsplat));
- const ssef tminmax = minmax ^ pn;
- const sseb lrhit = tminmax <= shuffle<2, 3, 0, 1>(tminmax);
-
- /* decide which nodes to traverse next */
- traverseChild0 = (movemask(lrhit) & 1);
- traverseChild1 = (movemask(lrhit) & 2);
+ traverse_mask = NODE_INTERSECT(kg,
+ P,
+ dir,
+# if BVH_FEATURE(BVH_HAIR)
+ tnear,
+ tfar,
+# endif
+ tsplat,
+ Psplat,
+ idirsplat,
+ shufflexyz,
+ node_addr,
+ PATH_RAY_ALL_VISIBILITY,
+ dist);
#endif // __KERNEL_SSE2__
- nodeAddr = __float_as_int(cnodes.x);
- nodeAddrChild1 = __float_as_int(cnodes.y);
-
- if(traverseChild0 && traverseChild1) {
- /* both children were intersected, push the farther one */
-#if !defined(__KERNEL_SSE2__)
- bool closestChild1 = (c1min < c0min);
-#else
- bool closestChild1 = tminmax[1] < tminmax[0];
-#endif
+ node_addr = __float_as_int(cnodes.z);
+ node_addr_child1 = __float_as_int(cnodes.w);
- if(closestChild1) {
- int tmp = nodeAddr;
- nodeAddr = nodeAddrChild1;
- nodeAddrChild1 = 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;
}
- ++stackPtr;
- kernel_assert(stackPtr < BVH_STACK_SIZE);
- traversalStack[stackPtr] = nodeAddrChild1;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_STACK_SIZE);
+ traversal_stack[stack_ptr] = node_addr_child1;
}
else {
- /* one child was intersected */
- if(traverseChild1) {
- nodeAddr = nodeAddrChild1;
+ /* One child was intersected. */
+ if(traverse_mask == 2) {
+ node_addr = node_addr_child1;
}
- else if(!traverseChild0) {
- /* neither child was intersected */
- nodeAddr = traversalStack[stackPtr];
- --stackPtr;
+ 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(nodeAddr < 0) {
- float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-nodeAddr-1)*BVH_NODE_LEAF_SIZE);
- int primAddr = __float_as_int(leaf.x);
+ 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 primAddr2 = __float_as_int(leaf.y);
+ const int prim_addr2 = __float_as_int(leaf.y);
const uint type = __float_as_int(leaf.w);
/* pop */
- nodeAddr = traversalStack[stackPtr];
- --stackPtr;
+ node_addr = traversal_stack[stack_ptr];
+ --stack_ptr;
/* primitive intersection */
switch(type & PRIMITIVE_ALL) {
case PRIMITIVE_TRIANGLE: {
/* intersect ray against primitive */
- for(; primAddr < primAddr2; primAddr++) {
- kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ for(; prim_addr < prim_addr2; prim_addr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
triangle_intersect_subsurface(kg,
&isect_precalc,
ss_isect,
P,
object,
- primAddr,
+ prim_addr,
isect_t,
lcg_state,
max_hits);
@@ -230,15 +206,15 @@ ccl_device void BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
#if BVH_FEATURE(BVH_MOTION)
case PRIMITIVE_MOTION_TRIANGLE: {
/* intersect ray against primitive */
- for(; primAddr < primAddr2; primAddr++) {
- kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ for(; prim_addr < prim_addr2; prim_addr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
motion_triangle_intersect_subsurface(kg,
ss_isect,
P,
dir,
ray->time,
object,
- primAddr,
+ prim_addr,
isect_t,
lcg_state,
max_hits);
@@ -251,8 +227,8 @@ ccl_device void BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
}
}
}
- } while(nodeAddr != ENTRYPOINT_SENTINEL);
- } while(nodeAddr != ENTRYPOINT_SENTINEL);
+ } while(node_addr != ENTRYPOINT_SENTINEL);
+ } while(node_addr != ENTRYPOINT_SENTINEL);
}
ccl_device_inline void BVH_FUNCTION_NAME(KernelGlobals *kg,
@@ -286,3 +262,4 @@ ccl_device_inline void BVH_FUNCTION_NAME(KernelGlobals *kg,
#undef BVH_FUNCTION_NAME
#undef BVH_FUNCTION_FEATURES
+#undef NODE_INTERSECT
diff --git a/intern/cycles/kernel/geom/geom_bvh_traversal.h b/intern/cycles/kernel/bvh/bvh_traversal.h
index 8560612addc..68a11b65ad7 100644
--- a/intern/cycles/kernel/geom/geom_bvh_traversal.h
+++ b/intern/cycles/kernel/bvh/bvh_traversal.h
@@ -18,7 +18,15 @@
*/
#ifdef __QBVH__
-# include "geom_qbvh_traversal.h"
+# include "qbvh_traversal.h"
+#endif
+
+#if BVH_FEATURE(BVH_HAIR)
+# define NODE_INTERSECT bvh_node_intersect
+# define NODE_INTERSECT_ROBUST bvh_node_intersect_robust
+#else
+# define NODE_INTERSECT bvh_aligned_node_intersect
+# define NODE_INTERSECT_ROBUST bvh_aligned_node_intersect_robust
#endif
/* This is a template BVH traversal function, where various features can be
@@ -49,14 +57,14 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
* - likely and unlikely for if() statements
* - test restrict attribute for pointers
*/
-
+
/* traversal stack in CUDA thread-local memory */
- int traversalStack[BVH_STACK_SIZE];
- traversalStack[0] = ENTRYPOINT_SENTINEL;
+ int traversal_stack[BVH_STACK_SIZE];
+ traversal_stack[0] = ENTRYPOINT_SENTINEL;
/* traversal variables in registers */
- int stackPtr = 0;
- int nodeAddr = kernel_data.bvh.root;
+ int stack_ptr = 0;
+ int node_addr = kernel_data.bvh.root;
/* ray parameters in registers */
float3 P = ray->P;
@@ -74,17 +82,17 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
isect->prim = PRIM_NONE;
isect->object = OBJECT_NONE;
-#if defined(__KERNEL_DEBUG__)
- isect->num_traversal_steps = 0;
- isect->num_traversed_instances = 0;
-#endif
+ 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 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);
+# endif
shuffle_swap_t shufflexyz[3];
Psplat[0] = ssef(P.x);
@@ -103,179 +111,148 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
do {
do {
/* traverse internal nodes */
- while(nodeAddr >= 0 && nodeAddr != ENTRYPOINT_SENTINEL) {
- bool traverseChild0, traverseChild1;
- int nodeAddrChild1;
+ 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__)
- /* Intersect two child bounding boxes, non-SSE version */
- float t = isect->t;
-
- /* fetch node data */
- float4 node0 = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+0);
- float4 node1 = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+1);
- float4 node2 = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+2);
- float4 cnodes = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+3);
-
- /* intersect ray against child nodes */
- NO_EXTENDED_PRECISION float c0lox = (node0.x - P.x) * idir.x;
- NO_EXTENDED_PRECISION float c0hix = (node0.z - P.x) * idir.x;
- NO_EXTENDED_PRECISION float c0loy = (node1.x - P.y) * idir.y;
- NO_EXTENDED_PRECISION float c0hiy = (node1.z - P.y) * idir.y;
- NO_EXTENDED_PRECISION float c0loz = (node2.x - P.z) * idir.z;
- NO_EXTENDED_PRECISION float c0hiz = (node2.z - P.z) * idir.z;
- NO_EXTENDED_PRECISION float c0min = max4(min(c0lox, c0hix), min(c0loy, c0hiy), min(c0loz, c0hiz), 0.0f);
- NO_EXTENDED_PRECISION float c0max = min4(max(c0lox, c0hix), max(c0loy, c0hiy), max(c0loz, c0hiz), t);
-
- NO_EXTENDED_PRECISION float c1lox = (node0.y - P.x) * idir.x;
- NO_EXTENDED_PRECISION float c1hix = (node0.w - P.x) * idir.x;
- NO_EXTENDED_PRECISION float c1loy = (node1.y - P.y) * idir.y;
- NO_EXTENDED_PRECISION float c1hiy = (node1.w - P.y) * idir.y;
- NO_EXTENDED_PRECISION float c1loz = (node2.y - P.z) * idir.z;
- NO_EXTENDED_PRECISION float c1hiz = (node2.w - P.z) * idir.z;
- NO_EXTENDED_PRECISION float c1min = max4(min(c1lox, c1hix), min(c1loy, c1hiy), min(c1loz, c1hiz), 0.0f);
- NO_EXTENDED_PRECISION float c1max = min4(max(c1lox, c1hix), max(c1loy, c1hiy), max(c1loz, c1hiz), t);
-
# if BVH_FEATURE(BVH_HAIR_MINIMUM_WIDTH)
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);
- }
+ traverse_mask = NODE_INTERSECT_ROBUST(kg,
+ P,
+# if BVH_FEATURE(BVH_HAIR)
+ dir,
+# endif
+ idir,
+ isect->t,
+ difl,
+ extmax,
+ node_addr,
+ visibility,
+ dist);
}
+ else
# endif
-
- /* decide which nodes to traverse next */
-# ifdef __VISIBILITY_FLAG__
- /* this visibility test gives a 5% performance hit, how to solve? */
- traverseChild0 = (c0max >= c0min) && (__float_as_uint(cnodes.z) & visibility);
- traverseChild1 = (c1max >= c1min) && (__float_as_uint(cnodes.w) & visibility);
-# else
- traverseChild0 = (c0max >= c0min);
- traverseChild1 = (c1max >= c1min);
-# endif
-
+ {
+ traverse_mask = NODE_INTERSECT(kg,
+ P,
+# if BVH_FEATURE(BVH_HAIR)
+ dir,
+# endif
+ idir,
+ isect->t,
+ node_addr,
+ visibility,
+ dist);
+ }
#else // __KERNEL_SSE2__
- /* Intersect two child bounding boxes, SSE3 version adapted from Embree */
-
- /* fetch node data */
- const ssef *bvh_nodes = (ssef*)kg->__bvh_nodes.data + nodeAddr*BVH_NODE_SIZE;
- const float4 cnodes = ((float4*)bvh_nodes)[3];
-
- /* intersect ray against child nodes */
- const ssef tminmaxx = (shuffle_swap(bvh_nodes[0], shufflexyz[0]) - Psplat[0]) * idirsplat[0];
- const ssef tminmaxy = (shuffle_swap(bvh_nodes[1], shufflexyz[1]) - Psplat[1]) * idirsplat[1];
- const ssef tminmaxz = (shuffle_swap(bvh_nodes[2], 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 BVH_FEATURE(BVH_HAIR_MINIMUM_WIDTH)
if(difl != 0.0f) {
- 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.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);
- }
+ traverse_mask = NODE_INTERSECT_ROBUST(kg,
+ P,
+ dir,
+# if BVH_FEATURE(BVH_HAIR)
+ tnear,
+ tfar,
+# endif
+ tsplat,
+ Psplat,
+ idirsplat,
+ shufflexyz,
+ difl,
+ extmax,
+ node_addr,
+ visibility,
+ dist);
}
+ else
# endif
-
- const sseb lrhit = tminmax <= shuffle<2, 3, 0, 1>(tminmax);
-
- /* decide which nodes to traverse next */
-# ifdef __VISIBILITY_FLAG__
- /* this visibility test gives a 5% performance hit, how to solve? */
- traverseChild0 = (movemask(lrhit) & 1) && (__float_as_uint(cnodes.z) & visibility);
- traverseChild1 = (movemask(lrhit) & 2) && (__float_as_uint(cnodes.w) & visibility);
-# else
- traverseChild0 = (movemask(lrhit) & 1);
- traverseChild1 = (movemask(lrhit) & 2);
-# endif
+ {
+ 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__
- nodeAddr = __float_as_int(cnodes.x);
- nodeAddrChild1 = __float_as_int(cnodes.y);
-
- if(traverseChild0 && traverseChild1) {
- /* both children were intersected, push the farther one */
-#if !defined(__KERNEL_SSE2__)
- bool closestChild1 = (c1min < c0min);
-#else
- bool closestChild1 = tminmax[1] < tminmax[0];
-#endif
+ node_addr = __float_as_int(cnodes.z);
+ node_addr_child1 = __float_as_int(cnodes.w);
- if(closestChild1) {
- int tmp = nodeAddr;
- nodeAddr = nodeAddrChild1;
- nodeAddrChild1 = 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;
}
- ++stackPtr;
- kernel_assert(stackPtr < BVH_STACK_SIZE);
- traversalStack[stackPtr] = nodeAddrChild1;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_STACK_SIZE);
+ traversal_stack[stack_ptr] = node_addr_child1;
}
else {
- /* one child was intersected */
- if(traverseChild1) {
- nodeAddr = nodeAddrChild1;
+ /* One child was intersected. */
+ if(traverse_mask == 2) {
+ node_addr = node_addr_child1;
}
- else if(!traverseChild0) {
- /* neither child was intersected */
- nodeAddr = traversalStack[stackPtr];
- --stackPtr;
+ else if(traverse_mask == 0) {
+ /* Neither child was intersected. */
+ node_addr = traversal_stack[stack_ptr];
+ --stack_ptr;
}
}
-
-#if defined(__KERNEL_DEBUG__)
- isect->num_traversal_steps++;
-#endif
+ BVH_DEBUG_NEXT_STEP();
}
/* if node is leaf, fetch triangle list */
- if(nodeAddr < 0) {
- float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-nodeAddr-1)*BVH_NODE_LEAF_SIZE);
- int primAddr = __float_as_int(leaf.x);
+ 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(primAddr >= 0) {
+ if(prim_addr >= 0) {
#endif
- const int primAddr2 = __float_as_int(leaf.y);
+ const int prim_addr2 = __float_as_int(leaf.y);
const uint type = __float_as_int(leaf.w);
/* pop */
- nodeAddr = traversalStack[stackPtr];
- --stackPtr;
+ node_addr = traversal_stack[stack_ptr];
+ --stack_ptr;
/* primitive intersection */
switch(type & PRIMITIVE_ALL) {
case PRIMITIVE_TRIANGLE: {
- for(; primAddr < primAddr2; primAddr++) {
-#if defined(__KERNEL_DEBUG__)
- isect->num_traversal_steps++;
-#endif
- kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
- if(triangle_intersect(kg, &isect_precalc, isect, P, visibility, object, primAddr)) {
+ for(; prim_addr < prim_addr2; prim_addr++) {
+ BVH_DEBUG_NEXT_STEP();
+ kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
+ if(triangle_intersect(kg,
+ &isect_precalc,
+ isect,
+ P,
+ 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 BVH_FEATURE(BVH_HAIR)
+ tfar = ssef(isect->t);
+# endif
#else
if(visibility == PATH_RAY_SHADOW_OPAQUE)
return true;
@@ -286,17 +263,26 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
}
#if BVH_FEATURE(BVH_MOTION)
case PRIMITIVE_MOTION_TRIANGLE: {
- for(; primAddr < primAddr2; primAddr++) {
-# if defined(__KERNEL_DEBUG__)
- isect->num_traversal_steps++;
-# endif
- kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
- if(motion_triangle_intersect(kg, isect, P, dir, ray->time, visibility, object, primAddr)) {
+ for(; prim_addr < prim_addr2; prim_addr++) {
+ BVH_DEBUG_NEXT_STEP();
+ 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 BVH_FEATURE(BVH_HAIR)
+ tfar = ssef(isect->t);
+# endif
# else
if(visibility == PATH_RAY_SHADOW_OPAQUE)
return true;
@@ -309,22 +295,47 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
#if BVH_FEATURE(BVH_HAIR)
case PRIMITIVE_CURVE:
case PRIMITIVE_MOTION_CURVE: {
- for(; primAddr < primAddr2; primAddr++) {
-# if defined(__KERNEL_DEBUG__)
- isect->num_traversal_steps++;
-# endif
- kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ for(; prim_addr < prim_addr2; prim_addr++) {
+ BVH_DEBUG_NEXT_STEP();
+ kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
bool hit;
- if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
- hit = bvh_cardinal_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, lcg_state, difl, extmax);
- else
- hit = bvh_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, lcg_state, difl, extmax);
+ if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE) {
+ hit = bvh_cardinal_curve_intersect(kg,
+ isect,
+ P,
+ dir,
+ visibility,
+ object,
+ prim_addr,
+ ray->time,
+ type,
+ lcg_state,
+ difl,
+ extmax);
+ }
+ else {
+ hit = bvh_curve_intersect(kg,
+ isect,
+ P,
+ dir,
+ visibility,
+ object,
+ prim_addr,
+ ray->time,
+ 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 BVH_FEATURE(BVH_HAIR)
+ tfar = ssef(isect->t);
+# endif
# else
if(visibility == PATH_RAY_SHADOW_OPAQUE)
return true;
@@ -339,7 +350,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
#if BVH_FEATURE(BVH_INSTANCING)
else {
/* instance push */
- object = kernel_tex_fetch(__prim_object, -primAddr-1);
+ object = kernel_tex_fetch(__prim_object, -prim_addr-1);
# if BVH_FEATURE(BVH_MOTION)
bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &isect->t, &ob_itfm);
@@ -354,26 +365,27 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
Psplat[2] = ssef(P.z);
tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t);
+# if BVH_FEATURE(BVH_HAIR)
+ tfar = ssef(isect->t);
+# endif
gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
# endif
- ++stackPtr;
- kernel_assert(stackPtr < BVH_STACK_SIZE);
- traversalStack[stackPtr] = ENTRYPOINT_SENTINEL;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_STACK_SIZE);
+ traversal_stack[stack_ptr] = ENTRYPOINT_SENTINEL;
- nodeAddr = kernel_tex_fetch(__object_node, object);
+ node_addr = kernel_tex_fetch(__object_node, object);
-# if defined(__KERNEL_DEBUG__)
- isect->num_traversed_instances++;
-# endif
+ BVH_DEBUG_NEXT_INSTANCE();
}
}
#endif /* FEATURE(BVH_INSTANCING) */
- } while(nodeAddr != ENTRYPOINT_SENTINEL);
+ } while(node_addr != ENTRYPOINT_SENTINEL);
#if BVH_FEATURE(BVH_INSTANCING)
- if(stackPtr >= 0) {
+ if(stack_ptr >= 0) {
kernel_assert(object != OBJECT_NONE);
/* instance pop */
@@ -390,16 +402,19 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
Psplat[2] = ssef(P.z);
tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t);
+# if BVH_FEATURE(BVH_HAIR)
+ tfar = ssef(isect->t);
+# endif
gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
# endif
object = OBJECT_NONE;
- nodeAddr = traversalStack[stackPtr];
- --stackPtr;
+ node_addr = traversal_stack[stack_ptr];
+ --stack_ptr;
}
#endif /* FEATURE(BVH_INSTANCING) */
- } while(nodeAddr != ENTRYPOINT_SENTINEL);
+ } while(node_addr != ENTRYPOINT_SENTINEL);
return (isect->prim != PRIM_NONE);
}
@@ -447,3 +462,5 @@ ccl_device_inline bool BVH_FUNCTION_NAME(KernelGlobals *kg,
#undef BVH_FUNCTION_NAME
#undef BVH_FUNCTION_FEATURES
+#undef NODE_INTERSECT
+#undef NODE_INTERSECT_ROBUST
diff --git a/intern/cycles/kernel/geom/geom_bvh_volume.h b/intern/cycles/kernel/bvh/bvh_volume.h
index f3edf85d723..03499e94347 100644
--- a/intern/cycles/kernel/geom/geom_bvh_volume.h
+++ b/intern/cycles/kernel/bvh/bvh_volume.h
@@ -18,7 +18,13 @@
*/
#ifdef __QBVH__
-#include "geom_qbvh_volume.h"
+# include "qbvh_volume.h"
+#endif
+
+#if BVH_FEATURE(BVH_HAIR)
+# define NODE_INTERSECT bvh_node_intersect
+#else
+# define NODE_INTERSECT bvh_aligned_node_intersect
#endif
/* This is a template BVH traversal function for volumes, where
@@ -43,12 +49,12 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
*/
/* traversal stack in CUDA thread-local memory */
- int traversalStack[BVH_STACK_SIZE];
- traversalStack[0] = ENTRYPOINT_SENTINEL;
+ int traversal_stack[BVH_STACK_SIZE];
+ traversal_stack[0] = ENTRYPOINT_SENTINEL;
/* traversal variables in registers */
- int stackPtr = 0;
- int nodeAddr = kernel_data.bvh.root;
+ int stack_ptr = 0;
+ int node_addr = kernel_data.bvh.root;
/* ray parameters in registers */
float3 P = ray->P;
@@ -69,9 +75,12 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
#if defined(__KERNEL_SSE2__)
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];
+# if BVH_FEATURE(BVH_HAIR)
+ ssef tnear(0.0f), tfar(isect->t);
+# endif
shuffle_swap_t shufflexyz[3];
Psplat[0] = ssef(P.x);
@@ -90,143 +99,124 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
do {
do {
/* traverse internal nodes */
- while(nodeAddr >= 0 && nodeAddr != ENTRYPOINT_SENTINEL) {
- bool traverseChild0, traverseChild1;
- int nodeAddrChild1;
+ 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__)
- /* Intersect two child bounding boxes, non-SSE version */
- float t = isect->t;
-
- /* fetch node data */
- float4 node0 = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+0);
- float4 node1 = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+1);
- float4 node2 = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+2);
- float4 cnodes = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+3);
-
- /* intersect ray against child nodes */
- NO_EXTENDED_PRECISION float c0lox = (node0.x - P.x) * idir.x;
- NO_EXTENDED_PRECISION float c0hix = (node0.z - P.x) * idir.x;
- NO_EXTENDED_PRECISION float c0loy = (node1.x - P.y) * idir.y;
- NO_EXTENDED_PRECISION float c0hiy = (node1.z - P.y) * idir.y;
- NO_EXTENDED_PRECISION float c0loz = (node2.x - P.z) * idir.z;
- NO_EXTENDED_PRECISION float c0hiz = (node2.z - P.z) * idir.z;
- NO_EXTENDED_PRECISION float c0min = max4(min(c0lox, c0hix), min(c0loy, c0hiy), min(c0loz, c0hiz), 0.0f);
- NO_EXTENDED_PRECISION float c0max = min4(max(c0lox, c0hix), max(c0loy, c0hiy), max(c0loz, c0hiz), t);
-
- NO_EXTENDED_PRECISION float c1lox = (node0.y - P.x) * idir.x;
- NO_EXTENDED_PRECISION float c1hix = (node0.w - P.x) * idir.x;
- NO_EXTENDED_PRECISION float c1loy = (node1.y - P.y) * idir.y;
- NO_EXTENDED_PRECISION float c1hiy = (node1.w - P.y) * idir.y;
- NO_EXTENDED_PRECISION float c1loz = (node2.y - P.z) * idir.z;
- NO_EXTENDED_PRECISION float c1hiz = (node2.w - P.z) * idir.z;
- NO_EXTENDED_PRECISION float c1min = max4(min(c1lox, c1hix), min(c1loy, c1hiy), min(c1loz, c1hiz), 0.0f);
- NO_EXTENDED_PRECISION float c1max = min4(max(c1lox, c1hix), max(c1loy, c1hiy), max(c1loz, c1hiz), t);
-
- /* decide which nodes to traverse next */
- traverseChild0 = (c0max >= c0min);
- traverseChild1 = (c1max >= c1min);
-
+ traverse_mask = NODE_INTERSECT(kg,
+ P,
+# if BVH_FEATURE(BVH_HAIR)
+ dir,
+# endif
+ idir,
+ isect->t,
+ node_addr,
+ visibility,
+ dist);
#else // __KERNEL_SSE2__
- /* Intersect two child bounding boxes, SSE3 version adapted from Embree */
-
- /* fetch node data */
- const ssef *bvh_nodes = (ssef*)kg->__bvh_nodes.data + nodeAddr*BVH_NODE_SIZE;
- const float4 cnodes = ((float4*)bvh_nodes)[3];
-
- /* intersect ray against child nodes */
- const ssef tminmaxx = (shuffle_swap(bvh_nodes[0], shufflexyz[0]) - Psplat[0]) * idirsplat[0];
- const ssef tminmaxy = (shuffle_swap(bvh_nodes[1], shufflexyz[1]) - Psplat[1]) * idirsplat[1];
- const ssef tminmaxz = (shuffle_swap(bvh_nodes[2], 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);
-
- /* decide which nodes to traverse next */
- traverseChild0 = (movemask(lrhit) & 1);
- traverseChild1 = (movemask(lrhit) & 2);
+ 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__
- nodeAddr = __float_as_int(cnodes.x);
- nodeAddrChild1 = __float_as_int(cnodes.y);
-
- if(traverseChild0 && traverseChild1) {
- /* both children were intersected, push the farther one */
-#if !defined(__KERNEL_SSE2__)
- bool closestChild1 = (c1min < c0min);
-#else
- bool closestChild1 = tminmax[1] < tminmax[0];
-#endif
+ node_addr = __float_as_int(cnodes.z);
+ node_addr_child1 = __float_as_int(cnodes.w);
- if(closestChild1) {
- int tmp = nodeAddr;
- nodeAddr = nodeAddrChild1;
- nodeAddrChild1 = 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;
}
- ++stackPtr;
- kernel_assert(stackPtr < BVH_STACK_SIZE);
- traversalStack[stackPtr] = nodeAddrChild1;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_STACK_SIZE);
+ traversal_stack[stack_ptr] = node_addr_child1;
}
else {
- /* one child was intersected */
- if(traverseChild1) {
- nodeAddr = nodeAddrChild1;
+ /* One child was intersected. */
+ if(traverse_mask == 2) {
+ node_addr = node_addr_child1;
}
- else if(!traverseChild0) {
- /* neither child was intersected */
- nodeAddr = traversalStack[stackPtr];
- --stackPtr;
+ 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(nodeAddr < 0) {
- float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-nodeAddr-1)*BVH_NODE_LEAF_SIZE);
- int primAddr = __float_as_int(leaf.x);
+ 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(primAddr >= 0) {
+ if(prim_addr >= 0) {
#endif
- const int primAddr2 = __float_as_int(leaf.y);
+ const int prim_addr2 = __float_as_int(leaf.y);
const uint type = __float_as_int(leaf.w);
/* pop */
- nodeAddr = traversalStack[stackPtr];
- --stackPtr;
+ node_addr = traversal_stack[stack_ptr];
+ --stack_ptr;
/* primitive intersection */
switch(type & PRIMITIVE_ALL) {
case PRIMITIVE_TRIANGLE: {
/* intersect ray against primitive */
- for(; primAddr < primAddr2; primAddr++) {
- kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ 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, primAddr): 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_precalc, isect, P, visibility, object, primAddr);
+ triangle_intersect(kg,
+ &isect_precalc,
+ isect,
+ P,
+ visibility,
+ object,
+ prim_addr);
}
break;
}
#if BVH_FEATURE(BVH_MOTION)
case PRIMITIVE_MOTION_TRIANGLE: {
/* intersect ray against primitive */
- for(; primAddr < primAddr2; primAddr++) {
- kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ 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, primAddr): 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, primAddr);
+ motion_triangle_intersect(kg,
+ isect,
+ P,
+ dir,
+ ray->time,
+ visibility,
+ object,
+ prim_addr);
}
break;
}
@@ -239,7 +229,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
#if BVH_FEATURE(BVH_INSTANCING)
else {
/* instance push */
- object = kernel_tex_fetch(__prim_object, -primAddr-1);
+ 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) {
@@ -258,29 +248,32 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
Psplat[2] = ssef(P.z);
tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t);
+# if BVH_FEATURE(BVH_HAIR)
+ tfar = ssef(isect->t);
+# endif
gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
# endif
- ++stackPtr;
- kernel_assert(stackPtr < BVH_STACK_SIZE);
- traversalStack[stackPtr] = ENTRYPOINT_SENTINEL;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_STACK_SIZE);
+ traversal_stack[stack_ptr] = ENTRYPOINT_SENTINEL;
- nodeAddr = kernel_tex_fetch(__object_node, object);
+ node_addr = kernel_tex_fetch(__object_node, object);
}
else {
/* pop */
object = OBJECT_NONE;
- nodeAddr = traversalStack[stackPtr];
- --stackPtr;
+ node_addr = traversal_stack[stack_ptr];
+ --stack_ptr;
}
}
}
#endif /* FEATURE(BVH_INSTANCING) */
- } while(nodeAddr != ENTRYPOINT_SENTINEL);
+ } while(node_addr != ENTRYPOINT_SENTINEL);
#if BVH_FEATURE(BVH_INSTANCING)
- if(stackPtr >= 0) {
+ if(stack_ptr >= 0) {
kernel_assert(object != OBJECT_NONE);
/* instance pop */
@@ -298,16 +291,19 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
Psplat[2] = ssef(P.z);
tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t);
+# if BVH_FEATURE(BVH_HAIR)
+ tfar = ssef(isect->t);
+# endif
gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
# endif
object = OBJECT_NONE;
- nodeAddr = traversalStack[stackPtr];
- --stackPtr;
+ node_addr = traversal_stack[stack_ptr];
+ --stack_ptr;
}
#endif /* FEATURE(BVH_MOTION) */
- } while(nodeAddr != ENTRYPOINT_SENTINEL);
+ } while(node_addr != ENTRYPOINT_SENTINEL);
return (isect->prim != PRIM_NONE);
}
@@ -337,3 +333,4 @@ ccl_device_inline bool BVH_FUNCTION_NAME(KernelGlobals *kg,
#undef BVH_FUNCTION_NAME
#undef BVH_FUNCTION_FEATURES
+#undef NODE_INTERSECT
diff --git a/intern/cycles/kernel/geom/geom_bvh_volume_all.h b/intern/cycles/kernel/bvh/bvh_volume_all.h
index ec837212471..7eddc2891d0 100644
--- a/intern/cycles/kernel/geom/geom_bvh_volume_all.h
+++ b/intern/cycles/kernel/bvh/bvh_volume_all.h
@@ -18,7 +18,13 @@
*/
#ifdef __QBVH__
-#include "geom_qbvh_volume_all.h"
+# include "qbvh_volume_all.h"
+#endif
+
+#if BVH_FEATURE(BVH_HAIR)
+# define NODE_INTERSECT bvh_node_intersect
+#else
+# define NODE_INTERSECT bvh_aligned_node_intersect
#endif
/* This is a template BVH traversal function for volumes, where
@@ -44,12 +50,12 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
*/
/* traversal stack in CUDA thread-local memory */
- int traversalStack[BVH_STACK_SIZE];
- traversalStack[0] = ENTRYPOINT_SENTINEL;
+ int traversal_stack[BVH_STACK_SIZE];
+ traversal_stack[0] = ENTRYPOINT_SENTINEL;
/* traversal variables in registers */
- int stackPtr = 0;
- int nodeAddr = kernel_data.bvh.root;
+ int stack_ptr = 0;
+ int node_addr = kernel_data.bvh.root;
/* ray parameters in registers */
const float tmax = ray->t;
@@ -73,9 +79,12 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
#if defined(__KERNEL_SSE2__)
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];
+# if BVH_FEATURE(BVH_HAIR)
+ ssef tnear(0.0f), tfar(isect_t);
+# endif
shuffle_swap_t shufflexyz[3];
Psplat[0] = ssef(P.x);
@@ -94,129 +103,103 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
do {
do {
/* traverse internal nodes */
- while(nodeAddr >= 0 && nodeAddr != ENTRYPOINT_SENTINEL) {
- bool traverseChild0, traverseChild1;
- int nodeAddrChild1;
+ 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__)
- /* Intersect two child bounding boxes, non-SSE version */
- float t = isect_array->t;
-
- /* fetch node data */
- float4 node0 = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+0);
- float4 node1 = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+1);
- float4 node2 = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+2);
- float4 cnodes = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+3);
-
- /* intersect ray against child nodes */
- NO_EXTENDED_PRECISION float c0lox = (node0.x - P.x) * idir.x;
- NO_EXTENDED_PRECISION float c0hix = (node0.z - P.x) * idir.x;
- NO_EXTENDED_PRECISION float c0loy = (node1.x - P.y) * idir.y;
- NO_EXTENDED_PRECISION float c0hiy = (node1.z - P.y) * idir.y;
- NO_EXTENDED_PRECISION float c0loz = (node2.x - P.z) * idir.z;
- NO_EXTENDED_PRECISION float c0hiz = (node2.z - P.z) * idir.z;
- NO_EXTENDED_PRECISION float c0min = max4(min(c0lox, c0hix), min(c0loy, c0hiy), min(c0loz, c0hiz), 0.0f);
- NO_EXTENDED_PRECISION float c0max = min4(max(c0lox, c0hix), max(c0loy, c0hiy), max(c0loz, c0hiz), t);
-
- NO_EXTENDED_PRECISION float c1lox = (node0.y - P.x) * idir.x;
- NO_EXTENDED_PRECISION float c1hix = (node0.w - P.x) * idir.x;
- NO_EXTENDED_PRECISION float c1loy = (node1.y - P.y) * idir.y;
- NO_EXTENDED_PRECISION float c1hiy = (node1.w - P.y) * idir.y;
- NO_EXTENDED_PRECISION float c1loz = (node2.y - P.z) * idir.z;
- NO_EXTENDED_PRECISION float c1hiz = (node2.w - P.z) * idir.z;
- NO_EXTENDED_PRECISION float c1min = max4(min(c1lox, c1hix), min(c1loy, c1hiy), min(c1loz, c1hiz), 0.0f);
- NO_EXTENDED_PRECISION float c1max = min4(max(c1lox, c1hix), max(c1loy, c1hiy), max(c1loz, c1hiz), t);
-
- /* decide which nodes to traverse next */
- traverseChild0 = (c0max >= c0min);
- traverseChild1 = (c1max >= c1min);
-
+ traverse_mask = NODE_INTERSECT(kg,
+ P,
+# if BVH_FEATURE(BVH_HAIR)
+ dir,
+# endif
+ idir,
+ isect_t,
+ node_addr,
+ visibility,
+ dist);
#else // __KERNEL_SSE2__
- /* Intersect two child bounding boxes, SSE3 version adapted from Embree */
-
- /* fetch node data */
- const ssef *bvh_nodes = (ssef*)kg->__bvh_nodes.data + nodeAddr*BVH_NODE_SIZE;
- const float4 cnodes = ((float4*)bvh_nodes)[3];
-
- /* intersect ray against child nodes */
- const ssef tminmaxx = (shuffle_swap(bvh_nodes[0], shufflexyz[0]) - Psplat[0]) * idirsplat[0];
- const ssef tminmaxy = (shuffle_swap(bvh_nodes[1], shufflexyz[1]) - Psplat[1]) * idirsplat[1];
- const ssef tminmaxz = (shuffle_swap(bvh_nodes[2], 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);
-
- /* decide which nodes to traverse next */
- traverseChild0 = (movemask(lrhit) & 1);
- traverseChild1 = (movemask(lrhit) & 2);
+ 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__
- nodeAddr = __float_as_int(cnodes.x);
- nodeAddrChild1 = __float_as_int(cnodes.y);
+ node_addr = __float_as_int(cnodes.z);
+ node_addr_child1 = __float_as_int(cnodes.w);
- if(traverseChild0 && traverseChild1) {
- /* both children were intersected, push the farther one */
-#if !defined(__KERNEL_SSE2__)
- bool closestChild1 = (c1min < c0min);
-#else
- bool closestChild1 = tminmax[1] < tminmax[0];
-#endif
-
- if(closestChild1) {
- int tmp = nodeAddr;
- nodeAddr = nodeAddrChild1;
- nodeAddrChild1 = 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;
}
- ++stackPtr;
- kernel_assert(stackPtr < BVH_STACK_SIZE);
- traversalStack[stackPtr] = nodeAddrChild1;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_STACK_SIZE);
+ traversal_stack[stack_ptr] = node_addr_child1;
}
else {
- /* one child was intersected */
- if(traverseChild1) {
- nodeAddr = nodeAddrChild1;
+ /* One child was intersected. */
+ if(traverse_mask == 2) {
+ node_addr = node_addr_child1;
}
- else if(!traverseChild0) {
- /* neither child was intersected */
- nodeAddr = traversalStack[stackPtr];
- --stackPtr;
+ 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(nodeAddr < 0) {
- float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-nodeAddr-1)*BVH_NODE_LEAF_SIZE);
- int primAddr = __float_as_int(leaf.x);
+ 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(primAddr >= 0) {
+ if(prim_addr >= 0) {
#endif
- const int primAddr2 = __float_as_int(leaf.y);
+ const int prim_addr2 = __float_as_int(leaf.y);
const uint type = __float_as_int(leaf.w);
bool hit;
/* pop */
- nodeAddr = traversalStack[stackPtr];
- --stackPtr;
+ node_addr = traversal_stack[stack_ptr];
+ --stack_ptr;
/* primitive intersection */
switch(type & PRIMITIVE_ALL) {
case PRIMITIVE_TRIANGLE: {
/* intersect ray against primitive */
- for(; primAddr < primAddr2; primAddr++) {
- kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ 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, primAddr): 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_precalc, isect_array, P, visibility, object, primAddr);
+ hit = triangle_intersect(kg,
+ &isect_precalc,
+ isect_array,
+ P,
+ visibility,
+ object,
+ prim_addr);
if(hit) {
/* Move on to next entry in intersections array. */
isect_array++;
@@ -246,15 +229,22 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
#if BVH_FEATURE(BVH_MOTION)
case PRIMITIVE_MOTION_TRIANGLE: {
/* intersect ray against primitive */
- for(; primAddr < primAddr2; primAddr++) {
- kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ 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, primAddr): 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, primAddr);
+ 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++;
@@ -290,7 +280,7 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
#if BVH_FEATURE(BVH_INSTANCING)
else {
/* instance push */
- object = kernel_tex_fetch(__prim_object, -primAddr-1);
+ 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) {
@@ -311,29 +301,32 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
Psplat[2] = ssef(P.z);
tsplat = ssef(0.0f, 0.0f, -isect_t, -isect_t);
+# if BVH_FEATURE(BVH_HAIR)
+ tfar = ssef(isect_t);
+# endif
gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
# endif
- ++stackPtr;
- kernel_assert(stackPtr < BVH_STACK_SIZE);
- traversalStack[stackPtr] = ENTRYPOINT_SENTINEL;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_STACK_SIZE);
+ traversal_stack[stack_ptr] = ENTRYPOINT_SENTINEL;
- nodeAddr = kernel_tex_fetch(__object_node, object);
+ node_addr = kernel_tex_fetch(__object_node, object);
}
else {
/* pop */
object = OBJECT_NONE;
- nodeAddr = traversalStack[stackPtr];
- --stackPtr;
+ node_addr = traversal_stack[stack_ptr];
+ --stack_ptr;
}
}
}
#endif /* FEATURE(BVH_INSTANCING) */
- } while(nodeAddr != ENTRYPOINT_SENTINEL);
+ } while(node_addr != ENTRYPOINT_SENTINEL);
#if BVH_FEATURE(BVH_INSTANCING)
- if(stackPtr >= 0) {
+ if(stack_ptr >= 0) {
kernel_assert(object != OBJECT_NONE);
if(num_hits_in_instance) {
@@ -368,16 +361,19 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
Psplat[2] = ssef(P.z);
tsplat = ssef(0.0f, 0.0f, -isect_t, -isect_t);
+# if BVH_FEATURE(BVH_HAIR)
+ tfar = ssef(isect_t);
+# endif
gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
# endif
object = OBJECT_NONE;
- nodeAddr = traversalStack[stackPtr];
- --stackPtr;
+ node_addr = traversal_stack[stack_ptr];
+ --stack_ptr;
}
#endif /* FEATURE(BVH_MOTION) */
- } while(nodeAddr != ENTRYPOINT_SENTINEL);
+ } while(node_addr != ENTRYPOINT_SENTINEL);
return num_hits;
}
@@ -410,3 +406,4 @@ ccl_device_inline uint BVH_FUNCTION_NAME(KernelGlobals *kg,
#undef BVH_FUNCTION_NAME
#undef BVH_FUNCTION_FEATURES
+#undef NODE_INTERSECT
diff --git a/intern/cycles/kernel/bvh/qbvh_nodes.h b/intern/cycles/kernel/bvh/qbvh_nodes.h
new file mode 100644
index 00000000000..4d8695bedec
--- /dev/null
+++ b/intern/cycles/kernel/bvh/qbvh_nodes.h
@@ -0,0 +1,433 @@
+/*
+ * Copyright 2011-2014, Blender Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+struct QBVHStackItem {
+ int addr;
+ float dist;
+};
+
+/* 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)
+{
+ 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); }
+}
+
+ccl_device_inline void qbvh_stack_sort(QBVHStackItem *ccl_restrict s1,
+ QBVHStackItem *ccl_restrict s2,
+ 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); }
+}
+
+/* Axis-aligned nodes intersection */
+
+ccl_device_inline int qbvh_aligned_node_intersect(KernelGlobals *ccl_restrict kg,
+ const ssef& isect_near,
+ const ssef& isect_far,
+#ifdef __KERNEL_AVX2__
+ const sse3f& org_idir,
+#else
+ 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 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);
+#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;
+#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;
+#else
+ const ssef tnear = max4(tnear_x, tnear_y, tnear_z, isect_near);
+ const ssef tfar = min4(tfar_x, tfar_y, tfar_z, isect_far);
+ const sseb vmask = tnear <= tfar;
+ int mask = (int)movemask(vmask);
+#endif
+ *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,
+#ifdef __KERNEL_AVX2__
+ const sse3f& P_idir,
+#else
+ 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 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);
+#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;
+#endif
+
+ const float round_down = 1.0f - difl;
+ const float round_up = 1.0f + difl;
+ const ssef tnear = max4(tnear_x, tnear_y, tnear_z, isect_near);
+ const ssef tfar = min4(tfar_x, tfar_y, tfar_z, isect_far);
+ 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,
+#ifdef __KERNEL_AVX2__
+ 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 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_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 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 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 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);
+#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);
+#endif
+}
+
+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,
+#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 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_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 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 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 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;
+
+#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);
+#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);
+#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);
+}
+
+/* Intersectors wrappers.
+ *
+ * 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,
+#ifdef __KERNEL_AVX2__
+ 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 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,
+#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,
+#ifdef __KERNEL_AVX2__
+ org_idir,
+#else
+ org,
+#endif
+ 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,
+#ifdef __KERNEL_AVX2__
+ 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 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,
+#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,
+#ifdef __KERNEL_AVX2__
+ P_idir,
+#else
+ P,
+#endif
+ idir,
+ near_x, near_y, near_z,
+ far_x, far_y, far_z,
+ node_addr,
+ difl,
+ dist);
+ }
+}
diff --git a/intern/cycles/kernel/geom/geom_qbvh_shadow.h b/intern/cycles/kernel/bvh/qbvh_shadow_all.h
index edb5b5c78c3..3a728b388eb 100644
--- a/intern/cycles/kernel/geom/geom_qbvh_shadow.h
+++ b/intern/cycles/kernel/bvh/qbvh_shadow_all.h
@@ -27,6 +27,12 @@
*
*/
+#if BVH_FEATURE(BVH_HAIR)
+# define NODE_INTERSECT qbvh_node_intersect
+#else
+# define NODE_INTERSECT qbvh_aligned_node_intersect
+#endif
+
ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
const Ray *ray,
Intersection *isect_array,
@@ -39,12 +45,12 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
*/
/* Traversal stack in CUDA thread-local memory. */
- QBVHStackItem traversalStack[BVH_QSTACK_SIZE];
- traversalStack[0].addr = ENTRYPOINT_SENTINEL;
+ QBVHStackItem traversal_stack[BVH_QSTACK_SIZE];
+ traversal_stack[0].addr = ENTRYPOINT_SENTINEL;
/* Traversal variables in registers. */
- int stackPtr = 0;
- int nodeAddr = kernel_data.bvh.root;
+ int stack_ptr = 0;
+ int node_addr = kernel_data.bvh.root;
/* Ray parameters in registers. */
const float tmax = ray->t;
@@ -72,13 +78,17 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
#endif
ssef tnear(0.0f), tfar(tmax);
+#if BVH_FEATURE(BVH_HAIR)
+ sse3f dir4(ssef(dir.x), ssef(dir.y), ssef(dir.z));
+#endif
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);
-#else
- sse3f org = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
+ 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));
#endif
/* Offsets to select the side that becomes the lower or upper bound. */
@@ -96,29 +106,53 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
do {
do {
/* Traverse internal nodes. */
- while(nodeAddr >= 0 && nodeAddr != ENTRYPOINT_SENTINEL) {
+ 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) & PATH_RAY_SHADOW) == 0) {
+ /* Pop. */
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ continue;
+ }
+#endif
+
ssef dist;
- int traverseChild = qbvh_node_intersect(kg,
- tnear,
- tfar,
+ int child_mask = NODE_INTERSECT(kg,
+ tnear,
+ tfar,
#ifdef __KERNEL_AVX2__
- P_idir4,
-#else
- org,
+ P_idir4,
#endif
- idir4,
- near_x, near_y, near_z,
- far_x, far_y, far_z,
- nodeAddr,
- &dist);
-
- if(traverseChild != 0) {
- float4 cnodes = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_QNODE_SIZE+6);
+# if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
+ org4,
+# endif
+# if BVH_FEATURE(BVH_HAIR)
+ dir4,
+# endif
+ 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
+#endif
+ {
+ cnodes = kernel_tex_fetch(__bvh_nodes, node_addr+7);
+ }
/* One child is hit, continue with that child. */
- int r = __bscf(traverseChild);
- if(traverseChild == 0) {
- nodeAddr = __float_as_int(cnodes[r]);
+ int r = __bscf(child_mask);
+ if(child_mask == 0) {
+ node_addr = __float_as_int(cnodes[r]);
continue;
}
@@ -127,24 +161,24 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
*/
int c0 = __float_as_int(cnodes[r]);
float d0 = ((float*)&dist)[r];
- r = __bscf(traverseChild);
+ r = __bscf(child_mask);
int c1 = __float_as_int(cnodes[r]);
float d1 = ((float*)&dist)[r];
- if(traverseChild == 0) {
+ if(child_mask == 0) {
if(d1 < d0) {
- nodeAddr = c1;
- ++stackPtr;
- kernel_assert(stackPtr < BVH_QSTACK_SIZE);
- traversalStack[stackPtr].addr = c0;
- traversalStack[stackPtr].dist = 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 {
- nodeAddr = c0;
- ++stackPtr;
- kernel_assert(stackPtr < BVH_QSTACK_SIZE);
- traversalStack[stackPtr].addr = c1;
- traversalStack[stackPtr].dist = d1;
+ 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;
}
}
@@ -152,86 +186,86 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
/* Here starts the slow path for 3 or 4 hit children. We push
* all nodes onto the stack to sort them there.
*/
- ++stackPtr;
- kernel_assert(stackPtr < BVH_QSTACK_SIZE);
- traversalStack[stackPtr].addr = c1;
- traversalStack[stackPtr].dist = d1;
- ++stackPtr;
- kernel_assert(stackPtr < BVH_QSTACK_SIZE);
- traversalStack[stackPtr].addr = c0;
- traversalStack[stackPtr].dist = d0;
+ ++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(traverseChild);
+ r = __bscf(child_mask);
int c2 = __float_as_int(cnodes[r]);
float d2 = ((float*)&dist)[r];
- if(traverseChild == 0) {
- ++stackPtr;
- kernel_assert(stackPtr < BVH_QSTACK_SIZE);
- traversalStack[stackPtr].addr = c2;
- traversalStack[stackPtr].dist = d2;
- qbvh_stack_sort(&traversalStack[stackPtr],
- &traversalStack[stackPtr - 1],
- &traversalStack[stackPtr - 2]);
- nodeAddr = traversalStack[stackPtr].addr;
- --stackPtr;
+ 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(traverseChild);
+ r = __bscf(child_mask);
int c3 = __float_as_int(cnodes[r]);
float d3 = ((float*)&dist)[r];
- ++stackPtr;
- kernel_assert(stackPtr < BVH_QSTACK_SIZE);
- traversalStack[stackPtr].addr = c3;
- traversalStack[stackPtr].dist = d3;
- ++stackPtr;
- kernel_assert(stackPtr < BVH_QSTACK_SIZE);
- traversalStack[stackPtr].addr = c2;
- traversalStack[stackPtr].dist = d2;
- qbvh_stack_sort(&traversalStack[stackPtr],
- &traversalStack[stackPtr - 1],
- &traversalStack[stackPtr - 2],
- &traversalStack[stackPtr - 3]);
+ ++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]);
}
- nodeAddr = traversalStack[stackPtr].addr;
- --stackPtr;
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
}
/* If node is leaf, fetch triangle list. */
- if(nodeAddr < 0) {
- float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-nodeAddr-1)*BVH_QNODE_LEAF_SIZE);
+ 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. */
- nodeAddr = traversalStack[stackPtr].addr;
- --stackPtr;
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
continue;
}
#endif
- int primAddr = __float_as_int(leaf.x);
+ int prim_addr = __float_as_int(leaf.x);
#if BVH_FEATURE(BVH_INSTANCING)
- if(primAddr >= 0) {
+ if(prim_addr >= 0) {
#endif
- int primAddr2 = __float_as_int(leaf.y);
+ int prim_addr2 = __float_as_int(leaf.y);
const uint type = __float_as_int(leaf.w);
const uint p_type = type & PRIMITIVE_ALL;
/* Pop. */
- nodeAddr = traversalStack[stackPtr].addr;
- --stackPtr;
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
/* Primitive intersection. */
- while(primAddr < primAddr2) {
- kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ while(prim_addr < prim_addr2) {
+ kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
bool hit;
@@ -241,22 +275,57 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
switch(p_type) {
case PRIMITIVE_TRIANGLE: {
- hit = triangle_intersect(kg, &isect_precalc, isect_array, P, PATH_RAY_SHADOW, object, primAddr);
+ hit = triangle_intersect(kg,
+ &isect_precalc,
+ isect_array,
+ P,
+ PATH_RAY_SHADOW,
+ object,
+ prim_addr);
break;
}
#if BVH_FEATURE(BVH_MOTION)
case PRIMITIVE_MOTION_TRIANGLE: {
- hit = motion_triangle_intersect(kg, isect_array, P, dir, ray->time, PATH_RAY_SHADOW, object, primAddr);
+ 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: {
- if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
- hit = bvh_cardinal_curve_intersect(kg, isect_array, P, dir, PATH_RAY_SHADOW, object, primAddr, ray->time, type, NULL, 0, 0);
- else
- hit = bvh_curve_intersect(kg, isect_array, P, dir, PATH_RAY_SHADOW, object, primAddr, ray->time, type, NULL, 0, 0);
+ if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE) {
+ hit = bvh_cardinal_curve_intersect(kg,
+ isect_array,
+ P,
+ dir,
+ PATH_RAY_SHADOW,
+ object,
+ prim_addr,
+ ray->time,
+ type,
+ NULL,
+ 0, 0);
+ }
+ else {
+ hit = bvh_curve_intersect(kg,
+ isect_array,
+ P,
+ dir,
+ PATH_RAY_SHADOW,
+ object,
+ prim_addr,
+ ray->time,
+ type,
+ NULL,
+ 0, 0);
+ }
break;
}
#endif
@@ -308,13 +377,13 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
isect_array->t = isect_t;
}
- primAddr++;
+ prim_addr++;
}
}
#if BVH_FEATURE(BVH_INSTANCING)
else {
/* Instance push. */
- object = kernel_tex_fetch(__prim_object, -primAddr-1);
+ object = kernel_tex_fetch(__prim_object, -prim_addr-1);
# if BVH_FEATURE(BVH_MOTION)
bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &isect_t, &ob_itfm);
@@ -329,28 +398,33 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
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; }
tfar = ssef(isect_t);
+# if BVH_FEATURE(BVH_HAIR)
+ dir4 = sse3f(ssef(dir.x), ssef(dir.y), ssef(dir.z));
+# endif
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);
-# else
- org = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
# endif
+# if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
+ org4 = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
+# endif
+
triangle_intersect_precalc(dir, &isect_precalc);
- ++stackPtr;
- kernel_assert(stackPtr < BVH_QSTACK_SIZE);
- traversalStack[stackPtr].addr = ENTRYPOINT_SENTINEL;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = ENTRYPOINT_SENTINEL;
- nodeAddr = kernel_tex_fetch(__object_node, object);
+ node_addr = kernel_tex_fetch(__object_node, object);
}
}
#endif /* FEATURE(BVH_INSTANCING) */
- } while(nodeAddr != ENTRYPOINT_SENTINEL);
+ } while(node_addr != ENTRYPOINT_SENTINEL);
#if BVH_FEATURE(BVH_INSTANCING)
- if(stackPtr >= 0) {
+ if(stack_ptr >= 0) {
kernel_assert(object != OBJECT_NONE);
if(num_hits_in_instance) {
@@ -383,21 +457,28 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
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; }
tfar = ssef(tmax);
+# if BVH_FEATURE(BVH_HAIR)
+ dir4 = sse3f(ssef(dir.x), ssef(dir.y), ssef(dir.z));
+# endif
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);
-# else
- org = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
# endif
+# if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
+ org4 = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
+# endif
+
triangle_intersect_precalc(dir, &isect_precalc);
object = OBJECT_NONE;
- nodeAddr = traversalStack[stackPtr].addr;
- --stackPtr;
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
}
#endif /* FEATURE(BVH_INSTANCING) */
- } while(nodeAddr != ENTRYPOINT_SENTINEL);
+ } while(node_addr != ENTRYPOINT_SENTINEL);
return false;
}
+
+#undef NODE_INTERSECT
diff --git a/intern/cycles/kernel/geom/geom_qbvh_subsurface.h b/intern/cycles/kernel/bvh/qbvh_subsurface.h
index 84512a8783c..03794e3a882 100644
--- a/intern/cycles/kernel/geom/geom_qbvh_subsurface.h
+++ b/intern/cycles/kernel/bvh/qbvh_subsurface.h
@@ -25,6 +25,12 @@
*
*/
+#if BVH_FEATURE(BVH_HAIR)
+# define NODE_INTERSECT qbvh_node_intersect
+#else
+# define NODE_INTERSECT qbvh_aligned_node_intersect
+#endif
+
ccl_device void BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
const Ray *ray,
SubsurfaceIntersection *ss_isect,
@@ -41,12 +47,12 @@ ccl_device void BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
*/
/* Traversal stack in CUDA thread-local memory. */
- QBVHStackItem traversalStack[BVH_QSTACK_SIZE];
- traversalStack[0].addr = ENTRYPOINT_SENTINEL;
+ QBVHStackItem traversal_stack[BVH_QSTACK_SIZE];
+ traversal_stack[0].addr = ENTRYPOINT_SENTINEL;
/* Traversal variables in registers. */
- int stackPtr = 0;
- int nodeAddr = kernel_tex_fetch(__object_node, subsurface_object);
+ int stack_ptr = 0;
+ int node_addr = kernel_tex_fetch(__object_node, subsurface_object);
/* Ray parameters in registers. */
float3 P = ray->P;
@@ -82,13 +88,17 @@ ccl_device void BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
#endif
ssef tnear(0.0f), tfar(isect_t);
+#if BVH_FEATURE(BVH_HAIR)
+ sse3f dir4(ssef(dir.x), ssef(dir.y), ssef(dir.z));
+#endif
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);
-#else
- sse3f org = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
+ 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));
#endif
/* Offsets to select the side that becomes the lower or upper bound. */
@@ -106,29 +116,43 @@ ccl_device void BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
do {
do {
/* Traverse internal nodes. */
- while(nodeAddr >= 0 && nodeAddr != ENTRYPOINT_SENTINEL) {
+ while(node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) {
ssef dist;
- int traverseChild = qbvh_node_intersect(kg,
- tnear,
- tfar,
+ int child_mask = NODE_INTERSECT(kg,
+ tnear,
+ tfar,
#ifdef __KERNEL_AVX2__
- P_idir4,
-#else
- org,
+ P_idir4,
#endif
- idir4,
- near_x, near_y, near_z,
- far_x, far_y, far_z,
- nodeAddr,
- &dist);
+#if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
+ org4,
+#endif
+#if BVH_FEATURE(BVH_HAIR)
+ dir4,
+#endif
+ idir4,
+ near_x, near_y, near_z,
+ far_x, far_y, far_z,
+ node_addr,
+ &dist);
- if(traverseChild != 0) {
- float4 cnodes = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_QNODE_SIZE+6);
+ 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
+#endif
+ {
+ cnodes = kernel_tex_fetch(__bvh_nodes, node_addr+7);
+ }
/* One child is hit, continue with that child. */
- int r = __bscf(traverseChild);
- if(traverseChild == 0) {
- nodeAddr = __float_as_int(cnodes[r]);
+ int r = __bscf(child_mask);
+ if(child_mask == 0) {
+ node_addr = __float_as_int(cnodes[r]);
continue;
}
@@ -137,24 +161,24 @@ ccl_device void BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
*/
int c0 = __float_as_int(cnodes[r]);
float d0 = ((float*)&dist)[r];
- r = __bscf(traverseChild);
+ r = __bscf(child_mask);
int c1 = __float_as_int(cnodes[r]);
float d1 = ((float*)&dist)[r];
- if(traverseChild == 0) {
+ if(child_mask == 0) {
if(d1 < d0) {
- nodeAddr = c1;
- ++stackPtr;
- kernel_assert(stackPtr < BVH_QSTACK_SIZE);
- traversalStack[stackPtr].addr = c0;
- traversalStack[stackPtr].dist = 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 {
- nodeAddr = c0;
- ++stackPtr;
- kernel_assert(stackPtr < BVH_QSTACK_SIZE);
- traversalStack[stackPtr].addr = c1;
- traversalStack[stackPtr].dist = d1;
+ 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;
}
}
@@ -162,82 +186,82 @@ ccl_device void BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
/* Here starts the slow path for 3 or 4 hit children. We push
* all nodes onto the stack to sort them there.
*/
- ++stackPtr;
- kernel_assert(stackPtr < BVH_QSTACK_SIZE);
- traversalStack[stackPtr].addr = c1;
- traversalStack[stackPtr].dist = d1;
- ++stackPtr;
- kernel_assert(stackPtr < BVH_QSTACK_SIZE);
- traversalStack[stackPtr].addr = c0;
- traversalStack[stackPtr].dist = d0;
+ ++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(traverseChild);
+ r = __bscf(child_mask);
int c2 = __float_as_int(cnodes[r]);
float d2 = ((float*)&dist)[r];
- if(traverseChild == 0) {
- ++stackPtr;
- kernel_assert(stackPtr < BVH_QSTACK_SIZE);
- traversalStack[stackPtr].addr = c2;
- traversalStack[stackPtr].dist = d2;
- qbvh_stack_sort(&traversalStack[stackPtr],
- &traversalStack[stackPtr - 1],
- &traversalStack[stackPtr - 2]);
- nodeAddr = traversalStack[stackPtr].addr;
- --stackPtr;
+ 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(traverseChild);
+ r = __bscf(child_mask);
int c3 = __float_as_int(cnodes[r]);
float d3 = ((float*)&dist)[r];
- ++stackPtr;
- kernel_assert(stackPtr < BVH_QSTACK_SIZE);
- traversalStack[stackPtr].addr = c3;
- traversalStack[stackPtr].dist = d3;
- ++stackPtr;
- kernel_assert(stackPtr < BVH_QSTACK_SIZE);
- traversalStack[stackPtr].addr = c2;
- traversalStack[stackPtr].dist = d2;
- qbvh_stack_sort(&traversalStack[stackPtr],
- &traversalStack[stackPtr - 1],
- &traversalStack[stackPtr - 2],
- &traversalStack[stackPtr - 3]);
+ ++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]);
}
- nodeAddr = traversalStack[stackPtr].addr;
- --stackPtr;
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
}
/* If node is leaf, fetch triangle list. */
- if(nodeAddr < 0) {
- float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-nodeAddr-1)*BVH_QNODE_LEAF_SIZE);
- int primAddr = __float_as_int(leaf.x);
+ if(node_addr < 0) {
+ float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-node_addr-1));
+ int prim_addr = __float_as_int(leaf.x);
- int primAddr2 = __float_as_int(leaf.y);
+ int prim_addr2 = __float_as_int(leaf.y);
const uint type = __float_as_int(leaf.w);
/* Pop. */
- nodeAddr = traversalStack[stackPtr].addr;
- --stackPtr;
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
/* Primitive intersection. */
switch(type & PRIMITIVE_ALL) {
case PRIMITIVE_TRIANGLE: {
/* Intersect ray against primitive, */
- for(; primAddr < primAddr2; primAddr++) {
- kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ for(; prim_addr < prim_addr2; prim_addr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
triangle_intersect_subsurface(kg,
&isect_precalc,
ss_isect,
P,
object,
- primAddr,
+ prim_addr,
isect_t,
lcg_state,
max_hits);
@@ -247,15 +271,15 @@ ccl_device void BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
#if BVH_FEATURE(BVH_MOTION)
case PRIMITIVE_MOTION_TRIANGLE: {
/* Intersect ray against primitive. */
- for(; primAddr < primAddr2; primAddr++) {
- kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ for(; prim_addr < prim_addr2; prim_addr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
motion_triangle_intersect_subsurface(kg,
ss_isect,
P,
dir,
ray->time,
object,
- primAddr,
+ prim_addr,
isect_t,
lcg_state,
max_hits);
@@ -267,6 +291,8 @@ ccl_device void BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
break;
}
}
- } while(nodeAddr != ENTRYPOINT_SENTINEL);
- } while(nodeAddr != ENTRYPOINT_SENTINEL);
+ } while(node_addr != ENTRYPOINT_SENTINEL);
+ } while(node_addr != ENTRYPOINT_SENTINEL);
}
+
+#undef NODE_INTERSECT
diff --git a/intern/cycles/kernel/bvh/qbvh_traversal.h b/intern/cycles/kernel/bvh/qbvh_traversal.h
new file mode 100644
index 00000000000..f82ff661495
--- /dev/null
+++ b/intern/cycles/kernel/bvh/qbvh_traversal.h
@@ -0,0 +1,505 @@
+/*
+ * Adapted from code Copyright 2009-2010 NVIDIA Corporation,
+ * and code copyright 2009-2012 Intel Corporation
+ *
+ * Modifications Copyright 2011-2014, Blender Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* This is a template BVH traversal function, where various features can be
+ * enabled/disabled. This way we can compile optimized versions for each case
+ * without new features slowing things down.
+ *
+ * BVH_INSTANCING: object instancing
+ * BVH_HAIR: hair curve rendering
+ * BVH_HAIR_MINIMUM_WIDTH: hair curve rendering with minimum width
+ * BVH_MOTION: motion blur rendering
+ *
+ */
+
+#if BVH_FEATURE(BVH_HAIR)
+# define NODE_INTERSECT qbvh_node_intersect
+# define NODE_INTERSECT_ROBUST qbvh_node_intersect_robust
+#else
+# define NODE_INTERSECT qbvh_aligned_node_intersect
+# define NODE_INTERSECT_ROBUST qbvh_aligned_node_intersect_robust
+#endif
+
+ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
+ const Ray *ray,
+ Intersection *isect,
+ const uint visibility
+#if BVH_FEATURE(BVH_HAIR_MINIMUM_WIDTH)
+ ,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;
+
+#if BVH_FEATURE(BVH_MOTION)
+ Transform ob_itfm;
+#endif
+
+#ifndef __KERNEL_SSE41__
+ if(!isfinite(P.x)) {
+ return false;
+ }
+#endif
+
+ isect->t = ray->t;
+ isect->u = 0.0f;
+ isect->v = 0.0f;
+ isect->prim = PRIM_NONE;
+ isect->object = OBJECT_NONE;
+
+ BVH_DEBUG_INIT();
+
+ ssef tnear(0.0f), tfar(ray->t);
+#if BVH_FEATURE(BVH_HAIR)
+ sse3f dir4(ssef(dir.x), ssef(dir.y), ssef(dir.z));
+#endif
+ 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);
+#endif
+#if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
+ 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;
+
+ 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; }
+
+ IsectPrecalc isect_precalc;
+ triangle_intersect_precalc(dir, &isect_precalc);
+
+ /* 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);
+
+ if(UNLIKELY(node_dist > isect->t)
+#ifdef __VISIBILITY_FLAG__
+ || (__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;
+ }
+
+ int child_mask;
+ ssef dist;
+
+ BVH_DEBUG_NEXT_STEP();
+
+#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,
+# ifdef __KERNEL_AVX2__
+ P_idir4,
+# endif
+# if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
+ org4,
+# endif
+# if BVH_FEATURE(BVH_HAIR)
+ 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,
+#ifdef __KERNEL_AVX2__
+ P_idir4,
+#endif
+#if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
+ org4,
+#endif
+#if BVH_FEATURE(BVH_HAIR)
+ 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),
+ */
+#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
+#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));
+
+#ifdef __VISIBILITY_FLAG__
+ if(UNLIKELY((node_dist > isect->t) ||
+ ((__float_as_uint(leaf.z) & visibility) == 0)))
+#else
+ 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);
+
+#if BVH_FEATURE(BVH_INSTANCING)
+ 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_STEP();
+ kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
+ if(triangle_intersect(kg,
+ &isect_precalc,
+ isect,
+ P,
+ 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_STEP();
+ 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_STEP();
+ kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
+ bool hit;
+ if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE) {
+ hit = bvh_cardinal_curve_intersect(kg,
+ isect,
+ P,
+ dir,
+ visibility,
+ object,
+ prim_addr,
+ ray->time,
+ type,
+ lcg_state,
+ difl,
+ extmax);
+ }
+ else {
+ hit = bvh_curve_intersect(kg,
+ isect,
+ P,
+ dir,
+ visibility,
+ object,
+ prim_addr,
+ ray->time,
+ 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);
+
+# if BVH_FEATURE(BVH_MOTION)
+ 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);
+# endif
+
+ 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; }
+ tfar = ssef(isect->t);
+# if BVH_FEATURE(BVH_HAIR)
+ dir4 = sse3f(ssef(dir.x), ssef(dir.y), ssef(dir.z));
+# endif
+ 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);
+# endif
+# if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
+ org4 = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
+# endif
+
+ triangle_intersect_precalc(dir, &isect_precalc);
+
+ ++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);
+
+ 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);
+
+ /* Instance pop. */
+# if BVH_FEATURE(BVH_MOTION)
+ bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, &isect->t, &ob_itfm);
+# else
+ bvh_instance_pop(kg, object, ray, &P, &dir, &idir, &isect->t);
+# endif
+
+ 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; }
+ tfar = ssef(isect->t);
+# if BVH_FEATURE(BVH_HAIR)
+ dir4 = sse3f(ssef(dir.x), ssef(dir.y), ssef(dir.z));
+# endif
+ 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);
+# endif
+# if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
+ org4 = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
+# endif
+
+ triangle_intersect_precalc(dir, &isect_precalc);
+
+ 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);
+}
+
+#undef NODE_INTERSECT
+#undef NODE_INTERSECT_ROBUST
diff --git a/intern/cycles/kernel/geom/geom_qbvh_volume.h b/intern/cycles/kernel/bvh/qbvh_volume.h
index ab2e530dd20..b4f334eb842 100644
--- a/intern/cycles/kernel/geom/geom_qbvh_volume.h
+++ b/intern/cycles/kernel/bvh/qbvh_volume.h
@@ -26,6 +26,12 @@
*
*/
+#if BVH_FEATURE(BVH_HAIR)
+# define NODE_INTERSECT qbvh_node_intersect
+#else
+# define NODE_INTERSECT qbvh_aligned_node_intersect
+#endif
+
ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
const Ray *ray,
Intersection *isect,
@@ -38,12 +44,12 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
*/
/* Traversal stack in CUDA thread-local memory. */
- QBVHStackItem traversalStack[BVH_QSTACK_SIZE];
- traversalStack[0].addr = ENTRYPOINT_SENTINEL;
+ QBVHStackItem traversal_stack[BVH_QSTACK_SIZE];
+ traversal_stack[0].addr = ENTRYPOINT_SENTINEL;
/* Traversal variables in registers. */
- int stackPtr = 0;
- int nodeAddr = kernel_data.bvh.root;
+ int stack_ptr = 0;
+ int node_addr = kernel_data.bvh.root;
/* Ray parameters in registers. */
float3 P = ray->P;
@@ -68,13 +74,17 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
isect->object = OBJECT_NONE;
ssef tnear(0.0f), tfar(ray->t);
+#if BVH_FEATURE(BVH_HAIR)
+ sse3f dir4(ssef(dir.x), ssef(dir.y), ssef(dir.z));
+#endif
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);
-#else
- sse3f org = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
+ 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));
#endif
/* Offsets to select the side that becomes the lower or upper bound. */
@@ -92,29 +102,52 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
do {
do {
/* Traverse internal nodes. */
- while(nodeAddr >= 0 && nodeAddr != ENTRYPOINT_SENTINEL) {
+ while(node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) {
+#ifdef __VISIBILITY_FLAG__
+ float4 inodes = kernel_tex_fetch(__bvh_nodes, node_addr+0);
+ if((__float_as_uint(inodes.x) & visibility) == 0) {
+ /* Pop. */
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ continue;
+ }
+#endif
+
ssef dist;
- int traverseChild = qbvh_node_intersect(kg,
- tnear,
- tfar,
+ int child_mask = NODE_INTERSECT(kg,
+ tnear,
+ tfar,
#ifdef __KERNEL_AVX2__
- P_idir4,
-#else
- org,
+ P_idir4,
#endif
- idir4,
- near_x, near_y, near_z,
- far_x, far_y, far_z,
- nodeAddr,
- &dist);
-
- if(traverseChild != 0) {
- float4 cnodes = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_QNODE_SIZE+6);
+#if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
+ org4,
+#endif
+#if BVH_FEATURE(BVH_HAIR)
+ dir4,
+#endif
+ 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
+#endif
+ {
+ cnodes = kernel_tex_fetch(__bvh_nodes, node_addr+7);
+ }
/* One child is hit, continue with that child. */
- int r = __bscf(traverseChild);
- if(traverseChild == 0) {
- nodeAddr = __float_as_int(cnodes[r]);
+ int r = __bscf(child_mask);
+ if(child_mask == 0) {
+ node_addr = __float_as_int(cnodes[r]);
continue;
}
@@ -123,24 +156,24 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
*/
int c0 = __float_as_int(cnodes[r]);
float d0 = ((float*)&dist)[r];
- r = __bscf(traverseChild);
+ r = __bscf(child_mask);
int c1 = __float_as_int(cnodes[r]);
float d1 = ((float*)&dist)[r];
- if(traverseChild == 0) {
+ if(child_mask == 0) {
if(d1 < d0) {
- nodeAddr = c1;
- ++stackPtr;
- kernel_assert(stackPtr < BVH_QSTACK_SIZE);
- traversalStack[stackPtr].addr = c0;
- traversalStack[stackPtr].dist = 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 {
- nodeAddr = c0;
- ++stackPtr;
- kernel_assert(stackPtr < BVH_QSTACK_SIZE);
- traversalStack[stackPtr].addr = c1;
- traversalStack[stackPtr].dist = d1;
+ 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;
}
}
@@ -148,102 +181,102 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
/* Here starts the slow path for 3 or 4 hit children. We push
* all nodes onto the stack to sort them there.
*/
- ++stackPtr;
- kernel_assert(stackPtr < BVH_QSTACK_SIZE);
- traversalStack[stackPtr].addr = c1;
- traversalStack[stackPtr].dist = d1;
- ++stackPtr;
- kernel_assert(stackPtr < BVH_QSTACK_SIZE);
- traversalStack[stackPtr].addr = c0;
- traversalStack[stackPtr].dist = d0;
+ ++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(traverseChild);
+ r = __bscf(child_mask);
int c2 = __float_as_int(cnodes[r]);
float d2 = ((float*)&dist)[r];
- if(traverseChild == 0) {
- ++stackPtr;
- kernel_assert(stackPtr < BVH_QSTACK_SIZE);
- traversalStack[stackPtr].addr = c2;
- traversalStack[stackPtr].dist = d2;
- qbvh_stack_sort(&traversalStack[stackPtr],
- &traversalStack[stackPtr - 1],
- &traversalStack[stackPtr - 2]);
- nodeAddr = traversalStack[stackPtr].addr;
- --stackPtr;
+ 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(traverseChild);
+ r = __bscf(child_mask);
int c3 = __float_as_int(cnodes[r]);
float d3 = ((float*)&dist)[r];
- ++stackPtr;
- kernel_assert(stackPtr < BVH_QSTACK_SIZE);
- traversalStack[stackPtr].addr = c3;
- traversalStack[stackPtr].dist = d3;
- ++stackPtr;
- kernel_assert(stackPtr < BVH_QSTACK_SIZE);
- traversalStack[stackPtr].addr = c2;
- traversalStack[stackPtr].dist = d2;
- qbvh_stack_sort(&traversalStack[stackPtr],
- &traversalStack[stackPtr - 1],
- &traversalStack[stackPtr - 2],
- &traversalStack[stackPtr - 3]);
+ ++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]);
}
- nodeAddr = traversalStack[stackPtr].addr;
- --stackPtr;
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
}
/* If node is leaf, fetch triangle list. */
- if(nodeAddr < 0) {
- float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-nodeAddr-1)*BVH_QNODE_LEAF_SIZE);
- int primAddr = __float_as_int(leaf.x);
+ 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(primAddr >= 0) {
+ if(prim_addr >= 0) {
#endif
- int primAddr2 = __float_as_int(leaf.y);
+ int prim_addr2 = __float_as_int(leaf.y);
const uint type = __float_as_int(leaf.w);
const uint p_type = type & PRIMITIVE_ALL;
/* Pop. */
- nodeAddr = traversalStack[stackPtr].addr;
- --stackPtr;
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
/* Primitive intersection. */
switch(p_type) {
case PRIMITIVE_TRIANGLE: {
- for(; primAddr < primAddr2; primAddr++) {
- kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ 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, primAddr): 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_precalc, isect, P, visibility, object, primAddr);
+ triangle_intersect(kg, &isect_precalc, isect, P, visibility, object, prim_addr);
}
break;
}
#if BVH_FEATURE(BVH_MOTION)
case PRIMITIVE_MOTION_TRIANGLE: {
- for(; primAddr < primAddr2; primAddr++) {
- kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ 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, primAddr): 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, primAddr);
+ motion_triangle_intersect(kg, isect, P, dir, ray->time, visibility, object, prim_addr);
}
break;
}
@@ -253,7 +286,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
#if BVH_FEATURE(BVH_INSTANCING)
else {
/* Instance push. */
- object = kernel_tex_fetch(__prim_object, -primAddr-1);
+ 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) {
@@ -268,34 +301,39 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
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; }
tfar = ssef(isect->t);
+# if BVH_FEATURE(BVH_HAIR)
+ dir4 = sse3f(ssef(dir.x), ssef(dir.y), ssef(dir.z));
+# endif
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);
-# else
- org = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
# endif
+# if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
+ org4 = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
+# endif
+
triangle_intersect_precalc(dir, &isect_precalc);
- ++stackPtr;
- kernel_assert(stackPtr < BVH_QSTACK_SIZE);
- traversalStack[stackPtr].addr = ENTRYPOINT_SENTINEL;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = ENTRYPOINT_SENTINEL;
- nodeAddr = kernel_tex_fetch(__object_node, object);
+ node_addr = kernel_tex_fetch(__object_node, object);
}
else {
/* Pop. */
object = OBJECT_NONE;
- nodeAddr = traversalStack[stackPtr].addr;
- --stackPtr;
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
}
}
}
#endif /* FEATURE(BVH_INSTANCING) */
- } while(nodeAddr != ENTRYPOINT_SENTINEL);
+ } while(node_addr != ENTRYPOINT_SENTINEL);
#if BVH_FEATURE(BVH_INSTANCING)
- if(stackPtr >= 0) {
+ if(stack_ptr >= 0) {
kernel_assert(object != OBJECT_NONE);
/* Instance pop. */
@@ -309,21 +347,28 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
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; }
tfar = ssef(isect->t);
+# if BVH_FEATURE(BVH_HAIR)
+ dir4 = sse3f(ssef(dir.x), ssef(dir.y), ssef(dir.z));
+# endif
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);
-# else
- org = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
# endif
+# if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
+ org4 = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
+# endif
+
triangle_intersect_precalc(dir, &isect_precalc);
object = OBJECT_NONE;
- nodeAddr = traversalStack[stackPtr].addr;
- --stackPtr;
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
}
#endif /* FEATURE(BVH_INSTANCING) */
- } while(nodeAddr != ENTRYPOINT_SENTINEL);
+ } while(node_addr != ENTRYPOINT_SENTINEL);
return (isect->prim != PRIM_NONE);
}
+
+#undef NODE_INTERSECT
diff --git a/intern/cycles/kernel/geom/geom_qbvh_volume_all.h b/intern/cycles/kernel/bvh/qbvh_volume_all.h
index 5546471b0e3..4d3028b37bf 100644
--- a/intern/cycles/kernel/geom/geom_qbvh_volume_all.h
+++ b/intern/cycles/kernel/bvh/qbvh_volume_all.h
@@ -26,6 +26,12 @@
*
*/
+#if BVH_FEATURE(BVH_HAIR)
+# define NODE_INTERSECT qbvh_node_intersect
+#else
+# define NODE_INTERSECT qbvh_aligned_node_intersect
+#endif
+
ccl_device uint BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
const Ray *ray,
Intersection *isect_array,
@@ -39,12 +45,12 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
*/
/* Traversal stack in CUDA thread-local memory. */
- QBVHStackItem traversalStack[BVH_QSTACK_SIZE];
- traversalStack[0].addr = ENTRYPOINT_SENTINEL;
+ QBVHStackItem traversal_stack[BVH_QSTACK_SIZE];
+ traversal_stack[0].addr = ENTRYPOINT_SENTINEL;
/* Traversal variables in registers. */
- int stackPtr = 0;
- int nodeAddr = kernel_data.bvh.root;
+ int stack_ptr = 0;
+ int node_addr = kernel_data.bvh.root;
/* Ray parameters in registers. */
const float tmax = ray->t;
@@ -72,13 +78,17 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
#endif
ssef tnear(0.0f), tfar(isect_t);
+#if BVH_FEATURE(BVH_HAIR)
+ sse3f dir4(ssef(dir.x), ssef(dir.y), ssef(dir.z));
+#endif
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);
-#else
- sse3f org = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
+ 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));
#endif
/* Offsets to select the side that becomes the lower or upper bound. */
@@ -96,29 +106,52 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
do {
do {
/* Traverse internal nodes. */
- while(nodeAddr >= 0 && nodeAddr != ENTRYPOINT_SENTINEL) {
+ while(node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) {
+#ifdef __VISIBILITY_FLAG__
+ float4 inodes = kernel_tex_fetch(__bvh_nodes, node_addr+0);
+ if((__float_as_uint(inodes.x) & visibility) == 0) {
+ /* Pop. */
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
+ continue;
+ }
+#endif
+
ssef dist;
- int traverseChild = qbvh_node_intersect(kg,
- tnear,
- tfar,
+ int child_mask = NODE_INTERSECT(kg,
+ tnear,
+ tfar,
#ifdef __KERNEL_AVX2__
- P_idir4,
-#else
- org,
+ P_idir4,
#endif
- idir4,
- near_x, near_y, near_z,
- far_x, far_y, far_z,
- nodeAddr,
- &dist);
-
- if(traverseChild != 0) {
- float4 cnodes = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_QNODE_SIZE+6);
+#if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
+ org4,
+#endif
+#if BVH_FEATURE(BVH_HAIR)
+ dir4,
+#endif
+ 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
+#endif
+ {
+ cnodes = kernel_tex_fetch(__bvh_nodes, node_addr+7);
+ }
/* One child is hit, continue with that child. */
- int r = __bscf(traverseChild);
- if(traverseChild == 0) {
- nodeAddr = __float_as_int(cnodes[r]);
+ int r = __bscf(child_mask);
+ if(child_mask == 0) {
+ node_addr = __float_as_int(cnodes[r]);
continue;
}
@@ -127,24 +160,24 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
*/
int c0 = __float_as_int(cnodes[r]);
float d0 = ((float*)&dist)[r];
- r = __bscf(traverseChild);
+ r = __bscf(child_mask);
int c1 = __float_as_int(cnodes[r]);
float d1 = ((float*)&dist)[r];
- if(traverseChild == 0) {
+ if(child_mask == 0) {
if(d1 < d0) {
- nodeAddr = c1;
- ++stackPtr;
- kernel_assert(stackPtr < BVH_QSTACK_SIZE);
- traversalStack[stackPtr].addr = c0;
- traversalStack[stackPtr].dist = 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 {
- nodeAddr = c0;
- ++stackPtr;
- kernel_assert(stackPtr < BVH_QSTACK_SIZE);
- traversalStack[stackPtr].addr = c1;
- traversalStack[stackPtr].dist = d1;
+ 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;
}
}
@@ -152,88 +185,88 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
/* Here starts the slow path for 3 or 4 hit children. We push
* all nodes onto the stack to sort them there.
*/
- ++stackPtr;
- kernel_assert(stackPtr < BVH_QSTACK_SIZE);
- traversalStack[stackPtr].addr = c1;
- traversalStack[stackPtr].dist = d1;
- ++stackPtr;
- kernel_assert(stackPtr < BVH_QSTACK_SIZE);
- traversalStack[stackPtr].addr = c0;
- traversalStack[stackPtr].dist = d0;
+ ++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(traverseChild);
+ r = __bscf(child_mask);
int c2 = __float_as_int(cnodes[r]);
float d2 = ((float*)&dist)[r];
- if(traverseChild == 0) {
- ++stackPtr;
- kernel_assert(stackPtr < BVH_QSTACK_SIZE);
- traversalStack[stackPtr].addr = c2;
- traversalStack[stackPtr].dist = d2;
- qbvh_stack_sort(&traversalStack[stackPtr],
- &traversalStack[stackPtr - 1],
- &traversalStack[stackPtr - 2]);
- nodeAddr = traversalStack[stackPtr].addr;
- --stackPtr;
+ 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(traverseChild);
+ r = __bscf(child_mask);
int c3 = __float_as_int(cnodes[r]);
float d3 = ((float*)&dist)[r];
- ++stackPtr;
- kernel_assert(stackPtr < BVH_QSTACK_SIZE);
- traversalStack[stackPtr].addr = c3;
- traversalStack[stackPtr].dist = d3;
- ++stackPtr;
- kernel_assert(stackPtr < BVH_QSTACK_SIZE);
- traversalStack[stackPtr].addr = c2;
- traversalStack[stackPtr].dist = d2;
- qbvh_stack_sort(&traversalStack[stackPtr],
- &traversalStack[stackPtr - 1],
- &traversalStack[stackPtr - 2],
- &traversalStack[stackPtr - 3]);
+ ++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]);
}
- nodeAddr = traversalStack[stackPtr].addr;
- --stackPtr;
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
}
/* If node is leaf, fetch triangle list. */
- if(nodeAddr < 0) {
- float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-nodeAddr-1)*BVH_QNODE_LEAF_SIZE);
- int primAddr = __float_as_int(leaf.x);
+ 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(primAddr >= 0) {
+ if(prim_addr >= 0) {
#endif
- int primAddr2 = __float_as_int(leaf.y);
+ 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. */
- nodeAddr = traversalStack[stackPtr].addr;
- --stackPtr;
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
/* Primitive intersection. */
switch(p_type) {
case PRIMITIVE_TRIANGLE: {
- for(; primAddr < primAddr2; primAddr++) {
- kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ 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, primAddr): 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_precalc, isect_array, P, visibility, object, primAddr);
+ hit = triangle_intersect(kg, &isect_precalc, isect_array, P, visibility, object, prim_addr);
if(hit) {
/* Move on to next entry in intersections array. */
isect_array++;
@@ -262,16 +295,16 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
}
#if BVH_FEATURE(BVH_MOTION)
case PRIMITIVE_MOTION_TRIANGLE: {
- for(; primAddr < primAddr2; primAddr++) {
- kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ 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, primAddr): 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, primAddr);
+ 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++;
@@ -304,7 +337,7 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
#if BVH_FEATURE(BVH_INSTANCING)
else {
/* Instance push. */
- object = kernel_tex_fetch(__prim_object, -primAddr-1);
+ 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) {
@@ -320,35 +353,40 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
if(idir.z >= 0.0f) { near_z = 4; far_z = 5; } else { near_z = 5; far_z = 4; }
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));
+# endif
# ifdef __KERNEL_AVX2__
P_idir = P*idir;
P_idir4 = sse3f(P_idir.x, P_idir.y, P_idir.z);
-# else
- org = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
# endif
+# if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
+ org4 = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
+# endif
+
triangle_intersect_precalc(dir, &isect_precalc);
num_hits_in_instance = 0;
isect_array->t = isect_t;
- ++stackPtr;
- kernel_assert(stackPtr < BVH_QSTACK_SIZE);
- traversalStack[stackPtr].addr = ENTRYPOINT_SENTINEL;
+ ++stack_ptr;
+ kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
+ traversal_stack[stack_ptr].addr = ENTRYPOINT_SENTINEL;
- nodeAddr = kernel_tex_fetch(__object_node, object);
+ node_addr = kernel_tex_fetch(__object_node, object);
}
else {
/* Pop. */
object = OBJECT_NONE;
- nodeAddr = traversalStack[stackPtr].addr;
- --stackPtr;
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
}
}
}
#endif /* FEATURE(BVH_INSTANCING) */
- } while(nodeAddr != ENTRYPOINT_SENTINEL);
+ } while(node_addr != ENTRYPOINT_SENTINEL);
#if BVH_FEATURE(BVH_INSTANCING)
- if(stackPtr >= 0) {
+ if(stack_ptr >= 0) {
kernel_assert(object != OBJECT_NONE);
/* Instance pop. */
@@ -379,23 +417,30 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
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; }
tfar = ssef(isect_t);
+# if BVH_FEATURE(BVH_HAIR)
+ dir4 = sse3f(ssef(dir.x), ssef(dir.y), ssef(dir.z));
+# endif
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);
-# else
- org = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
# endif
+# if BVH_FEATURE(BVH_HAIR) || !defined(__KERNEL_AVX2__)
+ org4 = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
+# endif
+
triangle_intersect_precalc(dir, &isect_precalc);
isect_t = tmax;
isect_array->t = isect_t;
object = OBJECT_NONE;
- nodeAddr = traversalStack[stackPtr].addr;
- --stackPtr;
+ node_addr = traversal_stack[stack_ptr].addr;
+ --stack_ptr;
}
#endif /* FEATURE(BVH_INSTANCING) */
- } while(nodeAddr != ENTRYPOINT_SENTINEL);
+ } while(node_addr != ENTRYPOINT_SENTINEL);
return num_hits;
}
+
+#undef NODE_INTERSECT
diff --git a/intern/cycles/kernel/closure/alloc.h b/intern/cycles/kernel/closure/alloc.h
new file mode 100644
index 00000000000..b7abc1ec507
--- /dev/null
+++ b/intern/cycles/kernel/closure/alloc.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2011-2016 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+CCL_NAMESPACE_BEGIN
+
+ccl_device ShaderClosure *closure_alloc(ShaderData *sd, int size, ClosureType type, float3 weight)
+{
+ kernel_assert(size <= sizeof(ShaderClosure));
+
+ int num_closure = ccl_fetch(sd, num_closure);
+ int num_closure_extra = ccl_fetch(sd, num_closure_extra);
+ if(num_closure + num_closure_extra >= MAX_CLOSURE)
+ return NULL;
+
+ ShaderClosure *sc = &ccl_fetch(sd, closure)[num_closure];
+
+ sc->type = type;
+ sc->weight = weight;
+
+ ccl_fetch(sd, num_closure)++;
+
+ 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));
+ int num_closure = ccl_fetch(sd, num_closure);
+ int num_closure_extra = ccl_fetch(sd, num_closure_extra) + num_extra;
+
+ if(num_closure + num_closure_extra > MAX_CLOSURE) {
+ /* Remove previous closure. */
+ ccl_fetch(sd, num_closure)--;
+ ccl_fetch(sd, num_closure_extra)++;
+ return NULL;
+ }
+
+ ccl_fetch(sd, num_closure_extra) = num_closure_extra;
+ return (ccl_addr_space void*)(ccl_fetch(sd, closure) + MAX_CLOSURE - num_closure_extra);
+}
+
+ccl_device_inline ShaderClosure *bsdf_alloc(ShaderData *sd, int size, float3 weight)
+{
+ ShaderClosure *sc = closure_alloc(sd, size, CLOSURE_NONE_ID, weight);
+
+ if(!sc)
+ return 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)
+{
+ ShaderClosure *sc = closure_alloc(sd, size, CLOSURE_NONE_ID, weight);
+
+ if(!sc)
+ return NULL;
+
+ memcpy(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;
+}
+#endif
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/closure/bsdf.h b/intern/cycles/kernel/closure/bsdf.h
index 1f225e1e96c..72096f4d873 100644
--- a/intern/cycles/kernel/closure/bsdf.h
+++ b/intern/cycles/kernel/closure/bsdf.h
@@ -20,6 +20,7 @@
#include "../closure/bsdf_phong_ramp.h"
#include "../closure/bsdf_diffuse_ramp.h"
#include "../closure/bsdf_microfacet.h"
+#include "../closure/bsdf_microfacet_multi.h"
#include "../closure/bsdf_reflection.h"
#include "../closure/bsdf_refraction.h"
#include "../closure/bsdf_transparent.h"
@@ -39,15 +40,10 @@
CCL_NAMESPACE_BEGIN
-ccl_device int bsdf_sample(KernelGlobals *kg, const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, differential3 *domega_in, float *pdf)
+ccl_device int bsdf_sample(KernelGlobals *kg, ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, differential3 *domega_in, float *pdf)
{
int label;
-#ifdef __OSL__
- if(kg->osl && sc->prim)
- return OSLShader::bsdf_sample(sd, sc, randu, randv, *eval, *omega_in, *domega_in, *pdf);
-#endif
-
switch(sc->type) {
case CLOSURE_BSDF_DIFFUSE_ID:
case CLOSURE_BSDF_BSSRDF_ID:
@@ -59,14 +55,16 @@ ccl_device int bsdf_sample(KernelGlobals *kg, const ShaderData *sd, const Shader
label = bsdf_oren_nayar_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
- /*case CLOSURE_BSDF_PHONG_RAMP_ID:
+#ifdef __OSL__
+ case CLOSURE_BSDF_PHONG_RAMP_ID:
label = bsdf_phong_ramp_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(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, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
- break;*/
+ break;
+#endif
case CLOSURE_BSDF_TRANSLUCENT_ID:
label = bsdf_translucent_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
@@ -89,6 +87,14 @@ ccl_device int bsdf_sample(KernelGlobals *kg, const ShaderData *sd, const Shader
label = bsdf_microfacet_ggx_sample(kg, sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
+ label = bsdf_microfacet_multi_ggx_sample(kg, sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
+ eval, omega_in, &domega_in->dx, &domega_in->dy, pdf, &ccl_fetch(sd, lcg_state));
+ break;
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
+ label = bsdf_microfacet_multi_ggx_glass_sample(kg, sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
+ eval, omega_in, &domega_in->dx, &domega_in->dy, pdf, &ccl_fetch(sd, lcg_state));
+ break;
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
@@ -129,10 +135,10 @@ ccl_device int bsdf_sample(KernelGlobals *kg, const ShaderData *sd, const Shader
label = bsdf_disney_sheen_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
- case CLOSURE_BSDF_DISNEY_SPECULAR_ID:
+ /*case CLOSURE_BSDF_DISNEY_SPECULAR_ID:
label = bsdf_disney_specular_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
- break;
+ break;*/
case CLOSURE_BSDF_DISNEY_CLEARCOAT_ID:
label = bsdf_disney_clearcoat_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
@@ -151,15 +157,10 @@ ccl_device int bsdf_sample(KernelGlobals *kg, const ShaderData *sd, const Shader
return label;
}
-ccl_device float3 bsdf_eval(KernelGlobals *kg, const ShaderData *sd, const ShaderClosure *sc, const float3 omega_in, float *pdf)
+ccl_device float3 bsdf_eval(KernelGlobals *kg, ShaderData *sd, const ShaderClosure *sc, const float3 omega_in, float *pdf)
{
float3 eval;
-#ifdef __OSL__
- if(kg->osl && sc->prim)
- return OSLShader::bsdf_eval(sd, sc, omega_in, *pdf);
-#endif
-
if(dot(ccl_fetch(sd, Ng), omega_in) >= 0.0f) {
switch(sc->type) {
case CLOSURE_BSDF_DIFFUSE_ID:
@@ -170,12 +171,14 @@ ccl_device float3 bsdf_eval(KernelGlobals *kg, const ShaderData *sd, const Shade
case CLOSURE_BSDF_OREN_NAYAR_ID:
eval = bsdf_oren_nayar_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
break;
- /*case CLOSURE_BSDF_PHONG_RAMP_ID:
+#ifdef __OSL__
+ case CLOSURE_BSDF_PHONG_RAMP_ID:
eval = bsdf_phong_ramp_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
break;
case CLOSURE_BSDF_DIFFUSE_RAMP_ID:
eval = bsdf_diffuse_ramp_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
- break;*/
+ break;
+#endif
case CLOSURE_BSDF_TRANSLUCENT_ID:
eval = bsdf_translucent_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
break;
@@ -193,6 +196,12 @@ ccl_device float3 bsdf_eval(KernelGlobals *kg, const ShaderData *sd, const Shade
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
eval = bsdf_microfacet_ggx_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
break;
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
+ eval = bsdf_microfacet_multi_ggx_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf, &ccl_fetch(sd, lcg_state));
+ break;
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
+ eval = bsdf_microfacet_multi_ggx_glass_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf, &ccl_fetch(sd, lcg_state));
+ break;
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
@@ -224,9 +233,9 @@ ccl_device float3 bsdf_eval(KernelGlobals *kg, const ShaderData *sd, const Shade
case CLOSURE_BSDF_DISNEY_SHEEN_ID:
eval = bsdf_disney_sheen_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
break;
- case CLOSURE_BSDF_DISNEY_SPECULAR_ID:
+ /*case CLOSURE_BSDF_DISNEY_SPECULAR_ID:
eval = bsdf_disney_specular_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
- break;
+ break;*/
case CLOSURE_BSDF_DISNEY_CLEARCOAT_ID:
eval = bsdf_disney_clearcoat_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
break;
@@ -268,6 +277,12 @@ ccl_device float3 bsdf_eval(KernelGlobals *kg, const ShaderData *sd, const Shade
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
eval = bsdf_microfacet_ggx_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf);
break;
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
+ eval = bsdf_microfacet_multi_ggx_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf, &ccl_fetch(sd, lcg_state));
+ break;
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
+ eval = bsdf_microfacet_multi_ggx_glass_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf, &ccl_fetch(sd, lcg_state));
+ break;
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
@@ -299,9 +314,9 @@ ccl_device float3 bsdf_eval(KernelGlobals *kg, const ShaderData *sd, const Shade
case CLOSURE_BSDF_DISNEY_SHEEN_ID:
eval = bsdf_disney_sheen_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf);
break;
- case CLOSURE_BSDF_DISNEY_SPECULAR_ID:
+ /*case CLOSURE_BSDF_DISNEY_SPECULAR_ID:
eval = bsdf_disney_specular_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf);
- break;
+ break;*/
case CLOSURE_BSDF_DISNEY_CLEARCOAT_ID:
eval = bsdf_disney_clearcoat_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf);
break;
@@ -322,17 +337,13 @@ ccl_device float3 bsdf_eval(KernelGlobals *kg, const ShaderData *sd, const Shade
ccl_device void bsdf_blur(KernelGlobals *kg, ShaderClosure *sc, float roughness)
{
-/* ToDo: do we want to blur volume closures? */
-
-#ifdef __OSL__
- if(kg->osl && sc->prim) {
- OSLShader::bsdf_blur(sc, roughness);
- return;
- }
-#endif
-
+ /* 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_GLASS_ID:
+ bsdf_microfacet_multi_ggx_blur(sc, roughness);
+ break;
case CLOSURE_BSDF_MICROFACET_GGX_ID:
case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
@@ -353,5 +364,48 @@ ccl_device void bsdf_blur(KernelGlobals *kg, ShaderClosure *sc, float roughness)
#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_ANISO_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_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 __VOLUME__
+ case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
+ return volume_henyey_greenstein_merge(a, b);
+#endif
+ default:
+ return false;
+ }
+#endif
+}
+
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h b/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h
index 8d7d533d6f8..8ed76bea525 100644
--- a/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h
+++ b/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h
@@ -31,28 +31,30 @@ Other than that, the implementation directly follows the paper.
CCL_NAMESPACE_BEGIN
-ccl_device int bsdf_ashikhmin_shirley_setup(ShaderClosure *sc)
+ccl_device int bsdf_ashikhmin_shirley_setup(MicrofacetBsdf *bsdf)
{
- sc->data0 = clamp(sc->data0, 1e-4f, 1.0f);
- sc->data1 = sc->data0;
+ bsdf->alpha_x = clamp(bsdf->alpha_x, 1e-4f, 1.0f);
+ bsdf->alpha_y = bsdf->alpha_x;
- sc->type = CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID;
+ bsdf->type = CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID;
return SD_BSDF|SD_BSDF_HAS_EVAL;
}
-ccl_device int bsdf_ashikhmin_shirley_aniso_setup(ShaderClosure *sc)
+ccl_device int bsdf_ashikhmin_shirley_aniso_setup(MicrofacetBsdf *bsdf)
{
- sc->data0 = clamp(sc->data0, 1e-4f, 1.0f);
- sc->data1 = clamp(sc->data1, 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);
- sc->type = CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID;
+ 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)
{
- sc->data0 = fmaxf(roughness, sc->data0); /* clamp roughness */
- sc->data1 = fmaxf(roughness, sc->data1);
+ MicrofacetBsdf *bsdf = (MicrofacetBsdf*)sc;
+
+ 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)
@@ -62,14 +64,15 @@ ccl_device_inline float bsdf_ashikhmin_shirley_roughness_to_exponent(float rough
ccl_device float3 bsdf_ashikhmin_shirley_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
- float3 N = sc->N;
+ 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(sc->data0, sc->data1) <= 1e-4f)
+ 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) {
@@ -82,8 +85,8 @@ ccl_device float3 bsdf_ashikhmin_shirley_eval_reflect(const ShaderClosure *sc, c
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(sc->data0);
- float n_y = bsdf_ashikhmin_shirley_roughness_to_exponent(sc->data1);
+ 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 */
@@ -97,12 +100,18 @@ ccl_device float3 bsdf_ashikhmin_shirley_eval_reflect(const ShaderClosure *sc, c
else {
/* anisotropic */
float3 X, Y;
- make_orthonormals_tangent(N, sc->T, &X, &Y);
+ make_orthonormals_tangent(N, bsdf->T, &X, &Y);
float HdotX = dot(H, X);
float HdotY = dot(H, Y);
- float e = (n_x * HdotX*HdotX + n_y * HdotY*HdotY) / (1.0f - HdotN*HdotN);
- float lobe = powf(HdotN, e);
+ 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;
@@ -128,13 +137,14 @@ ccl_device_inline void bsdf_ashikhmin_shirley_sample_first_quadrant(float n_x, f
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)
{
- float3 N = sc->N;
+ const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
+ float3 N = bsdf->N;
float NdotI = dot(N, I);
if(NdotI > 0.0f) {
- float n_x = bsdf_ashikhmin_shirley_roughness_to_exponent(sc->data0);
- float n_y = bsdf_ashikhmin_shirley_roughness_to_exponent(sc->data1);
+ 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;
@@ -142,7 +152,7 @@ ccl_device int bsdf_ashikhmin_shirley_sample(const ShaderClosure *sc, float3 Ng,
if(n_x == n_y)
make_orthonormals(N, &X, &Y);
else
- make_orthonormals_tangent(N, sc->T, &X, &Y);
+ make_orthonormals_tangent(N, bsdf->T, &X, &Y);
/* sample spherical coords for h in tangent space */
float phi;
@@ -193,7 +203,7 @@ ccl_device int bsdf_ashikhmin_shirley_sample(const ShaderClosure *sc, float3 Ng,
/* reflect I on H to get omega_in */
*omega_in = -I + (2.0f * HdotI) * H;
- if(fmaxf(sc->data0, sc->data1) <= 1e-4f) {
+ if(fmaxf(bsdf->alpha_x, bsdf->alpha_y) <= 1e-4f) {
/* Some high number for MIS. */
*pdf = 1e6f;
*eval = make_float3(1e6f, 1e6f, 1e6f);
diff --git a/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h b/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h
index f1a26650078..7e0f5a7ec75 100644
--- a/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h
+++ b/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h
@@ -35,20 +35,38 @@
CCL_NAMESPACE_BEGIN
-ccl_device int bsdf_ashikhmin_velvet_setup(ShaderClosure *sc)
+typedef ccl_addr_space struct VelvetBsdf {
+ SHADER_CLOSURE_BASE;
+
+ float sigma;
+ float invsigma2;
+ float3 N;
+} VelvetBsdf;
+
+ccl_device int bsdf_ashikhmin_velvet_setup(VelvetBsdf *bsdf)
{
- float sigma = fmaxf(sc->data0, 0.01f);
- sc->data0 = 1.0f/(sigma * sigma); /* m_invsigma2 */
+ float sigma = fmaxf(bsdf->sigma, 0.01f);
+ bsdf->invsigma2 = 1.0f/(sigma * sigma);
- sc->type = CLOSURE_BSDF_ASHIKHMIN_VELVET_ID;
+ bsdf->type = CLOSURE_BSDF_ASHIKHMIN_VELVET_ID;
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;
+
+ 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)
{
- float m_invsigma2 = sc->data0;
- float3 N = sc->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);
@@ -90,8 +108,9 @@ ccl_device float3 bsdf_ashikhmin_velvet_eval_transmit(const ShaderClosure *sc, c
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)
{
- float m_invsigma2 = sc->data0;
- float3 N = sc->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
diff --git a/intern/cycles/kernel/closure/bsdf_diffuse.h b/intern/cycles/kernel/closure/bsdf_diffuse.h
index 4b29bb096d1..dcd187f9305 100644
--- a/intern/cycles/kernel/closure/bsdf_diffuse.h
+++ b/intern/cycles/kernel/closure/bsdf_diffuse.h
@@ -35,17 +35,31 @@
CCL_NAMESPACE_BEGIN
+typedef ccl_addr_space struct DiffuseBsdf {
+ SHADER_CLOSURE_BASE;
+ float3 N;
+} DiffuseBsdf;
+
/* DIFFUSE */
-ccl_device int bsdf_diffuse_setup(ShaderClosure *sc)
+ccl_device int bsdf_diffuse_setup(DiffuseBsdf *bsdf)
{
- sc->type = CLOSURE_BSDF_DIFFUSE_ID;
+ 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;
+
+ 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)
{
- float3 N = sc->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;
@@ -59,7 +73,8 @@ ccl_device float3 bsdf_diffuse_eval_transmit(const ShaderClosure *sc, const floa
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)
{
- float3 N = sc->N;
+ const DiffuseBsdf *bsdf = (const DiffuseBsdf*)sc;
+ float3 N = bsdf->N;
// distribution over the hemisphere
sample_cos_hemisphere(N, randu, randv, omega_in, pdf);
@@ -80,9 +95,9 @@ ccl_device int bsdf_diffuse_sample(const ShaderClosure *sc, float3 Ng, float3 I,
/* TRANSLUCENT */
-ccl_device int bsdf_translucent_setup(ShaderClosure *sc)
+ccl_device int bsdf_translucent_setup(DiffuseBsdf *bsdf)
{
- sc->type = CLOSURE_BSDF_TRANSLUCENT_ID;
+ bsdf->type = CLOSURE_BSDF_TRANSLUCENT_ID;
return SD_BSDF|SD_BSDF_HAS_EVAL;
}
@@ -93,7 +108,8 @@ ccl_device float3 bsdf_translucent_eval_reflect(const ShaderClosure *sc, const f
ccl_device float3 bsdf_translucent_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
- float3 N = sc->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;
@@ -102,7 +118,8 @@ ccl_device float3 bsdf_translucent_eval_transmit(const ShaderClosure *sc, const
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)
{
- float3 N = sc->N;
+ 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
diff --git a/intern/cycles/kernel/closure/bsdf_diffuse_ramp.h b/intern/cycles/kernel/closure/bsdf_diffuse_ramp.h
index e0287e7655a..2d982a95fe4 100644
--- a/intern/cycles/kernel/closure/bsdf_diffuse_ramp.h
+++ b/intern/cycles/kernel/closure/bsdf_diffuse_ramp.h
@@ -35,7 +35,16 @@
CCL_NAMESPACE_BEGIN
-ccl_device float3 bsdf_diffuse_ramp_get_color(const ShaderClosure *sc, const float3 colors[8], float pos)
+#ifdef __OSL__
+
+typedef ccl_addr_space struct DiffuseRampBsdf {
+ SHADER_CLOSURE_BASE;
+
+ float3 N;
+ float3 *colors;
+} DiffuseRampBsdf;
+
+ccl_device float3 bsdf_diffuse_ramp_get_color(const float3 colors[8], float pos)
{
int MAXCOLORS = 8;
@@ -49,11 +58,9 @@ ccl_device float3 bsdf_diffuse_ramp_get_color(const ShaderClosure *sc, const flo
return colors[ipos] * (1.0f - offset) + colors[ipos+1] * offset;
}
-ccl_device int bsdf_diffuse_ramp_setup(ShaderClosure *sc)
+ccl_device int bsdf_diffuse_ramp_setup(DiffuseRampBsdf *bsdf)
{
- sc->type = CLOSURE_BSDF_DIFFUSE_RAMP_ID;
- sc->data0 = 0.0f;
- sc->data1 = 0.0f;
+ bsdf->type = CLOSURE_BSDF_DIFFUSE_RAMP_ID;
return SD_BSDF|SD_BSDF_HAS_EVAL;
}
@@ -61,29 +68,31 @@ ccl_device void bsdf_diffuse_ramp_blur(ShaderClosure *sc, float roughness)
{
}
-ccl_device float3 bsdf_diffuse_ramp_eval_reflect(const ShaderClosure *sc, const float3 colors[8], 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)
{
- float3 N = sc->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(sc, colors, 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 colors[8], 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);
}
-ccl_device int bsdf_diffuse_ramp_sample(const ShaderClosure *sc, const float3 colors[8], 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)
{
- float3 N = sc->N;
+ 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(sc, colors, *pdf * M_PI_F) * M_1_PI_F;
+ *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;
@@ -95,6 +104,8 @@ ccl_device int bsdf_diffuse_ramp_sample(const ShaderClosure *sc, const float3 co
return LABEL_REFLECT|LABEL_DIFFUSE;
}
+#endif /* __OSL__ */
+
CCL_NAMESPACE_END
#endif /* __BSDF_DIFFUSE_RAMP_H__ */
diff --git a/intern/cycles/kernel/closure/bsdf_disney_clearcoat.h b/intern/cycles/kernel/closure/bsdf_disney_clearcoat.h
index 377d21939b7..cdb8b3e0cff 100644
--- a/intern/cycles/kernel/closure/bsdf_disney_clearcoat.h
+++ b/intern/cycles/kernel/closure/bsdf_disney_clearcoat.h
@@ -35,22 +35,30 @@
CCL_NAMESPACE_BEGIN
+typedef ccl_addr_space struct DisneyClearcoatBsdf {
+ SHADER_CLOSURE_BASE;
-ccl_device int bsdf_disney_clearcoat_setup(ShaderClosure *sc)
+ float clearcoat, clearcoatGloss, clearcoatRoughness;
+ float3 N;
+} DisneyClearcoatBsdf;
+
+ccl_device int bsdf_disney_clearcoat_setup(DisneyClearcoatBsdf *bsdf)
{
/* clearcoat roughness */
- sc->custom1 = 0.1f * (1.0f - sc->data1/*clearcoatGloss*/) + 0.001f * sc->data1/*clearcoatGloss*/; // lerp(0.1f, 0.001f, sc->data1/*clearcoatGloss*/); //
+ bsdf->clearcoatRoughness = 0.1f * (1.0f - bsdf->clearcoatGloss) + 0.001f * bsdf->clearcoatGloss; // lerp(0.1f, 0.001f, sc->data1/*clearcoatGloss*/); //
- sc->type = CLOSURE_BSDF_DISNEY_CLEARCOAT_ID;
+ bsdf->type = CLOSURE_BSDF_DISNEY_CLEARCOAT_ID;
return SD_BSDF|SD_BSDF_HAS_EVAL;
}
ccl_device float3 bsdf_disney_clearcoat_eval_reflect(const ShaderClosure *sc, const float3 I,
const float3 omega_in, float *pdf)
{
- if (sc->data0 > 0.0f) {
- float alpha = sc->custom1;
- float3 N = sc->N;
+ const DisneyClearcoatBsdf *bsdf = (const DisneyClearcoatBsdf *)sc;
+
+ if (bsdf->clearcoat > 0.0f) {
+ float alpha = bsdf->clearcoatRoughness;
+ float3 N = bsdf->N;
if (alpha <= 1e-4f)
return make_float3(0.0f, 0.0f, 0.0f);
@@ -81,7 +89,7 @@ ccl_device float3 bsdf_disney_clearcoat_eval_reflect(const ShaderClosure *sc, co
float common = D * 0.25f / cosNO;
float FH = schlick_fresnel(dot(omega_in, m));
- float3 F = (0.04f * (1.0f - FH) + 1.0f * FH) * 0.25f * sc->data0/*clearcoat*/ * make_float3(1.0f, 1.0f, 1.0f); // lerp(make_float3(0.04f, 0.04f, 0.04f), make_float3(1.0f, 1.0f, 1.0f), FH);
+ float3 F = (0.04f * (1.0f - FH) + 1.0f * FH) * 0.25f * bsdf->clearcoat * make_float3(1.0f, 1.0f, 1.0f); // lerp(make_float3(0.04f, 0.04f, 0.04f), make_float3(1.0f, 1.0f, 1.0f), FH);
float3 out = F * G * common;
@@ -110,9 +118,11 @@ ccl_device int bsdf_disney_clearcoat_sample(const ShaderClosure *sc,
float3 *eval, float3 *omega_in, float3 *domega_in_dx,
float3 *domega_in_dy, float *pdf)
{
- if (sc->data0 > 0.0f) {
- float alpha = sc->custom1;
- float3 N = sc->N;
+ const DisneyClearcoatBsdf *bsdf = (const DisneyClearcoatBsdf *)sc;
+
+ if (bsdf->clearcoat > 0.0f) {
+ float alpha = bsdf->clearcoatRoughness;
+ float3 N = bsdf->N;
float cosNO = dot(N, I);
if (cosNO > 0) {
@@ -168,8 +178,8 @@ ccl_device int bsdf_disney_clearcoat_sample(const ShaderClosure *sc,
float FH = schlick_fresnel(dot(*omega_in, m));
float3 F = make_float3(0.04f, 0.04f, 0.04f) * (1.0f - FH) + make_float3(1.0f, 1.0f, 1.0f) * FH; // lerp(make_float3(0.04f, 0.04f, 0.04f), make_float3(1.0f, 1.0f, 1.0f), FH);
-
- *eval = G1i * common * F * 0.25f * sc->data0/*clearcoat*/;
+
+ *eval = G1i * common * F * 0.25f * bsdf->clearcoat;
}
#ifdef __RAY_DIFFERENTIALS__
diff --git a/intern/cycles/kernel/closure/bsdf_disney_diffuse.h b/intern/cycles/kernel/closure/bsdf_disney_diffuse.h
index ac5032f3377..faeb00197c7 100644
--- a/intern/cycles/kernel/closure/bsdf_disney_diffuse.h
+++ b/intern/cycles/kernel/closure/bsdf_disney_diffuse.h
@@ -36,8 +36,15 @@
CCL_NAMESPACE_BEGIN
+typedef ccl_addr_space struct DisneyDiffuseBsdf {
+ SHADER_CLOSURE_BASE;
-ccl_device float3 calculate_disney_diffuse_brdf(const ShaderClosure *sc,
+ float roughness;
+ float3 N;
+ float3 baseColor;
+} DisneyDiffuseBsdf;
+
+ccl_device float3 calculate_disney_diffuse_brdf(const DisneyDiffuseBsdf *bsdf,
float3 N, float3 V, float3 L, float3 H, float *pdf)
{
float NdotL = max(dot(N, L), 0.0f);
@@ -51,10 +58,10 @@ ccl_device float3 calculate_disney_diffuse_brdf(const ShaderClosure *sc,
float LdotH = dot(L, H);
float FL = schlick_fresnel(NdotL), FV = schlick_fresnel(NdotV);
- const float Fd90 = 0.5f + 2.0f * LdotH*LdotH * sc->data0/*roughness*/;
+ 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); //lerp(1.0f, Fd90, FL) * lerp(1.0f, Fd90, FV);
- float3 value = M_1_PI_F * Fd * sc->color0/*baseColor*/;
+ float3 value = M_1_PI_F * Fd * bsdf->baseColor;
*pdf = M_1_PI_F * 0.5f;
@@ -63,22 +70,24 @@ ccl_device float3 calculate_disney_diffuse_brdf(const ShaderClosure *sc,
return value;
}
-ccl_device int bsdf_disney_diffuse_setup(ShaderClosure *sc)
+ccl_device int bsdf_disney_diffuse_setup(DisneyDiffuseBsdf *bsdf)
{
- sc->type = CLOSURE_BSDF_DISNEY_DIFFUSE_ID;
+ bsdf->type = CLOSURE_BSDF_DISNEY_DIFFUSE_ID;
return SD_BSDF|SD_BSDF_HAS_EVAL;
}
ccl_device float3 bsdf_disney_diffuse_eval_reflect(const ShaderClosure *sc, const float3 I,
const float3 omega_in, float *pdf)
{
- float3 N = normalize(sc->N);
+ const DisneyDiffuseBsdf *bsdf = (const DisneyDiffuseBsdf *)sc;
+
+ float3 N = normalize(bsdf->N);
float3 V = I; // outgoing
float3 L = omega_in; // incoming
float3 H = normalize(L + V);
- if (dot(sc->N, omega_in) > 0.0f) {
- float3 value = calculate_disney_diffuse_brdf(sc, N, V, L, H, pdf);
+ if (dot(bsdf->N, omega_in) > 0.0f) {
+ float3 value = calculate_disney_diffuse_brdf(bsdf, N, V, L, H, pdf);
return value;
}
@@ -99,14 +108,16 @@ ccl_device int bsdf_disney_diffuse_sample(const ShaderClosure *sc,
float3 *eval, float3 *omega_in, float3 *domega_in_dx,
float3 *domega_in_dy, float *pdf)
{
- float3 N = normalize(sc->N);
+ const DisneyDiffuseBsdf *bsdf = (const DisneyDiffuseBsdf *)sc;
+
+ float3 N = normalize(bsdf->N);
sample_uniform_hemisphere(N, randu, randv, omega_in, pdf);
if (dot(Ng, *omega_in) > 0) {
float3 H = normalize(I + *omega_in);
- *eval = calculate_disney_diffuse_brdf(sc, N, I, *omega_in, H, pdf);
+ *eval = calculate_disney_diffuse_brdf(bsdf, N, I, *omega_in, H, pdf);
#ifdef __RAY_DIFFERENTIALS__
// TODO: find a better approximation for the diffuse bounce
diff --git a/intern/cycles/kernel/closure/bsdf_disney_sheen.h b/intern/cycles/kernel/closure/bsdf_disney_sheen.h
index 2806ecfc951..478ecaba324 100644
--- a/intern/cycles/kernel/closure/bsdf_disney_sheen.h
+++ b/intern/cycles/kernel/closure/bsdf_disney_sheen.h
@@ -36,14 +36,21 @@
CCL_NAMESPACE_BEGIN
+typedef ccl_addr_space struct DisneySheenBsdf {
+ SHADER_CLOSURE_BASE;
-ccl_device float3 calculate_disney_sheen_brdf(const ShaderClosure *sc,
+ float sheen, sheenTint;
+ float3 N;
+ float3 baseColor, csheen0;
+} DisneySheenBsdf;
+
+ccl_device float3 calculate_disney_sheen_brdf(const DisneySheenBsdf *bsdf,
float3 N, float3 V, float3 L, float3 H, float *pdf)
{
float NdotL = dot(N, L);
float NdotV = dot(N, V);
- if (NdotL < 0 || NdotV < 0 || sc->data0 == 0.0f) {
+ if (NdotL < 0 || NdotV < 0 || bsdf->sheen == 0.0f) {
*pdf = 0.0f;
return make_float3(0.0f, 0.0f, 0.0f);
}
@@ -54,36 +61,38 @@ ccl_device float3 calculate_disney_sheen_brdf(const ShaderClosure *sc,
float FH = schlick_fresnel(LdotH);
- float3 value = FH * sc->data0/*sheen*/ * sc->custom_color0/*csheen0*/;
+ float3 value = FH * bsdf->sheen * bsdf->csheen0;
value *= NdotL;
return value;
}
-ccl_device int bsdf_disney_sheen_setup(ShaderClosure *sc)
+ccl_device int bsdf_disney_sheen_setup(DisneySheenBsdf *bsdf)
{
- float m_cdlum = 0.3f * sc->color0.x + 0.6f * sc->color0.y + 0.1f * sc->color0.z; // luminance approx.
+ float m_cdlum = 0.3f * bsdf->baseColor.x + 0.6f * bsdf->baseColor.y + 0.1f * bsdf->baseColor.z; // luminance approx.
- float3 m_ctint = m_cdlum > 0.0f ? sc->color0 / m_cdlum : make_float3(1.0f, 1.0f, 1.0f); // normalize lum. to isolate hue+sat
+ float3 m_ctint = m_cdlum > 0.0f ? bsdf->baseColor / m_cdlum : make_float3(1.0f, 1.0f, 1.0f); // normalize lum. to isolate hue+sat
/* csheen0 */
- sc->custom_color0 = make_float3(1.0f, 1.0f, 1.0f) * (1.0f - sc->data1/*sheenTint*/) + m_ctint * sc->data1/*sheenTint*/; // lerp(make_float3(1.0f, 1.0f, 1.0f), m_ctint, sc->data1/*sheenTint*/);
+ bsdf->csheen0 = make_float3(1.0f, 1.0f, 1.0f) * (1.0f - bsdf->sheenTint) + m_ctint * bsdf->sheenTint; // lerp(make_float3(1.0f, 1.0f, 1.0f), m_ctint, sc->data1/*sheenTint*/);
- sc->type = CLOSURE_BSDF_DISNEY_SHEEN_ID;
+ bsdf->type = CLOSURE_BSDF_DISNEY_SHEEN_ID;
return SD_BSDF|SD_BSDF_HAS_EVAL;
}
ccl_device float3 bsdf_disney_sheen_eval_reflect(const ShaderClosure *sc, const float3 I,
const float3 omega_in, float *pdf)
{
- float3 N = normalize(sc->N);
+ const DisneySheenBsdf *bsdf = (const DisneySheenBsdf *)sc;
+
+ float3 N = normalize(bsdf->N);
float3 V = I; // outgoing
float3 L = omega_in; // incoming
float3 H = normalize(L + V);
- if (dot(sc->N, omega_in) > 0.0f) {
- float3 value = calculate_disney_sheen_brdf(sc, N, V, L, H, pdf);
+ if (dot(bsdf->N, omega_in) > 0.0f) {
+ float3 value = calculate_disney_sheen_brdf(bsdf, N, V, L, H, pdf);
return value;
}
@@ -104,14 +113,16 @@ ccl_device int bsdf_disney_sheen_sample(const ShaderClosure *sc,
float3 *eval, float3 *omega_in, float3 *domega_in_dx,
float3 *domega_in_dy, float *pdf)
{
- float3 N = normalize(sc->N);
+ const DisneySheenBsdf *bsdf = (const DisneySheenBsdf *)sc;
+
+ float3 N = normalize(bsdf->N);
sample_uniform_hemisphere(N, randu, randv, omega_in, pdf);
if (dot(Ng, *omega_in) > 0) {
float3 H = normalize(I + *omega_in);
- *eval = calculate_disney_sheen_brdf(sc, N, I, *omega_in, H, pdf);
+ *eval = calculate_disney_sheen_brdf(bsdf, N, I, *omega_in, H, pdf);
#ifdef __RAY_DIFFERENTIALS__
// TODO: find a better approximation for the diffuse bounce
diff --git a/intern/cycles/kernel/closure/bsdf_disney_specular.h b/intern/cycles/kernel/closure/bsdf_disney_specular.h
index cbcfc4106c5..7e8139fd040 100644
--- a/intern/cycles/kernel/closure/bsdf_disney_specular.h
+++ b/intern/cycles/kernel/closure/bsdf_disney_specular.h
@@ -35,40 +35,47 @@
CCL_NAMESPACE_BEGIN
+typedef ccl_addr_space struct DisneySpecularBsdf {
+ SHADER_CLOSURE_BASE;
-ccl_device int bsdf_disney_specular_setup(ShaderClosure *sc)
+ float specular, specularTint, roughness, metallic, anisotropic, alpha_x, alpha_y, rough_g;
+ float3 N, T;
+ float3 baseColor, cspec0;
+} DisneySpecularBsdf;
+
+ccl_device int bsdf_disney_specular_setup(DisneySpecularBsdf *bsdf)
{
- float m_cdlum = 0.3f * sc->color0.x + 0.6f * sc->color0.y + 0.1f * sc->color0.z; // luminance approx.
+ float m_cdlum = 0.3f * bsdf->baseColor.x + 0.6f * bsdf->baseColor.y + 0.1f * bsdf->baseColor.z; // luminance approx.
- float3 m_ctint = m_cdlum > 0.0f ? sc->color0/*baseColor*/ / m_cdlum : make_float3(1.0f, 1.0f, 1.0f); // normalize lum. to isolate hue+sat
+ float3 m_ctint = m_cdlum > 0.0f ? bsdf->baseColor / m_cdlum : make_float3(1.0f, 1.0f, 1.0f); // normalize lum. to isolate hue+sat
- float3 tmp_col = make_float3(1.0f, 1.0f, 1.0f) * (1.0f - sc->data2/*specularTint*/) + m_ctint * sc->data2/*specularTint*/; // lerp(make_float3(1.0f, 1.0f, 1.0f), m_ctint, sc->data2/*specularTint*/);
- sc->custom_color0/*cspec0*/ = (sc->data1/*specular*/ * 0.08f * tmp_col) * (1.0f - sc->data0/*metallic*/) + sc->color0/*baseColor*/ * sc->data0/*metallic*/; // lerp(sc->data1/*specular*/ * 0.08f * tmp_col, sc->color0/*baseColor*/, sc->data0/*metallic*/);
+ float3 tmp_col = make_float3(1.0f, 1.0f, 1.0f) * (1.0f - bsdf->specularTint) + m_ctint * bsdf->specularTint; // lerp(make_float3(1.0f, 1.0f, 1.0f), m_ctint, sc->data2/*specularTint*/);
+ bsdf->cspec0 = (bsdf->specular * 0.08f * tmp_col) * (1.0f - bsdf->metallic) + bsdf->baseColor * bsdf->metallic; // lerp(sc->data1/*specular*/ * 0.08f * tmp_col, sc->color0/*baseColor*/, sc->data0/*metallic*/);
- float aspect = safe_sqrtf(1.0f - sc->data4/*anisotropic*/ * 0.9f);
- float r2 = sqr(sc->data3/*roughness*/);
+ float aspect = safe_sqrtf(1.0f - bsdf->anisotropic * 0.9f);
+ float r2 = sqr(bsdf->roughness);
/* ax */
- sc->custom1 = fmaxf(0.001f, r2 / aspect);
+ bsdf->alpha_x = fmaxf(0.001f, r2 / aspect);
/* ay */
- sc->custom2 = fmaxf(0.001f, r2 * aspect);
+ bsdf->alpha_y = fmaxf(0.001f, r2 * aspect);
/* rough_g */
- sc->custom3 = sqr(sc->data3/*roughness*/ * 0.5f + 0.5f);
+ bsdf->rough_g = sqr(bsdf->roughness * 0.5f + 0.5f);
- sc->type = CLOSURE_BSDF_DISNEY_SPECULAR_ID;
+ bsdf->type = CLOSURE_BSDF_DISNEY_SPECULAR_ID;
return SD_BSDF|SD_BSDF_HAS_EVAL;
}
ccl_device float3 bsdf_disney_specular_eval_reflect(const ShaderClosure *sc, const float3 I,
const float3 omega_in, float *pdf)
{
- float alpha_x = sc->custom1;
- float alpha_y = sc->custom2;
- float3 N = sc->N;
+ const DisneySpecularBsdf *bsdf = (const DisneySpecularBsdf *)sc;
+
+ float3 N = bsdf->N;
- if (fmaxf(alpha_x, alpha_y) <= 1e-4f)
+ if (fmaxf(bsdf->alpha_x, bsdf->alpha_y) <= 1e-4f)
return make_float3(0.0f, 0.0f, 0.0f);
float cosNO = dot(N, I);
@@ -77,10 +84,10 @@ ccl_device float3 bsdf_disney_specular_eval_reflect(const ShaderClosure *sc, con
if (cosNI > 0 && cosNO > 0) {
/* get half vector */
float3 m = normalize(omega_in + I);
- float alpha2 = alpha_x * alpha_y;
+ float alpha2 = bsdf->alpha_x * bsdf->alpha_y;
float D, G1o, G1i;
- if (alpha_x == alpha_y) {
+ if (bsdf->alpha_x == bsdf->alpha_y) {
/* isotropic
* eq. 20: (F*G*D)/(4*in*on)
* eq. 33: first we calculate D(m) */
@@ -97,12 +104,12 @@ ccl_device float3 bsdf_disney_specular_eval_reflect(const ShaderClosure *sc, con
else {
/* anisotropic */
float3 X, Y, Z = N;
- make_orthonormals_tangent(Z, sc->T, &X, &Y);
+ 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_x = -local_m.x/(local_m.z*bsdf->alpha_x);
+ float slope_y = -local_m.y/(local_m.z*bsdf->alpha_y);
float slope_len = 1 + slope_x*slope_x + slope_y*slope_y;
float cosThetaM = local_m.z;
@@ -116,7 +123,7 @@ ccl_device float3 bsdf_disney_specular_eval_reflect(const ShaderClosure *sc, con
float cosPhiO = dot(I, X);
float sinPhiO = dot(I, Y);
- float alphaO2 = (cosPhiO*cosPhiO)*(alpha_x*alpha_x) + (sinPhiO*sinPhiO)*(alpha_y*alpha_y);
+ float alphaO2 = (cosPhiO*cosPhiO)*(bsdf->alpha_x*bsdf->alpha_x) + (sinPhiO*sinPhiO)*(bsdf->alpha_y*bsdf->alpha_y);
alphaO2 /= cosPhiO*cosPhiO + sinPhiO*sinPhiO;
G1o = 2 / (1 + safe_sqrtf(1 + alphaO2 * tanThetaO2));
@@ -125,7 +132,7 @@ ccl_device float3 bsdf_disney_specular_eval_reflect(const ShaderClosure *sc, con
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);
+ float alphaI2 = (cosPhiI*cosPhiI)*(bsdf->alpha_x*bsdf->alpha_x) + (sinPhiI*sinPhiI)*(bsdf->alpha_y*bsdf->alpha_y);
alphaI2 /= cosPhiI*cosPhiI + sinPhiI*sinPhiI;
G1i = 2 / (1 + safe_sqrtf(1 + alphaI2 * tanThetaI2));
@@ -137,7 +144,7 @@ ccl_device float3 bsdf_disney_specular_eval_reflect(const ShaderClosure *sc, con
float common = D * 0.25f / cosNO;
float FH = schlick_fresnel(dot(omega_in, m));
- float3 F = sc->custom_color0 * (1.0f - FH) + make_float3(1.0f, 1.0f, 1.0f) * FH; // lerp(sc->custom_color0, make_float3(1.0f, 1.0f, 1.0f), FH);
+ float3 F = bsdf->cspec0 * (1.0f - FH) + make_float3(1.0f, 1.0f, 1.0f) * FH; // lerp(sc->custom_color0, make_float3(1.0f, 1.0f, 1.0f), FH);
float3 out = F * G * common;
@@ -166,18 +173,18 @@ ccl_device int bsdf_disney_specular_sample(const ShaderClosure *sc,
float3 *eval, float3 *omega_in, float3 *domega_in_dx,
float3 *domega_in_dy, float *pdf)
{
- float alpha_x = sc->custom1;
- float alpha_y = sc->custom2;
- float3 N = sc->N;
+ const DisneySpecularBsdf *bsdf = (const DisneySpecularBsdf *)sc;
+
+ float3 N = bsdf->N;
float cosNO = dot(N, I);
if(cosNO > 0) {
float3 X, Y, Z = N;
- if(alpha_x == alpha_y)
+ if (bsdf->alpha_x == bsdf->alpha_y)
make_orthonormals(Z, &X, &Y);
else
- make_orthonormals_tangent(Z, sc->T, &X, &Y);
+ make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
/* importance sampling with distribution of visible normals. vectors are
* transformed to local space before and after */
@@ -186,7 +193,7 @@ ccl_device int bsdf_disney_specular_sample(const ShaderClosure *sc,
float3 m;
float G1o;
- local_m = importance_sample_microfacet_stretched(local_I, alpha_x, alpha_y,
+ local_m = importance_sample_microfacet_stretched(local_I, bsdf->alpha_x, bsdf->alpha_y,
randu, randv, false, &G1o);
m = X*local_m.x + Y*local_m.y + Z*local_m.z;
@@ -200,7 +207,7 @@ ccl_device int bsdf_disney_specular_sample(const ShaderClosure *sc,
*omega_in = 2 * cosMO * m - I;
if(dot(Ng, *omega_in) > 0) {
- if(fmaxf(alpha_x, alpha_y) <= 1e-4f) {
+ if (fmaxf(bsdf->alpha_x, bsdf->alpha_y) <= 1e-4f) {
/* some high number for MIS */
*pdf = 1e6f;
*eval = make_float3(1e6f, 1e6f, 1e6f);
@@ -208,10 +215,10 @@ ccl_device int bsdf_disney_specular_sample(const ShaderClosure *sc,
else {
/* microfacet normal is visible to this ray */
/* eq. 33 */
- float alpha2 = alpha_x * alpha_y;
+ float alpha2 = bsdf->alpha_x * bsdf->alpha_y;
float D, G1i;
- if(alpha_x == alpha_y) {
+ if (bsdf->alpha_x == bsdf->alpha_y) {
float cosThetaM2 = cosThetaM * cosThetaM;
float cosThetaM4 = cosThetaM2 * cosThetaM2;
float tanThetaM2 = 1/(cosThetaM2) - 1;
@@ -225,8 +232,8 @@ ccl_device int bsdf_disney_specular_sample(const ShaderClosure *sc,
}
else {
/* anisotropic distribution */
- float slope_x = -local_m.x/(local_m.z*alpha_x);
- float slope_y = -local_m.y/(local_m.z*alpha_y);
+ float slope_x = -local_m.x / (local_m.z*bsdf->alpha_x);
+ float slope_y = -local_m.y / (local_m.z*bsdf->alpha_y);
float slope_len = 1 + slope_x*slope_x + slope_y*slope_y;
float cosThetaM = local_m.z;
@@ -242,7 +249,7 @@ ccl_device int bsdf_disney_specular_sample(const ShaderClosure *sc,
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);
+ float alphaI2 = (cosPhiI*cosPhiI)*(bsdf->alpha_x*bsdf->alpha_x) + (sinPhiI*sinPhiI)*(bsdf->alpha_y*bsdf->alpha_y);
alphaI2 /= cosPhiI*cosPhiI + sinPhiI*sinPhiI;
G1i = 2 / (1 + safe_sqrtf(1 + alphaI2 * tanThetaI2));
@@ -253,7 +260,7 @@ ccl_device int bsdf_disney_specular_sample(const ShaderClosure *sc,
*pdf = common;
float FH = schlick_fresnel(dot(*omega_in, m));
- float3 F = sc->custom_color0 * (1.0f - FH) + make_float3(1.0f, 1.0f, 1.0f) * FH; // lerp(sc->custom_color0, make_float3(1.0f, 1.0f, 1.0f), FH);
+ float3 F = bsdf->cspec0 * (1.0f - FH) + make_float3(1.0f, 1.0f, 1.0f) * FH; // lerp(sc->custom_color0, make_float3(1.0f, 1.0f, 1.0f), FH);
*eval = G1i * common * F;
}
diff --git a/intern/cycles/kernel/closure/bsdf_hair.h b/intern/cycles/kernel/closure/bsdf_hair.h
index 1e81617a7d3..bede5f45e7e 100644
--- a/intern/cycles/kernel/closure/bsdf_hair.h
+++ b/intern/cycles/kernel/closure/bsdf_hair.h
@@ -35,29 +35,49 @@
CCL_NAMESPACE_BEGIN
+typedef ccl_addr_space struct HairBsdf {
+ SHADER_CLOSURE_BASE;
-ccl_device int bsdf_hair_reflection_setup(ShaderClosure *sc)
+ float3 T;
+ float roughness1;
+ float roughness2;
+ float offset;
+} HairBsdf;
+
+ccl_device int bsdf_hair_reflection_setup(HairBsdf *bsdf)
{
- sc->type = CLOSURE_BSDF_HAIR_REFLECTION_ID;
- sc->data0 = clamp(sc->data0, 0.001f, 1.0f);
- sc->data1 = clamp(sc->data1, 0.001f, 1.0f);
+ 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(ShaderClosure *sc)
+ccl_device int bsdf_hair_transmission_setup(HairBsdf *bsdf)
{
- sc->type = CLOSURE_BSDF_HAIR_TRANSMISSION_ID;
- sc->data0 = clamp(sc->data0, 0.001f, 1.0f);
- sc->data1 = clamp(sc->data1, 0.001f, 1.0f);
+ 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;
+
+ 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)
{
- float offset = sc->data2;
- float3 Tg = sc->T;
- float roughness1 = sc->data0;
- float roughness2 = sc->data1;
+ 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);
@@ -107,10 +127,11 @@ ccl_device float3 bsdf_hair_reflection_eval_transmit(const ShaderClosure *sc, co
ccl_device float3 bsdf_hair_transmission_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
- float offset = sc->data2;
- float3 Tg = sc->T;
- float roughness1 = sc->data0;
- float roughness2 = sc->data1;
+ 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);
@@ -148,10 +169,11 @@ ccl_device float3 bsdf_hair_transmission_eval_transmit(const ShaderClosure *sc,
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)
{
- float offset = sc->data2;
- float3 Tg = sc->T;
- float roughness1 = sc->data0;
- float roughness2 = sc->data1;
+ 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);
@@ -198,10 +220,11 @@ ccl_device int bsdf_hair_reflection_sample(const ShaderClosure *sc, float3 Ng, f
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)
{
- float offset = sc->data2;
- float3 Tg = sc->T;
- float roughness1 = sc->data0;
- float roughness2 = sc->data1;
+ 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);
diff --git a/intern/cycles/kernel/closure/bsdf_microfacet.h b/intern/cycles/kernel/closure/bsdf_microfacet.h
index 2a0e8f62e7c..7173ecd64de 100644
--- a/intern/cycles/kernel/closure/bsdf_microfacet.h
+++ b/intern/cycles/kernel/closure/bsdf_microfacet.h
@@ -35,6 +35,20 @@
CCL_NAMESPACE_BEGIN
+typedef ccl_addr_space struct MicrofacetExtra {
+ float3 color, cspec0;
+ bool use_fresnel;
+} MicrofacetExtra;
+
+typedef ccl_addr_space struct MicrofacetBsdf {
+ SHADER_CLOSURE_BASE;
+
+ float alpha_x, alpha_y, ior;
+ MicrofacetExtra *extra;
+ float3 T;
+ float3 N;
+} MicrofacetBsdf;
+
/* Beckmann and GGX microfacet importance sampling. */
ccl_device_inline void microfacet_beckmann_sample_slopes(
@@ -233,50 +247,92 @@ ccl_device_inline float3 microfacet_sample_stretched(
* Anisotropy is only supported for reflection currently, but adding it for
* transmission is just a matter of copying code from reflection if needed. */
-ccl_device int bsdf_microfacet_ggx_setup(ShaderClosure *sc)
+ccl_device int bsdf_microfacet_ggx_setup(MicrofacetBsdf *bsdf, bool use_fresnel = false)
{
- sc->data0 = saturate(sc->data0); /* alpha_x */
- sc->data1 = sc->data0; /* alpha_y */
+ if (bsdf->extra) {
+ bsdf->extra->use_fresnel = use_fresnel;
+
+ 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 = saturate(bsdf->alpha_x);
+ bsdf->alpha_y = bsdf->alpha_x;
- sc->type = CLOSURE_BSDF_MICROFACET_GGX_ID;
+ bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_ID;
return SD_BSDF|SD_BSDF_HAS_EVAL;
}
-ccl_device int bsdf_microfacet_ggx_aniso_setup(ShaderClosure *sc)
+ccl_device bool bsdf_microfacet_merge(const ShaderClosure *a, const ShaderClosure *b)
{
- sc->data0 = saturate(sc->data0); /* alpha_x */
- sc->data1 = saturate(sc->data1); /* alpha_y */
+ 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 && !bsdf_b->extra) ||
+ ((bsdf_a->extra && bsdf_b->extra) &&
+ (isequal_float3(bsdf_a->extra->color, bsdf_b->extra->color))));
+}
+
+ccl_device int bsdf_microfacet_ggx_aniso_setup(MicrofacetBsdf *bsdf, bool use_fresnel = false)
+{
+ if (bsdf->extra) {
+ bsdf->extra->use_fresnel = use_fresnel;
+
+ 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 = saturate(bsdf->alpha_x);
+ bsdf->alpha_y = saturate(bsdf->alpha_y);
- sc->type = CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID;
+ bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID;
return SD_BSDF|SD_BSDF_HAS_EVAL;
}
-ccl_device int bsdf_microfacet_ggx_refraction_setup(ShaderClosure *sc)
+ccl_device int bsdf_microfacet_ggx_refraction_setup(MicrofacetBsdf *bsdf, bool use_fresnel = false)
{
- sc->data0 = saturate(sc->data0); /* alpha_x */
- sc->data1 = sc->data0; /* alpha_y */
+ if (bsdf->extra) {
+ bsdf->extra->use_fresnel = use_fresnel;
+
+ 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 = saturate(bsdf->alpha_x);
+ bsdf->alpha_y = bsdf->alpha_x;
- sc->type = CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
+ bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
return SD_BSDF|SD_BSDF_HAS_EVAL;
}
ccl_device void bsdf_microfacet_ggx_blur(ShaderClosure *sc, float roughness)
{
- sc->data0 = fmaxf(roughness, sc->data0); /* alpha_x */
- sc->data1 = fmaxf(roughness, sc->data1); /* alpha_y */
+ MicrofacetBsdf *bsdf = (MicrofacetBsdf*)sc;
+
+ 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)
{
- float alpha_x = sc->data0;
- float alpha_y = sc->data1;
- bool m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
- float3 N = sc->N;
+ 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 || fmaxf(alpha_x, alpha_y) <= 1e-4f)
+ if(m_refractive || alpha_x*alpha_y <= 1e-7f)
return make_float3(0.0f, 0.0f, 0.0f);
float cosNO = dot(N, I);
@@ -305,7 +361,7 @@ ccl_device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderClosure *sc, cons
else {
/* anisotropic */
float3 X, Y, Z = N;
- make_orthonormals_tangent(Z, sc->T, &X, &Y);
+ make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
/* distribution */
float3 local_m = make_float3(dot(X, m), dot(Y, m), dot(Z, m));
@@ -343,7 +399,17 @@ ccl_device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderClosure *sc, cons
/* eq. 20 */
float common = D * 0.25f / cosNO;
- float out = G * common;
+
+ float3 F = make_float3(1.0f, 1.0f, 1.0f);
+ if (bsdf->extra) {
+ if (bsdf->extra->use_fresnel) {
+ float FH = schlick_fresnel(dot(omega_in, m));
+
+ F = bsdf->extra->cspec0 * (1.0f - FH) + make_float3(1.0f, 1.0f, 1.0f) * FH; // lerp(sc->custom_color0, make_float3(1.0f, 1.0f, 1.0f), FH);
+ }
+ }
+
+ float3 out = F * G * common;
/* eq. 2 in distribution of visible normals sampling
* pm = Dw = G1o * dot(m, I) * D / dot(N, I); */
@@ -353,7 +419,7 @@ ccl_device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderClosure *sc, cons
* pdf = pm * 0.25 / dot(m, I); */
*pdf = G1o * common;
- return make_float3(out, out, out);
+ return out;
}
return make_float3(0.0f, 0.0f, 0.0f);
@@ -361,13 +427,14 @@ ccl_device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderClosure *sc, cons
ccl_device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
- float alpha_x = sc->data0;
- float alpha_y = sc->data1;
- float m_eta = sc->data2;
- bool m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
- float3 N = sc->N;
-
- if(!m_refractive || fmaxf(alpha_x, alpha_y) <= 1e-4f)
+ 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);
float cosNO = dot(N, I);
@@ -407,18 +474,29 @@ ccl_device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderClosure *sc, con
/* 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;
+
+ float3 F = make_float3(1.0f, 1.0f, 1.0f);
+ if (bsdf->extra) {
+ if (bsdf->extra->use_fresnel) {
+ float FH = schlick_fresnel(dot(omega_in, Ht));
+
+ F = bsdf->extra->cspec0 * (1.0f - FH) + make_float3(1.0f, 1.0f, 1.0f) * FH; // lerp(sc->custom_color0, make_float3(1.0f, 1.0f, 1.0f), FH);
+ }
+ }
+
+ float3 out = G * fabsf(cosHI * cosHO) * common * F;
*pdf = G1o * fabsf(cosHO * cosHI) * common;
- return make_float3(out, out, out);
+ return 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)
{
- float alpha_x = sc->data0;
- float alpha_y = sc->data1;
- bool m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
- float3 N = sc->N;
+ 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;
float cosNO = dot(N, I);
if(cosNO > 0) {
@@ -427,7 +505,7 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals *kg, const ShaderClosure
if(alpha_x == alpha_y)
make_orthonormals(Z, &X, &Y);
else
- make_orthonormals_tangent(Z, sc->T, &X, &Y);
+ make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
/* importance sampling with distribution of visible normals. vectors are
* transformed to local space before and after */
@@ -450,7 +528,7 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals *kg, const ShaderClosure
*omega_in = 2 * cosMO * m - I;
if(dot(Ng, *omega_in) > 0) {
- if(fmaxf(alpha_x, alpha_y) <= 1e-4f) {
+ if(alpha_x*alpha_y <= 1e-7f) {
/* some high number for MIS */
*pdf = 1e6f;
*eval = make_float3(1e6f, 1e6f, 1e6f);
@@ -502,10 +580,18 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals *kg, const ShaderClosure
/* see eval function for derivation */
float common = (G1o * D) * 0.25f / cosNO;
- float out = G1i * common;
*pdf = common;
- *eval = make_float3(out, out, out);
+ float3 F = make_float3(1.0f, 1.0f, 1.0f);
+ if (bsdf->extra) {
+ if (bsdf->extra->use_fresnel) {
+ float FH = schlick_fresnel(dot(*omega_in, m));
+
+ F = bsdf->extra->cspec0 * (1.0f - FH) + make_float3(1.0f, 1.0f, 1.0f) * FH; // lerp(sc->custom_color0, make_float3(1.0f, 1.0f, 1.0f), FH);
+ }
+ }
+
+ *eval = G1i * common * F;
}
#ifdef __RAY_DIFFERENTIALS__
@@ -522,7 +608,7 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals *kg, const ShaderClosure
#ifdef __RAY_DIFFERENTIALS__
float3 dRdx, dRdy, dTdx, dTdy;
#endif
- float m_eta = sc->data2, fresnel;
+ float m_eta = bsdf->ior, fresnel;
bool inside;
fresnel = fresnel_dielectric(m_eta, m, I, &R, &T,
@@ -539,7 +625,7 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals *kg, const ShaderClosure
*domega_in_dy = dTdy;
#endif
- if(fmaxf(alpha_x, alpha_y) <= 1e-4f || fabsf(m_eta - 1.0f) < 1e-4f) {
+ 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);
@@ -566,10 +652,20 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals *kg, const ShaderClosure
/* see eval function for derivation */
float common = (G1o * D) * (m_eta * m_eta) / (cosNO * Ht2);
- float out = G1i * fabsf(cosHI * cosHO) * common;
+
+ float3 F = make_float3(1.0f, 1.0f, 1.0f);
+ if (bsdf->extra) {
+ if (bsdf->extra->use_fresnel) {
+ float FH = schlick_fresnel(dot(*omega_in, m));
+
+ F = bsdf->extra->cspec0 * (1.0f - FH) + make_float3(1.0f, 1.0f, 1.0f) * FH; // lerp(sc->custom_color0, make_float3(1.0f, 1.0f, 1.0f), FH);
+ }
+ }
+
+ float3 out = G1i * fabsf(cosHI * cosHO) * common * F;
*pdf = cosHO * fabsf(cosHI) * common;
- *eval = make_float3(out, out, out);
+ *eval = out;
}
}
}
@@ -582,47 +678,80 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals *kg, const ShaderClosure
* Microfacet Models for Refraction through Rough Surfaces
* B. Walter, S. R. Marschner, H. Li, K. E. Torrance, EGSR 2007 */
-ccl_device int bsdf_microfacet_beckmann_setup(ShaderClosure *sc)
+ccl_device int bsdf_microfacet_beckmann_setup(MicrofacetBsdf *bsdf)
{
- sc->data0 = saturate(sc->data0); /* alpha_x */
- sc->data1 = sc->data0; /* alpha_y */
+ bsdf->alpha_x = saturate(bsdf->alpha_x);
+ bsdf->alpha_y = bsdf->alpha_x;
- sc->type = CLOSURE_BSDF_MICROFACET_BECKMANN_ID;
+ bsdf->type = CLOSURE_BSDF_MICROFACET_BECKMANN_ID;
return SD_BSDF|SD_BSDF_HAS_EVAL;
}
-ccl_device int bsdf_microfacet_beckmann_aniso_setup(ShaderClosure *sc)
+ccl_device int bsdf_microfacet_beckmann_aniso_setup(MicrofacetBsdf *bsdf)
{
- sc->data0 = saturate(sc->data0); /* alpha_x */
- sc->data1 = saturate(sc->data1); /* alpha_y */
+ bsdf->alpha_x = saturate(bsdf->alpha_x);
+ bsdf->alpha_y = saturate(bsdf->alpha_y);
- sc->type = CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID;
+ bsdf->type = CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID;
return SD_BSDF|SD_BSDF_HAS_EVAL;
}
-ccl_device int bsdf_microfacet_beckmann_refraction_setup(ShaderClosure *sc)
+ccl_device int bsdf_microfacet_beckmann_refraction_setup(MicrofacetBsdf *bsdf)
{
- sc->data0 = saturate(sc->data0); /* alpha_x */
- sc->data1 = sc->data0; /* alpha_y */
+ bsdf->alpha_x = saturate(bsdf->alpha_x);
+ bsdf->alpha_y = bsdf->alpha_x;
- sc->type = CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
+ 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)
{
- sc->data0 = fmaxf(roughness, sc->data0); /* alpha_x */
- sc->data1 = fmaxf(roughness, sc->data1); /* alpha_y */
+ MicrofacetBsdf *bsdf = (MicrofacetBsdf*)sc;
+
+ 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);
+}
+
+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);
}
ccl_device float3 bsdf_microfacet_beckmann_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
- float alpha_x = sc->data0;
- float alpha_y = sc->data1;
- bool m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
- float3 N = sc->N;
+ 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 || fmaxf(alpha_x, alpha_y) <= 1e-4f)
+ if(m_refractive || alpha_x*alpha_y <= 1e-7f)
return make_float3(0.0f, 0.0f, 0.0f);
float cosNO = dot(N, I);
@@ -646,15 +775,13 @@ ccl_device float3 bsdf_microfacet_beckmann_eval_reflect(const ShaderClosure *sc,
D = expf(-tanThetaM2 / alpha2) / (M_PI_F * alpha2 * cosThetaM4);
/* eq. 26, 27: now calculate G1(i,m) and G1(o,m) */
- float ao = 1 / (alpha_x * safe_sqrtf((1 - cosNO * cosNO) / (cosNO * cosNO)));
- float ai = 1 / (alpha_x * safe_sqrtf((1 - cosNI * cosNI) / (cosNI * cosNI)));
- G1o = ao < 1.6f ? (3.535f * ao + 2.181f * ao * ao) / (1 + 2.276f * ao + 2.577f * ao * ao) : 1.0f;
- G1i = ai < 1.6f ? (3.535f * ai + 2.181f * ai * ai) / (1 + 2.276f * ai + 2.577f * ai * ai) : 1.0f;
+ 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, sc->T, &X, &Y);
+ make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
/* distribution */
float3 local_m = make_float3(dot(X, m), dot(Y, m), dot(Z, m));
@@ -668,24 +795,8 @@ ccl_device float3 bsdf_microfacet_beckmann_eval_reflect(const ShaderClosure *sc,
D = expf(-slope_x*slope_x - slope_y*slope_y) / (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;
-
- 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;
-
- float ao = 1 / (safe_sqrtf(alphaO2 * tanThetaO2));
- float ai = 1 / (safe_sqrtf(alphaI2 * tanThetaI2));
- G1o = ao < 1.6f ? (3.535f * ao + 2.181f * ao * ao) / (1 + 2.276f * ao + 2.577f * ao * ao) : 1.0f;
- G1i = ai < 1.6f ? (3.535f * ai + 2.181f * ai * ai) / (1 + 2.276f * ai + 2.577f * ai * ai) : 1.0f;
+ 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;
@@ -710,13 +821,14 @@ ccl_device float3 bsdf_microfacet_beckmann_eval_reflect(const ShaderClosure *sc,
ccl_device float3 bsdf_microfacet_beckmann_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
- float alpha_x = sc->data0;
- float alpha_y = sc->data1;
- float m_eta = sc->data2;
- bool m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
- float3 N = sc->N;
-
- if(!m_refractive || fmaxf(alpha_x, alpha_y) <= 1e-4f)
+ 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);
@@ -740,10 +852,8 @@ ccl_device float3 bsdf_microfacet_beckmann_eval_transmit(const ShaderClosure *sc
float D = expf(-tanThetaM2 / alpha2) / (M_PI_F * alpha2 * cosThetaM4);
/* eq. 26, 27: now calculate G1(i,m) and G1(o,m) */
- float ao = 1 / (alpha_x * safe_sqrtf((1 - cosNO * cosNO) / (cosNO * cosNO)));
- float ai = 1 / (alpha_x * safe_sqrtf((1 - cosNI * cosNI) / (cosNI * cosNI)));
- float G1o = ao < 1.6f ? (3.535f * ao + 2.181f * ao * ao) / (1 + 2.276f * ao + 2.577f * ao * ao) : 1.0f;
- float G1i = ai < 1.6f ? (3.535f * ai + 2.181f * ai * ai) / (1 + 2.276f * ai + 2.577f * ai * ai) : 1.0f;
+ float G1o = bsdf_beckmann_G1(alpha_x, cosNO);
+ float G1i = bsdf_beckmann_G1(alpha_x, cosNI);
float G = G1o * G1i;
/* probability */
@@ -763,10 +873,11 @@ ccl_device float3 bsdf_microfacet_beckmann_eval_transmit(const ShaderClosure *sc
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)
{
- float alpha_x = sc->data0;
- float alpha_y = sc->data1;
- bool m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
- float3 N = sc->N;
+ 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;
float cosNO = dot(N, I);
if(cosNO > 0) {
@@ -775,7 +886,7 @@ ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals *kg, const ShaderCl
if(alpha_x == alpha_y)
make_orthonormals(Z, &X, &Y);
else
- make_orthonormals_tangent(Z, sc->T, &X, &Y);
+ make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
/* importance sampling with distribution of visible normals. vectors are
* transformed to local space before and after */
@@ -798,7 +909,7 @@ ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals *kg, const ShaderCl
*omega_in = 2 * cosMO * m - I;
if(dot(Ng, *omega_in) > 0) {
- if(fmaxf(alpha_x, alpha_y) <= 1e-4f) {
+ if(alpha_x*alpha_y <= 1e-7f) {
/* some high number for MIS */
*pdf = 1e6f;
*eval = make_float3(1e6f, 1e6f, 1e6f);
@@ -820,8 +931,7 @@ ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals *kg, const ShaderCl
float cosNI = dot(N, *omega_in);
/* eq. 26, 27: now calculate G1(i,m) */
- float ai = 1 / (alpha_x * safe_sqrtf((1 - cosNI * cosNI) / (cosNI * cosNI)));
- G1i = ai < 1.6f ? (3.535f * ai + 2.181f * ai * ai) / (1 + 2.276f * ai + 2.577f * ai * ai) : 1.0f;
+ G1i = bsdf_beckmann_G1(alpha_x, cosNI);
}
else {
/* anisotropic distribution */
@@ -836,16 +946,7 @@ ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals *kg, const ShaderCl
D = expf(-slope_x*slope_x - slope_y*slope_y) / (M_PI_F * alpha2 * cosThetaM4);
/* 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;
-
- float ai = 1 / (safe_sqrtf(alphaI2 * tanThetaI2));
- G1i = ai < 1.6f ? (3.535f * ai + 2.181f * ai * ai) / (1 + 2.276f * ai + 2.577f * ai * ai) : 1.0f;
+ 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;
@@ -872,7 +973,7 @@ ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals *kg, const ShaderCl
#ifdef __RAY_DIFFERENTIALS__
float3 dRdx, dRdy, dTdx, dTdy;
#endif
- float m_eta = sc->data2, fresnel;
+ float m_eta = bsdf->ior, fresnel;
bool inside;
fresnel = fresnel_dielectric(m_eta, m, I, &R, &T,
@@ -889,7 +990,7 @@ ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals *kg, const ShaderCl
*domega_in_dy = dTdy;
#endif
- if(fmaxf(alpha_x, alpha_y) <= 1e-4f || fabsf(m_eta - 1.0f) < 1e-4f) {
+ 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);
@@ -906,8 +1007,7 @@ ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals *kg, const ShaderCl
float cosNI = dot(N, *omega_in);
/* eq. 26, 27: now calculate G1(i,m) */
- float ai = 1 / (alpha_x * safe_sqrtf((1 - cosNI * cosNI) / (cosNI * cosNI)));
- float G1i = ai < 1.6f ? (3.535f * ai + 2.181f * ai * ai) / (1 + 2.276f * ai + 2.577f * ai * ai) : 1.0f;
+ float G1i = bsdf_beckmann_G1(alpha_x, cosNI);
float G = G1o * G1i;
/* eq. 21 */
diff --git a/intern/cycles/kernel/closure/bsdf_microfacet_multi.h b/intern/cycles/kernel/closure/bsdf_microfacet_multi.h
new file mode 100644
index 00000000000..38c645cba87
--- /dev/null
+++ b/intern/cycles/kernel/closure/bsdf_microfacet_multi.h
@@ -0,0 +1,507 @@
+/*
+ * Copyright 2011-2016 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+CCL_NAMESPACE_BEGIN
+
+/* Most of the code is based on the supplemental implementations from https://eheitzresearch.wordpress.com/240-2/. */
+
+/* === GGX Microfacet distribution functions === */
+
+/* Isotropic GGX microfacet distribution */
+ccl_device_inline 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);
+}
+
+/* Anisotropic GGX microfacet distribution */
+ccl_device_inline 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;
+
+ 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_inline float2 mf_sampleP22_11(const float cosI, const float2 randU)
+{
+ if(cosI > 0.9999f || cosI < 1e-6f) {
+ const float r = sqrtf(randU.x / (1.0f - randU.x));
+ const float phi = M_2PI_F * randU.y;
+ return make_float2(r*cosf(phi), r*sinf(phi));
+ }
+
+ const float sinI = 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*randU.x*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(randU.y >= 0.5f)
+ U2 = 2.0f*(randU.y - 0.5f);
+ else
+ U2 = 2.0f*(0.5f - randU.y);
+ 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(randU.y >= 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_inline float3 mf_sample_vndf(const float3 wi, const float2 alpha, const float2 randU)
+{
+ 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, randU);
+
+ const float2 cossin_phi = normalize(make_float2(wi_11.x, wi_11.y));
+ 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));
+}
+
+/* === Phase functions: Glossy, Diffuse and Glass === */
+
+/* Phase function for reflective materials, either without a fresnel term (for compatibility) or with the conductive fresnel term. */
+ccl_device_inline float3 mf_sample_phase_glossy(const float3 wi, float3 *n, float3 *k, float3 *weight, const float3 wm)
+{
+ if(n && k)
+ *weight *= fresnel_conductor(dot(wi, wm), *n, *k);
+
+ return -wi + 2.0f * wm * dot(wi, wm);
+}
+
+ccl_device_inline float3 mf_eval_phase_glossy(const float3 w, const float lambda, const float3 wo, const float2 alpha, float3 *n, float3 *k)
+{
+ 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);
+
+ 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);
+
+ 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);
+
+ if(n && k) {
+ /* Apply conductive fresnel term. */
+ return phase * fresnel_conductor(dotW_WH, *n, *k);
+ }
+
+ return make_float3(phase, phase, phase);
+}
+
+/* Phase function for rough lambertian diffuse surfaces. */
+ccl_device_inline float3 mf_sample_phase_diffuse(const float3 wm, const float randu, const float randv)
+{
+ float3 tm, bm;
+ make_orthonormals(wm, &tm, &bm);
+
+ float2 disk = concentric_sample_disk(randu, randv);
+ return disk.x*tm + disk.y*bm + safe_sqrtf(1.0f - disk.x*disk.x - disk.y*disk.y)*wm;
+}
+
+ccl_device_inline float3 mf_eval_phase_diffuse(const float3 w, const float3 wm)
+{
+ const float v = max(0.0f, dot(w, wm)) * M_1_PI_F;
+ return make_float3(v, v, v);
+}
+
+/* Phase function for dielectric transmissive materials, including both reflection and refraction according to the dielectric fresnel term. */
+ccl_device_inline 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_inline 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 === */
+
+/* Smith Lambda function for GGX (based on page 12 of the supplemental implementation). */
+ccl_device_inline 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;
+
+ 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);
+}
+
+/* Height distribution CDF (based on page 4 of the supplemental implementation). */
+ccl_device_inline float mf_invC1(const float h)
+{
+ return 2.0f * saturate(h) - 1.0f;
+}
+
+ccl_device_inline float mf_C1(const float h)
+{
+ return saturate(0.5f * (h + 1.0f));
+}
+
+/* Masking function (based on page 16 of the supplemental implementation). */
+ccl_device_inline 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);
+}
+
+/* Sampling from the visible height distribution (based on page 17 of the supplemental implementation). */
+ccl_device_inline 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. ===
+ * As explained in bsdf_microfacet_multi_impl.h, using approximations with MIS still produces an unbiased result. */
+
+/* Approximation for the albedo of the single-scattering GGX distribution,
+ * the missing energy is then approximated as a diffuse reflection for the PDF. */
+ccl_device_inline 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);
+}
+
+ccl_device_inline 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 albedo = mf_ggx_albedo(alpha);
+ return 0.25f * D / max((1.0f + lambda) * wi.z, 1e-7f) + (1.0f - albedo) * wo.z;
+}
+
+ccl_device_inline float mf_ggx_aniso_pdf(const float3 wi, const float3 wo, const float2 alpha)
+{
+ return 0.25f * D_ggx_aniso(normalize(wi+wo), alpha) / ((1.0f + mf_lambda(wi, alpha)) * wi.z) + (1.0f - mf_ggx_albedo(sqrtf(alpha.x*alpha.y))) * wo.z;
+}
+
+ccl_device_inline float mf_diffuse_pdf(const float3 wo)
+{
+ return M_1_PI_F * wo.z;
+}
+
+ccl_device_inline float mf_glass_pdf(const float3 wi, const float3 wo, const float alpha, const float eta)
+{
+ float3 wh;
+ float fresnel;
+ if(wi.z*wo.z > 0.0f) {
+ wh = normalize(wi + wo);
+ fresnel = fresnel_dielectric_cos(dot(wi, wh), eta);
+ }
+ else {
+ wh = normalize(wi + wo*eta);
+ fresnel = 1.0f - fresnel_dielectric_cos(dot(wi, wh), eta);
+ }
+ if(wh.z < 0.0f)
+ wh = -wh;
+ float3 r_wi = (wi.z < 0.0f)? -wi: wi;
+ return fresnel * max(0.0f, dot(r_wi, wh)) * D_ggx(wh, alpha) / ((1.0f + mf_lambda(r_wi, make_float2(alpha, alpha))) * r_wi.z) + fabsf(wo.z);
+}
+
+/* === 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_FUNCTION_FULL_NAME(prefix) MF_NAME_EVAL(prefix, MF_PHASE_FUNCTION)
+
+#define MF_PHASE_FUNCTION glass
+#define MF_MULTI_GLASS
+#include "bsdf_microfacet_multi_impl.h"
+
+/* The diffuse phase function is not implemented as a node yet. */
+#if 0
+#define MF_PHASE_FUNCTION diffuse
+#define MF_MULTI_DIFFUSE
+#include "bsdf_microfacet_multi_impl.h"
+#endif
+
+#define MF_PHASE_FUNCTION glossy
+#define MF_MULTI_GLOSSY
+#include "bsdf_microfacet_multi_impl.h"
+
+ccl_device void bsdf_microfacet_multi_ggx_blur(ShaderClosure *sc, float roughness)
+{
+ MicrofacetBsdf *bsdf = (MicrofacetBsdf*)sc;
+
+ bsdf->alpha_x = fmaxf(roughness, bsdf->alpha_x);
+ bsdf->alpha_y = fmaxf(roughness, bsdf->alpha_y);
+}
+
+/* === Closure implementations === */
+
+/* Multiscattering GGX Glossy closure */
+
+ccl_device int bsdf_microfacet_multi_ggx_common_setup(MicrofacetBsdf *bsdf, bool use_fresnel = false)
+{
+ 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->use_fresnel = use_fresnel;
+ 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_ID;
+
+ return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_NEEDS_LCG;
+}
+
+ccl_device int bsdf_microfacet_multi_ggx_aniso_setup(MicrofacetBsdf *bsdf, bool use_fresnel = false)
+{
+ if(is_zero(bsdf->T))
+ bsdf->T = make_float3(1.0f, 0.0f, 0.0f);
+
+ return bsdf_microfacet_multi_ggx_common_setup(bsdf, use_fresnel);
+}
+
+ccl_device int bsdf_microfacet_multi_ggx_setup(MicrofacetBsdf *bsdf, bool use_fresnel = false)
+{
+ bsdf->alpha_y = bsdf->alpha_x;
+
+ return bsdf_microfacet_multi_ggx_common_setup(bsdf, use_fresnel);
+}
+
+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 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;
+ 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, NULL, NULL);
+}
+
+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;
+ 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;
+
+ *eval = mf_sample_glossy(localI, &localO, bsdf->extra->color, bsdf->alpha_x, bsdf->alpha_y, lcg_state, NULL, NULL);
+ 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;
+#endif
+ return LABEL_REFLECT|LABEL_GLOSSY;
+}
+
+/* Multiscattering GGX Glass closure */
+
+ccl_device int bsdf_microfacet_multi_ggx_glass_setup(MicrofacetBsdf *bsdf, bool use_fresnel = false)
+{
+ 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->use_fresnel = use_fresnel;
+ 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_ID;
+
+ 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;
+ 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);
+}
+
+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;
+ 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);
+}
+
+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;
+ 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;
+
+ *eval = mf_sample_glass(localI, &localO, bsdf->extra->color, bsdf->alpha_x, bsdf->alpha_y, lcg_state, bsdf->ior);
+ *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;
+#endif
+ 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;
+#endif
+
+ 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
new file mode 100644
index 00000000000..afd4a8da62a
--- /dev/null
+++ b/intern/cycles/kernel/closure/bsdf_microfacet_multi_impl.h
@@ -0,0 +1,226 @@
+/*
+ * Copyright 2011-2016 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* Evaluate the BSDF from wi to wo.
+ * Evaluation is split into the analytical single-scattering BSDF and the multi-scattering BSDF,
+ * which is evaluated stochastically through a random walk. At each bounce (except for the first one),
+ * the amount of reflection from here towards wo is evaluated before bouncing again.
+ *
+ * Because of the random walk, the evaluation is not deterministic, but its expected value is equal to
+ * the correct BSDF, which is enough for Monte-Carlo rendering. The PDF also can't be determined
+ * analytically, so the single-scattering PDF plus a diffuse term to account for the multi-scattered
+ * 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 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
+#ifdef MF_MULTI_GLASS
+ , const float eta
+#elif defined(MF_MULTI_GLOSSY)
+ , float3 *n, float3 *k
+#endif
+)
+{
+ /* 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
+#endif
+ 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);
+
+ 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);
+
+ /* Analytically compute single scattering for lower noise. */
+ float3 eval;
+#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);
+#elif defined(MF_MULTI_DIFFUSE)
+ /* Diffuse has no special closed form for the single scattering bounce */
+ eval = make_float3(0.0f, 0.0f, 0.0f);
+#else /* MF_MULTI_GLOSSY */
+ const float3 wh = normalize(wi+wo);
+ 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);
+ if(n && k) {
+ eval = fresnel_conductor(dot(wh, wi), *n, *k) * val;
+ }
+ else {
+ eval = make_float3(val, val, val);
+ }
+#endif
+
+ float3 wr = -wi;
+ 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);
+
+ for(int order = 0; order < 10; order++) {
+ /* Sample microfacet height and normal */
+ if(!mf_sample_height(wr, &hr, &C1_r, &G1_r, &lambda_r, lcg_step_float_addrspace(lcg_state)))
+ break;
+ float3 wm = mf_sample_vndf(-wr, alpha, make_float2(lcg_step_float_addrspace(lcg_state),
+ lcg_step_float_addrspace(lcg_state)));
+
+#ifdef MF_MULTI_DIFFUSE
+ if(order == 0) {
+ /* Compute single-scattering for diffuse. */
+ const float G2_G1 = -lambda_r / (shadowing_lambda - lambda_r);
+ eval += throughput * G2_G1 * mf_eval_phase_diffuse(wo, wm);
+ }
+#endif
+ 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);
+#elif defined(MF_MULTI_DIFFUSE)
+ phase = mf_eval_phase_diffuse(wo, wm);
+#else /* MF_MULTI_GLOSSY */
+ phase = mf_eval_phase_glossy(wr, lambda_r, wo, alpha, n, k) * 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. */
+#ifdef MF_MULTI_GLASS
+ bool next_outside;
+ wr = mf_sample_phase_glass(-wr, outside? eta: 1.0f/eta, wm, lcg_step_float_addrspace(lcg_state), &next_outside);
+ if(!next_outside) {
+ outside = !outside;
+ wr = -wr;
+ hr = -hr;
+ }
+#elif defined(MF_MULTI_DIFFUSE)
+ wr = mf_sample_phase_diffuse(wm,
+ lcg_step_float_addrspace(lcg_state),
+ lcg_step_float_addrspace(lcg_state));
+#else /* MF_MULTI_GLOSSY */
+ wr = mf_sample_phase_glossy(-wr, n, k, &throughput, wm);
+#endif
+
+ lambda_r = mf_lambda(wr, alpha);
+
+ throughput *= color;
+
+ C1_r = mf_C1(hr);
+ G1_r = mf_G1(wr, C1_r, lambda_r);
+ }
+ }
+
+ 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 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
+#ifdef MF_MULTI_GLASS
+ , const float eta
+#elif defined(MF_MULTI_GLOSSY)
+ , float3 *n, float3 *k
+#endif
+)
+{
+ 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;
+
+ int order;
+ for(order = 0; order < 10; order++) {
+ /* Sample microfacet height. */
+ if(!mf_sample_height(wr, &hr, &C1_r, &G1_r, &lambda_r, lcg_step_float_addrspace(lcg_state))) {
+ /* The random walk has left the surface. */
+ *wo = outside? wr: -wr;
+ return throughput;
+ }
+ /* Sample microfacet normal. */
+ float3 wm = mf_sample_vndf(-wr, alpha, make_float2(lcg_step_float_addrspace(lcg_state),
+ lcg_step_float_addrspace(lcg_state)));
+
+ /* First-bounce color is already accounted for in mix weight. */
+ if(order > 0)
+ throughput *= color;
+
+ /* Bounce from the microfacet. */
+#ifdef MF_MULTI_GLASS
+ bool next_outside;
+ wr = mf_sample_phase_glass(-wr, outside? eta: 1.0f/eta, wm, lcg_step_float_addrspace(lcg_state), &next_outside);
+ if(!next_outside) {
+ hr = -hr;
+ wr = -wr;
+ outside = !outside;
+ }
+#elif defined(MF_MULTI_DIFFUSE)
+ wr = mf_sample_phase_diffuse(wm,
+ lcg_step_float_addrspace(lcg_state),
+ lcg_step_float_addrspace(lcg_state));
+#else /* MF_MULTI_GLOSSY */
+ wr = mf_sample_phase_glossy(-wr, n, k, &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);
+}
+
+#undef MF_MULTI_GLASS
+#undef MF_MULTI_DIFFUSE
+#undef MF_MULTI_GLOSSY
+#undef MF_PHASE_FUNCTION
diff --git a/intern/cycles/kernel/closure/bsdf_oren_nayar.h b/intern/cycles/kernel/closure/bsdf_oren_nayar.h
index 61b7cb11b02..cb342a026ef 100644
--- a/intern/cycles/kernel/closure/bsdf_oren_nayar.h
+++ b/intern/cycles/kernel/closure/bsdf_oren_nayar.h
@@ -19,39 +19,59 @@
CCL_NAMESPACE_BEGIN
+typedef ccl_addr_space struct OrenNayarBsdf {
+ SHADER_CLOSURE_BASE;
+
+ float3 N;
+ float roughness;
+ float a;
+ float b;
+} OrenNayarBsdf;
+
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 * (sc->data0 + sc->data1 * t);
+ float is = nl * (bsdf->a + bsdf->b * t);
return make_float3(is, is, is);
}
-ccl_device int bsdf_oren_nayar_setup(ShaderClosure *sc)
+ccl_device int bsdf_oren_nayar_setup(OrenNayarBsdf *bsdf)
{
- float sigma = sc->data0;
+ float sigma = bsdf->roughness;
- sc->type = CLOSURE_BSDF_OREN_NAYAR_ID;
+ bsdf->type = CLOSURE_BSDF_OREN_NAYAR_ID;
sigma = saturate(sigma);
float div = 1.0f / (M_PI_F + ((3.0f * M_PI_F - 4.0f) / 6.0f) * sigma);
- sc->data0 = 1.0f * div;
- sc->data1 = sigma * div;
+ bsdf->a = 1.0f * div;
+ bsdf->b = sigma * div;
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;
+
+ 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)
{
- if(dot(sc->N, omega_in) > 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, sc->N, I, omega_in);
+ return bsdf_oren_nayar_get_intensity(sc, bsdf->N, I, omega_in);
}
else {
*pdf = 0.0f;
@@ -66,15 +86,16 @@ ccl_device float3 bsdf_oren_nayar_eval_transmit(const ShaderClosure *sc, const f
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)
{
- sample_uniform_hemisphere(sc->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, sc->N, I, *omega_in);
+ *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(sc->N, dIdx)) * sc->N - dIdx;
- *domega_in_dy = (2.0f * dot(sc->N, dIdy)) * sc->N - dIdy;
+ *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 {
diff --git a/intern/cycles/kernel/closure/bsdf_phong_ramp.h b/intern/cycles/kernel/closure/bsdf_phong_ramp.h
index 1ab15eee954..e152a8780db 100644
--- a/intern/cycles/kernel/closure/bsdf_phong_ramp.h
+++ b/intern/cycles/kernel/closure/bsdf_phong_ramp.h
@@ -35,7 +35,17 @@
CCL_NAMESPACE_BEGIN
-ccl_device float3 bsdf_phong_ramp_get_color(const ShaderClosure *sc, const float3 colors[8], float pos)
+#ifdef __OSL__
+
+typedef ccl_addr_space struct PhongRampBsdf {
+ SHADER_CLOSURE_BASE;
+
+ float3 N;
+ float exponent;
+ float3 *colors;
+} PhongRampBsdf;
+
+ccl_device float3 bsdf_phong_ramp_get_color(const float3 colors[8], float pos)
{
int MAXCOLORS = 8;
@@ -49,57 +59,54 @@ ccl_device float3 bsdf_phong_ramp_get_color(const ShaderClosure *sc, const float
return colors[ipos] * (1.0f - offset) + colors[ipos+1] * offset;
}
-ccl_device int bsdf_phong_ramp_setup(ShaderClosure *sc)
+ccl_device int bsdf_phong_ramp_setup(PhongRampBsdf *bsdf)
{
- sc->type = CLOSURE_BSDF_PHONG_RAMP_ID;
- sc->data0 = max(sc->data0, 0.0f);
- sc->data1 = 0.0f;
+ bsdf->type = CLOSURE_BSDF_PHONG_RAMP_ID;
+ bsdf->exponent = max(bsdf->exponent, 0.0f);
return SD_BSDF|SD_BSDF_HAS_EVAL;
}
-ccl_device void bsdf_phong_ramp_blur(ShaderClosure *sc, float roughness)
-{
-}
-
-ccl_device float3 bsdf_phong_ramp_eval_reflect(const ShaderClosure *sc, const float3 colors[8], 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)
{
- float m_exponent = sc->data0;
- float cosNI = dot(sc->N, omega_in);
- float cosNO = dot(sc->N, I);
+ 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) * sc->N - I;
+ 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(sc, colors, cosp) * out;
+ 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 colors[8], 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);
}
-ccl_device int bsdf_phong_ramp_sample(const ShaderClosure *sc, const float3 colors[8], 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)
{
- float cosNO = dot(sc->N, I);
- float m_exponent = sc->data0;
+ 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) * sc->N - I;
+ float3 R = (2 * cosNO) * bsdf->N - I;
#ifdef __RAY_DIFFERENTIALS__
- *domega_in_dx = (2 * dot(sc->N, dIdx)) * sc->N - dIdx;
- *domega_in_dy = (2 * dot(sc->N, dIdy)) * sc->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
float3 T, B;
@@ -114,7 +121,7 @@ ccl_device int bsdf_phong_ramp_sample(const ShaderClosure *sc, const float3 colo
if(dot(Ng, *omega_in) > 0.0f)
{
// common terms for pdf and eval
- float cosNI = dot(sc->N, *omega_in);
+ float cosNI = dot(bsdf->N, *omega_in);
// make sure the direction we chose is still in the right hemisphere
if(cosNI > 0)
{
@@ -122,13 +129,14 @@ ccl_device int bsdf_phong_ramp_sample(const ShaderClosure *sc, const float3 colo
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(sc, colors, cosp) * out;
+ *eval = bsdf_phong_ramp_get_color(bsdf->colors, cosp) * out;
}
}
}
return LABEL_REFLECT|LABEL_GLOSSY;
}
+#endif /* __OSL__ */
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/closure/bsdf_reflection.h b/intern/cycles/kernel/closure/bsdf_reflection.h
index 303f4c9ce34..1d21614ecee 100644
--- a/intern/cycles/kernel/closure/bsdf_reflection.h
+++ b/intern/cycles/kernel/closure/bsdf_reflection.h
@@ -37,9 +37,9 @@ CCL_NAMESPACE_BEGIN
/* REFLECTION */
-ccl_device int bsdf_reflection_setup(ShaderClosure *sc)
+ccl_device int bsdf_reflection_setup(MicrofacetBsdf *bsdf)
{
- sc->type = CLOSURE_BSDF_REFLECTION_ID;
+ bsdf->type = CLOSURE_BSDF_REFLECTION_ID;
return SD_BSDF;
}
@@ -55,7 +55,8 @@ ccl_device float3 bsdf_reflection_eval_transmit(const ShaderClosure *sc, const f
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)
{
- float3 N = sc->N;
+ const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
+ float3 N = bsdf->N;
// only one direction is possible
float cosNO = dot(N, I);
diff --git a/intern/cycles/kernel/closure/bsdf_refraction.h b/intern/cycles/kernel/closure/bsdf_refraction.h
index c78a4b67134..050a4e76fa9 100644
--- a/intern/cycles/kernel/closure/bsdf_refraction.h
+++ b/intern/cycles/kernel/closure/bsdf_refraction.h
@@ -37,9 +37,9 @@ CCL_NAMESPACE_BEGIN
/* REFRACTION */
-ccl_device int bsdf_refraction_setup(ShaderClosure *sc)
+ccl_device int bsdf_refraction_setup(MicrofacetBsdf *bsdf)
{
- sc->type = CLOSURE_BSDF_REFRACTION_ID;
+ bsdf->type = CLOSURE_BSDF_REFRACTION_ID;
return SD_BSDF;
}
@@ -55,8 +55,9 @@ ccl_device float3 bsdf_refraction_eval_transmit(const ShaderClosure *sc, const f
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)
{
- float m_eta = sc->data0;
- float3 N = sc->N;
+ const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
+ float m_eta = bsdf->ior;
+ float3 N = bsdf->N;
float3 R, T;
#ifdef __RAY_DIFFERENTIALS__
diff --git a/intern/cycles/kernel/closure/bsdf_toon.h b/intern/cycles/kernel/closure/bsdf_toon.h
index e5b6ab93a64..28e775bcbc8 100644
--- a/intern/cycles/kernel/closure/bsdf_toon.h
+++ b/intern/cycles/kernel/closure/bsdf_toon.h
@@ -35,17 +35,35 @@
CCL_NAMESPACE_BEGIN
+typedef ccl_addr_space struct ToonBsdf {
+ SHADER_CLOSURE_BASE;
+
+ float3 N;
+ float size;
+ float smooth;
+} ToonBsdf;
+
/* DIFFUSE TOON */
-ccl_device int bsdf_diffuse_toon_setup(ShaderClosure *sc)
+ccl_device int bsdf_diffuse_toon_setup(ToonBsdf *bsdf)
{
- sc->type = CLOSURE_BSDF_DIFFUSE_TOON_ID;
- sc->data0 = saturate(sc->data0);
- sc->data1 = saturate(sc->data1);
+ bsdf->type = CLOSURE_BSDF_DIFFUSE_TOON_ID;
+ bsdf->size = saturate(bsdf->size);
+ bsdf->smooth = saturate(bsdf->smooth);
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;
+
+ 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;
@@ -67,9 +85,10 @@ ccl_device float bsdf_toon_get_sample_angle(float max_angle, float smooth)
ccl_device float3 bsdf_diffuse_toon_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
{
- float max_angle = sc->data0*M_PI_2_F;
- float smooth = sc->data1*M_PI_2_F;
- float angle = safe_acosf(fmaxf(dot(sc->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);
@@ -90,21 +109,22 @@ ccl_device float3 bsdf_diffuse_toon_eval_transmit(const ShaderClosure *sc, const
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)
{
- float max_angle = sc->data0*M_PI_2_F;
- float smooth = sc->data1*M_PI_2_F;
+ 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(sc->N, sample_angle, randu, randv, omega_in, pdf);
+ 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);
#ifdef __RAY_DIFFERENTIALS__
// TODO: find a better approximation for the bounce
- *domega_in_dx = (2.0f * dot(sc->N, dIdx)) * sc->N - dIdx;
- *domega_in_dy = (2.0f * dot(sc->N, dIdy)) * sc->N - dIdy;
+ *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
@@ -117,25 +137,26 @@ ccl_device int bsdf_diffuse_toon_sample(const ShaderClosure *sc, float3 Ng, floa
/* GLOSSY TOON */
-ccl_device int bsdf_glossy_toon_setup(ShaderClosure *sc)
+ccl_device int bsdf_glossy_toon_setup(ToonBsdf *bsdf)
{
- sc->type = CLOSURE_BSDF_GLOSSY_TOON_ID;
- sc->data0 = saturate(sc->data0);
- sc->data1 = saturate(sc->data1);
+ bsdf->type = CLOSURE_BSDF_GLOSSY_TOON_ID;
+ bsdf->size = saturate(bsdf->size);
+ bsdf->smooth = saturate(bsdf->smooth);
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)
{
- float max_angle = sc->data0*M_PI_2_F;
- float smooth = sc->data1*M_PI_2_F;
- float cosNI = dot(sc->N, omega_in);
- float cosNO = dot(sc->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) * sc->N - I;
+ float3 R = (2 * cosNO) * bsdf->N - I;
float cosRI = dot(R, omega_in);
float angle = safe_acosf(fmaxf(cosRI, 0.0f));
@@ -157,13 +178,14 @@ ccl_device float3 bsdf_glossy_toon_eval_transmit(const ShaderClosure *sc, const
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)
{
- float max_angle = sc->data0*M_PI_2_F;
- float smooth = sc->data1*M_PI_2_F;
- float cosNO = dot(sc->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) * sc->N - I;
+ float3 R = (2 * cosNO) * bsdf->N - I;
float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth);
float angle = sample_angle*randu;
@@ -171,15 +193,15 @@ ccl_device int bsdf_glossy_toon_sample(const ShaderClosure *sc, float3 Ng, float
sample_uniform_cone(R, sample_angle, randu, randv, omega_in, pdf);
if(dot(Ng, *omega_in) > 0.0f) {
- float cosNI = dot(sc->N, *omega_in);
+ 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);
#ifdef __RAY_DIFFERENTIALS__
- *domega_in_dx = (2 * dot(sc->N, dIdx)) * sc->N - dIdx;
- *domega_in_dy = (2 * dot(sc->N, dIdy)) * sc->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
diff --git a/intern/cycles/kernel/closure/bsdf_util.h b/intern/cycles/kernel/closure/bsdf_util.h
index f99e0c3dca7..397d642c35a 100644
--- a/intern/cycles/kernel/closure/bsdf_util.h
+++ b/intern/cycles/kernel/closure/bsdf_util.h
@@ -80,7 +80,7 @@ ccl_device float fresnel_dielectric(
return 1; // total internal reflection
}
else {
- float dnp = sqrtf(arg);
+ float dnp = max(sqrtf(arg), 1e-7f);
float nK = (neta * cos)- dnp;
*T = -(neta * I)+(nK * Nn);
#ifdef __RAY_DIFFERENTIALS__
@@ -111,10 +111,9 @@ ccl_device float fresnel_dielectric_cos(float cosi, float eta)
return 1.0f; // TIR(no refracted component)
}
-#if 0
ccl_device float3 fresnel_conductor(float cosi, const float3 eta, const float3 k)
{
- float3 cosi2 = make_float3(cosi*cosi);
+ 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;
@@ -124,7 +123,6 @@ ccl_device float3 fresnel_conductor(float cosi, const float3 eta, const float3 k
(tmp_f + (2.0f * eta * cosi) + cosi2);
return(Rparl2 + Rperp2) * 0.5f;
}
-#endif
ccl_device float schlick_fresnel(float u)
{
diff --git a/intern/cycles/kernel/closure/bssrdf.h b/intern/cycles/kernel/closure/bssrdf.h
index a1920841e6e..e31d790dd84 100644
--- a/intern/cycles/kernel/closure/bssrdf.h
+++ b/intern/cycles/kernel/closure/bssrdf.h
@@ -19,6 +19,19 @@
CCL_NAMESPACE_BEGIN
+typedef ccl_addr_space struct Bssrdf {
+ SHADER_CLOSURE_BASE;
+
+ float radius;
+ float sharpness;
+ float d;
+ float texture_blur;
+ float albedo;
+ float roughness;
+ float3 N;
+ float3 baseColor;
+} Bssrdf;
+
/* Planar Truncated Gaussian
*
* Note how this is different from the typical gaussian, this one integrates
@@ -28,11 +41,12 @@ CCL_NAMESPACE_BEGIN
/* paper suggests 1/12.46 which is much too small, suspect it's *12.46 */
#define GAUSS_TRUNCATE 12.46f
-ccl_device float bssrdf_gaussian_eval(ShaderClosure *sc, float r)
+ccl_device float bssrdf_gaussian_eval(const ShaderClosure *sc, 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 = sc->data0*sc->data0*(0.25f*0.25f);
+ const Bssrdf *bssrdf = (const Bssrdf*)sc;
+ const float v = bssrdf->radius*bssrdf->radius*(0.25f*0.25f);
const float Rm = sqrtf(v*GAUSS_TRUNCATE);
if(r >= Rm)
@@ -41,7 +55,7 @@ ccl_device float bssrdf_gaussian_eval(ShaderClosure *sc, float r)
return expf(-r*r/(2.0f*v))/(2.0f*M_PI_F*v);
}
-ccl_device float bssrdf_gaussian_pdf(ShaderClosure *sc, float r)
+ccl_device float bssrdf_gaussian_pdf(const ShaderClosure *sc, float r)
{
/* 1.0 - expf(-Rm*Rm/(2*v)) simplified */
const float area_truncated = 1.0f - expf(-0.5f*GAUSS_TRUNCATE);
@@ -49,12 +63,12 @@ ccl_device float bssrdf_gaussian_pdf(ShaderClosure *sc, float r)
return bssrdf_gaussian_eval(sc, r) * (1.0f/(area_truncated));
}
-ccl_device void bssrdf_gaussian_sample(ShaderClosure *sc, float xi, float *r, float *h)
+ccl_device void bssrdf_gaussian_sample(const ShaderClosure *sc, 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 = sc->data0*sc->data0*(0.25f*0.25f);
+ const Bssrdf *bssrdf = (const Bssrdf*)sc;
+ const float v = bssrdf->radius*bssrdf->radius*(0.25f*0.25f);
const float Rm = sqrtf(v*GAUSS_TRUNCATE);
/* 1.0 - expf(-Rm*Rm/(2*v)) simplified */
@@ -75,12 +89,13 @@ ccl_device void bssrdf_gaussian_sample(ShaderClosure *sc, float xi, float *r, fl
* far as I can tell has no closed form solution. So we get an iterative solution
* instead with newton-raphson. */
-ccl_device float bssrdf_cubic_eval(ShaderClosure *sc, float r)
+ccl_device float bssrdf_cubic_eval(const ShaderClosure *sc, float r)
{
- const float sharpness = sc->T.x;
+ const Bssrdf *bssrdf = (const Bssrdf*)sc;
+ const float sharpness = bssrdf->sharpness;
if(sharpness == 0.0f) {
- const float Rm = sc->data0;
+ const float Rm = bssrdf->radius;
if(r >= Rm)
return 0.0f;
@@ -94,7 +109,7 @@ ccl_device float bssrdf_cubic_eval(ShaderClosure *sc, float r)
}
else {
- float Rm = sc->data0*(1.0f + sharpness);
+ float Rm = bssrdf->radius*(1.0f + sharpness);
if(r >= Rm)
return 0.0f;
@@ -122,7 +137,7 @@ ccl_device float bssrdf_cubic_eval(ShaderClosure *sc, float r)
}
}
-ccl_device float bssrdf_cubic_pdf(ShaderClosure *sc, float r)
+ccl_device float bssrdf_cubic_pdf(const ShaderClosure *sc, float r)
{
return bssrdf_cubic_eval(sc, r);
}
@@ -155,12 +170,13 @@ ccl_device float bssrdf_cubic_quintic_root_find(float xi)
return x;
}
-ccl_device void bssrdf_cubic_sample(ShaderClosure *sc, float xi, float *r, float *h)
+ccl_device void bssrdf_cubic_sample(const ShaderClosure *sc, float xi, float *r, float *h)
{
- float Rm = sc->data0;
+ const Bssrdf *bssrdf = (const Bssrdf*)sc;
+ const float sharpness = bssrdf->sharpness;
+ float Rm = bssrdf->radius;
float r_ = bssrdf_cubic_quintic_root_find(xi);
- const float sharpness = sc->T.x;
if(sharpness != 0.0f) {
r_ = powf(r_, 1.0f + sharpness);
Rm *= (1.0f + sharpness);
@@ -198,21 +214,22 @@ ccl_device_inline float bssrdf_burley_compatible_mfp(float r)
return 0.25f * M_1_PI_F * r;
}
-ccl_device void bssrdf_burley_setup(ShaderClosure *sc)
+ccl_device void bssrdf_burley_setup(Bssrdf *bssrdf)
{
/* Mean free path length. */
- const float l = bssrdf_burley_compatible_mfp(sc->data0);
+ const float l = bssrdf_burley_compatible_mfp(bssrdf->radius);
/* Surface albedo. */
- const float A = sc->data2;
+ const float A = bssrdf->albedo;
const float s = bssrdf_burley_fitting(A);
const float d = l / s;
- sc->custom1 = d;
+ bssrdf->d = d;
}
-ccl_device float bssrdf_burley_eval(ShaderClosure *sc, float r)
+ccl_device float bssrdf_burley_eval(const ShaderClosure *sc, float r)
{
- const float d = sc->custom1;
+ const Bssrdf *bssrdf = (const Bssrdf*)sc;
+ const float d = bssrdf->d;
const float Rm = BURLEY_TRUNCATE * d;
if(r >= Rm)
@@ -231,7 +248,7 @@ ccl_device float bssrdf_burley_eval(ShaderClosure *sc, float r)
return (exp_r_d + exp_r_3_d) / (4.0f*d);
}
-ccl_device float bssrdf_burley_pdf(ShaderClosure *sc, float r)
+ccl_device float bssrdf_burley_pdf(const ShaderClosure *sc, float r)
{
return bssrdf_burley_eval(sc, r) * (1.0f/BURLEY_TRUNCATE_CDF);
}
@@ -276,12 +293,13 @@ ccl_device float bssrdf_burley_root_find(float xi)
return r;
}
-ccl_device void bssrdf_burley_sample(ShaderClosure *sc,
+ccl_device void bssrdf_burley_sample(const ShaderClosure *sc,
float xi,
float *r,
float *h)
{
- const float d = sc->custom1;
+ const Bssrdf *bssrdf = (const Bssrdf*)sc;
+ const float d = bssrdf->d;
const float Rm = BURLEY_TRUNCATE * d;
const float r_ = bssrdf_burley_root_find(xi * BURLEY_TRUNCATE_CDF) * d;
@@ -295,26 +313,29 @@ ccl_device void bssrdf_burley_sample(ShaderClosure *sc,
*
* Samples distributed over disk with no falloff, for reference. */
-ccl_device float bssrdf_none_eval(ShaderClosure *sc, float r)
+ccl_device float bssrdf_none_eval(const ShaderClosure *sc, float r)
{
- const float Rm = sc->data0;
+ const Bssrdf *bssrdf = (const Bssrdf*)sc;
+ const float Rm = bssrdf->radius;
return (r < Rm)? 1.0f: 0.0f;
}
-ccl_device float bssrdf_none_pdf(ShaderClosure *sc, float r)
+ccl_device float bssrdf_none_pdf(const ShaderClosure *sc, float r)
{
/* integrate (2*pi*r)/(pi*Rm*Rm) from 0 to Rm = 1 */
- const float Rm = sc->data0;
+ const Bssrdf *bssrdf = (const Bssrdf*)sc;
+ const float Rm = bssrdf->radius;
const float area = (M_PI_F*Rm*Rm);
return bssrdf_none_eval(sc, r) / area;
}
-ccl_device void bssrdf_none_sample(ShaderClosure *sc, float xi, float *r, float *h)
+ccl_device void bssrdf_none_sample(const ShaderClosure *sc, 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 = sc->data0;
+ const Bssrdf *bssrdf = (const Bssrdf*)sc;
+ const float Rm = bssrdf->radius;
const float r_ = sqrtf(xi)*Rm;
*r = r_;
@@ -325,40 +346,54 @@ ccl_device void bssrdf_none_sample(ShaderClosure *sc, float xi, float *r, float
/* Generic */
-ccl_device int bssrdf_setup(ShaderClosure *sc, ClosureType type)
+ccl_device_inline Bssrdf *bssrdf_alloc(ShaderData *sd, float3 weight)
+{
+ Bssrdf *bssrdf = (Bssrdf*)closure_alloc(sd, sizeof(Bssrdf), CLOSURE_NONE_ID, weight);
+
+ if(!bssrdf)
+ return 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(Bssrdf *bssrdf, ClosureType type)
{
- if(sc->data0 < BSSRDF_MIN_RADIUS) {
+ if(bssrdf->radius < BSSRDF_MIN_RADIUS) {
/* revert to diffuse BSDF if radius too small */
int flag;
if (type == CLOSURE_BSSRDF_DISNEY_ID) {
- sc->data0 = sc->data3;
- sc->data1 = 0.0f;
- flag = bsdf_disney_diffuse_setup(sc);
- sc->type = CLOSURE_BSDF_BSSRDF_DISNEY_ID;
+ DisneyDiffuseBsdf *bsdf = (DisneyDiffuseBsdf*)bssrdf;
+ bsdf->N = bssrdf->N;
+ bsdf->roughness = bssrdf->roughness;
+ bsdf->baseColor = bssrdf->baseColor;
+ flag = bsdf_disney_diffuse_setup(bsdf);
+ bsdf->type = CLOSURE_BSDF_BSSRDF_DISNEY_ID;
}
else {
- sc->data0 = 0.0f;
- sc->data1 = 0.0f;
- flag = bsdf_diffuse_setup(sc);
- sc->type = CLOSURE_BSDF_BSSRDF_ID;
+ DiffuseBsdf *bsdf = (DiffuseBsdf*)bssrdf;
+ bsdf->N = bssrdf->N;
+ flag = bsdf_diffuse_setup(bsdf);
+ bsdf->type = CLOSURE_BSDF_BSSRDF_ID;
}
return flag;
}
else {
- sc->data1 = saturate(sc->data1); /* texture blur */
- sc->T.x = saturate(sc->T.x); /* sharpness */
- sc->type = type;
+ bssrdf->texture_blur = saturate(bssrdf->texture_blur);
+ bssrdf->sharpness = saturate(bssrdf->sharpness);
+ bssrdf->type = type;
if (type == CLOSURE_BSSRDF_BURLEY_ID || type == CLOSURE_BSSRDF_DISNEY_ID) {
- bssrdf_burley_setup(sc);
+ bssrdf_burley_setup(bssrdf);
}
return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSSRDF;
}
}
-ccl_device void bssrdf_sample(ShaderClosure *sc, float xi, float *r, float *h)
+ccl_device void bssrdf_sample(const ShaderClosure *sc, float xi, float *r, float *h)
{
if(sc->type == CLOSURE_BSSRDF_CUBIC_ID)
bssrdf_cubic_sample(sc, xi, r, h);
@@ -368,7 +403,7 @@ ccl_device void bssrdf_sample(ShaderClosure *sc, float xi, float *r, float *h)
bssrdf_burley_sample(sc, xi, r, h);
}
-ccl_device float bssrdf_pdf(ShaderClosure *sc, float r)
+ccl_device float bssrdf_pdf(const ShaderClosure *sc, float r)
{
if(sc->type == CLOSURE_BSSRDF_CUBIC_ID)
return bssrdf_cubic_pdf(sc, r);
diff --git a/intern/cycles/kernel/closure/volume.h b/intern/cycles/kernel/closure/volume.h
index 4d71ba50ec3..01e67c7c2fd 100644
--- a/intern/cycles/kernel/closure/volume.h
+++ b/intern/cycles/kernel/closure/volume.h
@@ -19,6 +19,12 @@
CCL_NAMESPACE_BEGIN
+typedef ccl_addr_space struct HenyeyGreensteinVolume {
+ SHADER_CLOSURE_BASE;
+
+ float g;
+} HenyeyGreensteinVolume;
+
/* HENYEY-GREENSTEIN CLOSURE */
/* Given cosine between rays, return probability density that a photon bounces
@@ -29,19 +35,28 @@ 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);
};
-ccl_device int volume_henyey_greenstein_setup(ShaderClosure *sc)
+ccl_device int volume_henyey_greenstein_setup(HenyeyGreensteinVolume *volume)
{
- sc->type = CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID;
+ volume->type = CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID;
/* clamp anisotropy to avoid delta function */
- sc->data0 = signf(sc->data0) * min(fabsf(sc->data0), 1.0f - 1e-3f);
+ volume->g = signf(volume->g) * min(fabsf(volume->g), 1.0f - 1e-3f);
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;
+
+ 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)
{
- float g = sc->data0;
+ const HenyeyGreensteinVolume *volume = (const HenyeyGreensteinVolume*)sc;
+ float g = volume->g;
/* note that I points towards the viewer */
if(fabsf(g) < 1e-3f) {
@@ -58,7 +73,8 @@ ccl_device float3 volume_henyey_greenstein_eval_phase(const ShaderClosure *sc, c
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)
{
- float g = sc->data0;
+ const HenyeyGreensteinVolume *volume = (const HenyeyGreensteinVolume*)sc;
+ float g = volume->g;
float cos_phi, sin_phi, cos_theta;
/* match pdf for small g */
diff --git a/intern/cycles/kernel/geom/geom.h b/intern/cycles/kernel/geom/geom.h
index c94a5384d1f..493afdc4f62 100644
--- a/intern/cycles/kernel/geom/geom.h
+++ b/intern/cycles/kernel/geom/geom.h
@@ -15,35 +15,14 @@
* limitations under the License.
*/
-/* bottom-most stack entry, indicating the end of traversal */
-#define ENTRYPOINT_SENTINEL 0x76543210
-
-/* 64 object BVH + 64 mesh BVH + 64 object node splitting */
-#define BVH_STACK_SIZE 192
-#define BVH_QSTACK_SIZE 384
-#define BVH_NODE_SIZE 4
-#define BVH_NODE_LEAF_SIZE 1
-#define BVH_QNODE_SIZE 7
-#define BVH_QNODE_LEAF_SIZE 1
-#define TRI_NODE_SIZE 3
-
-/* silly workaround for float extended precision that happens when compiling
- * without sse support on x86, it results in different results for float ops
- * that you would otherwise expect to compare correctly */
-#if !defined(__i386__) || defined(__SSE__)
-# define NO_EXTENDED_PRECISION
-#else
-# define NO_EXTENDED_PRECISION volatile
-#endif
-
#include "geom_attribute.h"
#include "geom_object.h"
#include "geom_triangle.h"
+#include "geom_subd_triangle.h"
#include "geom_triangle_intersect.h"
#include "geom_motion_triangle.h"
#include "geom_motion_curve.h"
#include "geom_curve.h"
#include "geom_volume.h"
#include "geom_primitive.h"
-#include "geom_bvh.h"
diff --git a/intern/cycles/kernel/geom/geom_attribute.h b/intern/cycles/kernel/geom/geom_attribute.h
index c7364e9edac..5d78cf8f9fc 100644
--- a/intern/cycles/kernel/geom/geom_attribute.h
+++ b/intern/cycles/kernel/geom/geom_attribute.h
@@ -25,6 +25,24 @@ CCL_NAMESPACE_BEGIN
* Lookup of attributes is different between OSL and SVM, as OSL is ustring
* based while for SVM we use integer ids. */
+ccl_device_inline uint subd_triangle_patch(KernelGlobals *kg, const ShaderData *sd);
+
+ccl_device_inline uint attribute_primitive_type(KernelGlobals *kg, const ShaderData *sd)
+{
+#ifdef __HAIR__
+ if(ccl_fetch(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;
+ }
+}
+
/* Find attribute based on ID */
ccl_device_inline int find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id, AttributeElement *elem)
@@ -34,9 +52,7 @@ ccl_device_inline int find_attribute(KernelGlobals *kg, const ShaderData *sd, ui
/* for SVM, find attribute by unique id */
uint attr_offset = ccl_fetch(sd, object)*kernel_data.bvh.attributes_map_stride;
-#ifdef __HAIR__
- attr_offset = (ccl_fetch(sd, type) & PRIMITIVE_ALL_CURVE)? attr_offset + ATTR_PRIM_CURVE: attr_offset;
-#endif
+ attr_offset += attribute_primitive_type(kg, sd);
uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
while(attr_map.x != id) {
diff --git a/intern/cycles/kernel/geom/geom_curve.h b/intern/cycles/kernel/geom/geom_curve.h
index 8894843997c..292e1bfca0e 100644
--- a/intern/cycles/kernel/geom/geom_curve.h
+++ b/intern/cycles/kernel/geom/geom_curve.h
@@ -450,8 +450,8 @@ ccl_device_inline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersect
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.*/
+ * 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;
diff --git a/intern/cycles/kernel/geom/geom_motion_triangle.h b/intern/cycles/kernel/geom/geom_motion_triangle.h
index ffe55529110..dabba3fb1f0 100644
--- a/intern/cycles/kernel/geom/geom_motion_triangle.h
+++ b/intern/cycles/kernel/geom/geom_motion_triangle.h
@@ -47,13 +47,13 @@ ccl_device_inline int find_attribute_motion(KernelGlobals *kg, int object, uint
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, float3 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(__tri_verts, __float_as_int(tri_vindex.x)));
- verts[1] = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.y)));
- verts[2] = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.z)));
+ 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 */
@@ -62,19 +62,19 @@ ccl_device_inline void motion_triangle_verts_for_step(KernelGlobals *kg, float3
offset += step*numverts;
- verts[0] = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(tri_vindex.x)));
- verts[1] = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(tri_vindex.y)));
- verts[2] = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(tri_vindex.z)));
+ 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, float3 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, __float_as_int(tri_vindex.x)));
- normals[1] = float4_to_float3(kernel_tex_fetch(__tri_vnormal, __float_as_int(tri_vindex.y)));
- normals[2] = float4_to_float3(kernel_tex_fetch(__tri_vnormal, __float_as_int(tri_vindex.z)));
+ 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 not stored in this array */
@@ -83,9 +83,9 @@ ccl_device_inline void motion_triangle_normals_for_step(KernelGlobals *kg, float
offset += step*numverts;
- normals[0] = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(tri_vindex.x)));
- normals[1] = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(tri_vindex.y)));
- normals[2] = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(tri_vindex.z)));
+ 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));
}
}
@@ -107,7 +107,7 @@ ccl_device_inline void motion_triangle_vertices(KernelGlobals *kg, int object, i
/* fetch vertex coordinates */
float3 next_verts[3];
- float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, prim));
+ 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);
@@ -259,7 +259,7 @@ ccl_device_noinline void motion_triangle_shader_setup(KernelGlobals *kg, ShaderD
/* fetch vertex coordinates */
float3 verts[3], next_verts[3];
- float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, ccl_fetch(sd, prim)));
+ uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, ccl_fetch(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);
@@ -387,6 +387,12 @@ ccl_device_inline void motion_triangle_intersect_subsurface(
float t, u, v;
if(ray_triangle_intersect_uv(P, dir, tmax, verts[2], verts[0], verts[1], &u, &v, &t)) {
+ for(int i = min(max_hits, ss_isect->num_hits) - 1; i >= 0; --i) {
+ if(ss_isect->hits[i].t == t) {
+ return;
+ }
+ }
+
ss_isect->num_hits++;
int hit;
diff --git a/intern/cycles/kernel/geom/geom_primitive.h b/intern/cycles/kernel/geom/geom_primitive.h
index b1b1e919e00..44734d1b70d 100644
--- a/intern/cycles/kernel/geom/geom_primitive.h
+++ b/intern/cycles/kernel/geom/geom_primitive.h
@@ -26,7 +26,10 @@ CCL_NAMESPACE_BEGIN
ccl_device float primitive_attribute_float(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float *dx, float *dy)
{
if(ccl_fetch(sd, type) & PRIMITIVE_ALL_TRIANGLE) {
- return triangle_attribute_float(kg, sd, elem, offset, dx, dy);
+ if(subd_triangle_patch(kg, sd) == ~0)
+ return triangle_attribute_float(kg, sd, elem, offset, dx, dy);
+ else
+ return subd_triangle_attribute_float(kg, sd, elem, offset, dx, dy);
}
#ifdef __HAIR__
else if(ccl_fetch(sd, type) & PRIMITIVE_ALL_CURVE) {
@@ -48,7 +51,10 @@ ccl_device float primitive_attribute_float(KernelGlobals *kg, const ShaderData *
ccl_device float3 primitive_attribute_float3(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float3 *dx, float3 *dy)
{
if(ccl_fetch(sd, type) & PRIMITIVE_ALL_TRIANGLE) {
- return triangle_attribute_float3(kg, sd, elem, offset, dx, dy);
+ if(subd_triangle_patch(kg, sd) == ~0)
+ return triangle_attribute_float3(kg, sd, elem, offset, dx, dy);
+ else
+ return subd_triangle_attribute_float3(kg, sd, elem, offset, dx, dy);
}
#ifdef __HAIR__
else if(ccl_fetch(sd, type) & PRIMITIVE_ALL_CURVE) {
diff --git a/intern/cycles/kernel/geom/geom_qbvh.h b/intern/cycles/kernel/geom/geom_qbvh.h
deleted file mode 100644
index 2a2d7822eee..00000000000
--- a/intern/cycles/kernel/geom/geom_qbvh.h
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright 2011-2014, Blender Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-struct QBVHStackItem {
- int addr;
- float dist;
-};
-
-/* TOOD(sergey): Investigate if using intrinsics helps for both
- * stack item swap and float comparison.
- */
-ccl_device_inline void qbvh_item_swap(QBVHStackItem *__restrict a,
- QBVHStackItem *__restrict b)
-{
- QBVHStackItem tmp = *a;
- *a = *b;
- *b = tmp;
-}
-
-ccl_device_inline void qbvh_stack_sort(QBVHStackItem *__restrict s1,
- QBVHStackItem *__restrict s2,
- QBVHStackItem *__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); }
-}
-
-ccl_device_inline void qbvh_stack_sort(QBVHStackItem *__restrict s1,
- QBVHStackItem *__restrict s2,
- QBVHStackItem *__restrict s3,
- QBVHStackItem *__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); }
-}
-
-ccl_device_inline int qbvh_node_intersect(KernelGlobals *__restrict kg,
- const ssef& tnear,
- const ssef& tfar,
-#ifdef __KERNEL_AVX2__
- const sse3f& org_idir,
-#else
- 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 nodeAddr,
- ssef *__restrict dist)
-{
- const int offset = nodeAddr*BVH_QNODE_SIZE;
-#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);
-#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;
-#endif
-
-#ifdef __KERNEL_SSE41__
- const ssef tNear = maxi(maxi(tnear_x, tnear_y), maxi(tnear_z, tnear));
- const ssef tFar = mini(mini(tfar_x, tfar_y), mini(tfar_z, tfar));
- const sseb vmask = cast(tNear) > cast(tFar);
- int mask = (int)movemask(vmask)^0xf;
-#else
- const ssef tNear = max4(tnear_x, tnear_y, tnear_z, tnear);
- const ssef tFar = min4(tfar_x, tfar_y, tfar_z, tfar);
- const sseb vmask = tNear <= tFar;
- int mask = (int)movemask(vmask);
-#endif
- *dist = tNear;
- return mask;
-}
-
-ccl_device_inline int qbvh_node_intersect_robust(KernelGlobals *__restrict kg,
- const ssef& tnear,
- const ssef& tfar,
-#ifdef __KERNEL_AVX2__
- const sse3f& P_idir,
-#else
- 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 nodeAddr,
- const float difl,
- ssef *__restrict dist)
-{
- const int offset = nodeAddr*BVH_QNODE_SIZE;
-#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);
-#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;
-#endif
-
- const float round_down = 1.0f - difl;
- const float round_up = 1.0f + difl;
- const ssef tNear = max4(tnear_x, tnear_y, tnear_z, tnear);
- const ssef tFar = min4(tfar_x, tfar_y, tfar_z, tfar);
- const sseb vmask = round_down*tNear <= round_up*tFar;
- *dist = tNear;
- return (int)movemask(vmask);
-}
diff --git a/intern/cycles/kernel/geom/geom_qbvh_traversal.h b/intern/cycles/kernel/geom/geom_qbvh_traversal.h
deleted file mode 100644
index ce3bbbdf957..00000000000
--- a/intern/cycles/kernel/geom/geom_qbvh_traversal.h
+++ /dev/null
@@ -1,425 +0,0 @@
-/*
- * Adapted from code Copyright 2009-2010 NVIDIA Corporation,
- * and code copyright 2009-2012 Intel Corporation
- *
- * Modifications Copyright 2011-2014, Blender Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/* This is a template BVH traversal function, where various features can be
- * enabled/disabled. This way we can compile optimized versions for each case
- * without new features slowing things down.
- *
- * BVH_INSTANCING: object instancing
- * BVH_HAIR: hair curve rendering
- * BVH_HAIR_MINIMUM_WIDTH: hair curve rendering with minimum width
- * BVH_MOTION: motion blur rendering
- *
- */
-
-ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
- const Ray *ray,
- Intersection *isect,
- const uint visibility
-#if BVH_FEATURE(BVH_HAIR_MINIMUM_WIDTH)
- ,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 traversalStack[BVH_QSTACK_SIZE];
- traversalStack[0].addr = ENTRYPOINT_SENTINEL;
- traversalStack[0].dist = -FLT_MAX;
-
- /* Traversal variables in registers. */
- int stackPtr = 0;
- int nodeAddr = kernel_data.bvh.root;
- float nodeDist = -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;
-#endif
-
-#ifndef __KERNEL_SSE41__
- if(!isfinite(P.x)) {
- return false;
- }
-#endif
-
- isect->t = ray->t;
- isect->u = 0.0f;
- isect->v = 0.0f;
- isect->prim = PRIM_NONE;
- isect->object = OBJECT_NONE;
-
-#if defined(__KERNEL_DEBUG__)
- isect->num_traversal_steps = 0;
- isect->num_traversed_instances = 0;
-#endif
-
- ssef tnear(0.0f), tfar(ray->t);
- 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);
-#else
- sse3f org = 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;
-
- 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; }
-
- IsectPrecalc isect_precalc;
- triangle_intersect_precalc(dir, &isect_precalc);
-
- /* Traversal loop. */
- do {
- do {
- /* Traverse internal nodes. */
- while(nodeAddr >= 0 && nodeAddr != ENTRYPOINT_SENTINEL) {
- if(UNLIKELY(nodeDist > isect->t)) {
- /* Pop. */
- nodeAddr = traversalStack[stackPtr].addr;
- nodeDist = traversalStack[stackPtr].dist;
- --stackPtr;
- continue;
- }
-
- int traverseChild;
- ssef dist;
-
-#if defined(__KERNEL_DEBUG__)
- isect->num_traversal_steps++;
-#endif
-
-#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.
- */
- traverseChild = qbvh_node_intersect_robust(kg,
- tnear,
- tfar,
-# ifdef __KERNEL_AVX2__
- P_idir4,
-# else
- org,
-# endif
- idir4,
- near_x, near_y, near_z,
- far_x, far_y, far_z,
- nodeAddr,
- difl,
- &dist);
- }
- else
-#endif /* BVH_HAIR_MINIMUM_WIDTH */
- {
- traverseChild = qbvh_node_intersect(kg,
- tnear,
- tfar,
-#ifdef __KERNEL_AVX2__
- P_idir4,
-#else
- org,
-#endif
- idir4,
- near_x, near_y, near_z,
- far_x, far_y, far_z,
- nodeAddr,
- &dist);
- }
-
- if(traverseChild != 0) {
- float4 cnodes = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_QNODE_SIZE+6);
-
- /* One child is hit, continue with that child. */
- int r = __bscf(traverseChild);
- float d0 = ((float*)&dist)[r];
- if(traverseChild == 0) {
- nodeAddr = __float_as_int(cnodes[r]);
- nodeDist = d0;
- continue;
- }
-
- /* Two children are hit, push far child, and continue with
- * closer child.
- */
- int c0 = __float_as_int(cnodes[r]);
- r = __bscf(traverseChild);
- int c1 = __float_as_int(cnodes[r]);
- float d1 = ((float*)&dist)[r];
- if(traverseChild == 0) {
- if(d1 < d0) {
- nodeAddr = c1;
- nodeDist = d1;
- ++stackPtr;
- kernel_assert(stackPtr < BVH_QSTACK_SIZE);
- traversalStack[stackPtr].addr = c0;
- traversalStack[stackPtr].dist = d0;
- continue;
- }
- else {
- nodeAddr = c0;
- nodeDist = d0;
- ++stackPtr;
- kernel_assert(stackPtr < BVH_QSTACK_SIZE);
- traversalStack[stackPtr].addr = c1;
- traversalStack[stackPtr].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.
- */
- ++stackPtr;
- kernel_assert(stackPtr < BVH_QSTACK_SIZE);
- traversalStack[stackPtr].addr = c1;
- traversalStack[stackPtr].dist = d1;
- ++stackPtr;
- kernel_assert(stackPtr < BVH_QSTACK_SIZE);
- traversalStack[stackPtr].addr = c0;
- traversalStack[stackPtr].dist = d0;
-
- /* Three children are hit, push all onto stack and sort 3
- * stack items, continue with closest child.
- */
- r = __bscf(traverseChild);
- int c2 = __float_as_int(cnodes[r]);
- float d2 = ((float*)&dist)[r];
- if(traverseChild == 0) {
- ++stackPtr;
- kernel_assert(stackPtr < BVH_QSTACK_SIZE);
- traversalStack[stackPtr].addr = c2;
- traversalStack[stackPtr].dist = d2;
- qbvh_stack_sort(&traversalStack[stackPtr],
- &traversalStack[stackPtr - 1],
- &traversalStack[stackPtr - 2]);
- nodeAddr = traversalStack[stackPtr].addr;
- nodeDist = traversalStack[stackPtr].dist;
- --stackPtr;
- continue;
- }
-
- /* Four children are hit, push all onto stack and sort 4
- * stack items, continue with closest child.
- */
- r = __bscf(traverseChild);
- int c3 = __float_as_int(cnodes[r]);
- float d3 = ((float*)&dist)[r];
- ++stackPtr;
- kernel_assert(stackPtr < BVH_QSTACK_SIZE);
- traversalStack[stackPtr].addr = c3;
- traversalStack[stackPtr].dist = d3;
- ++stackPtr;
- kernel_assert(stackPtr < BVH_QSTACK_SIZE);
- traversalStack[stackPtr].addr = c2;
- traversalStack[stackPtr].dist = d2;
- qbvh_stack_sort(&traversalStack[stackPtr],
- &traversalStack[stackPtr - 1],
- &traversalStack[stackPtr - 2],
- &traversalStack[stackPtr - 3]);
- }
-
- nodeAddr = traversalStack[stackPtr].addr;
- nodeDist = traversalStack[stackPtr].dist;
- --stackPtr;
- }
-
- /* If node is leaf, fetch triangle list. */
- if(nodeAddr < 0) {
- float4 leaf = kernel_tex_fetch(__bvh_leaf_nodes, (-nodeAddr-1)*BVH_QNODE_LEAF_SIZE);
-
-#ifdef __VISIBILITY_FLAG__
- if(UNLIKELY((nodeDist > isect->t) || ((__float_as_uint(leaf.z) & visibility) == 0)))
-#else
- if(UNLIKELY((nodeDist > isect->t)))
-#endif
- {
- /* Pop. */
- nodeAddr = traversalStack[stackPtr].addr;
- nodeDist = traversalStack[stackPtr].dist;
- --stackPtr;
- continue;
- }
-
- int primAddr = __float_as_int(leaf.x);
-
-#if BVH_FEATURE(BVH_INSTANCING)
- if(primAddr >= 0) {
-#endif
- int primAddr2 = __float_as_int(leaf.y);
- const uint type = __float_as_int(leaf.w);
-
- /* Pop. */
- nodeAddr = traversalStack[stackPtr].addr;
- nodeDist = traversalStack[stackPtr].dist;
- --stackPtr;
-
- /* Primitive intersection. */
- switch(type & PRIMITIVE_ALL) {
- case PRIMITIVE_TRIANGLE: {
- for(; primAddr < primAddr2; primAddr++) {
-#if defined(__KERNEL_DEBUG__)
- isect->num_traversal_steps++;
-#endif
- kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
- if(triangle_intersect(kg, &isect_precalc, isect, P, visibility, object, primAddr)) {
- 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(; primAddr < primAddr2; primAddr++) {
-# if defined(__KERNEL_DEBUG__)
- isect->num_traversal_steps++;
-# endif
- kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
- if(motion_triangle_intersect(kg, isect, P, dir, ray->time, visibility, object, primAddr)) {
- 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(; primAddr < primAddr2; primAddr++) {
-# if defined(__KERNEL_DEBUG__)
- isect->num_traversal_steps++;
-# endif
- kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
- bool hit;
- if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
- hit = bvh_cardinal_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, lcg_state, difl, extmax);
- else
- hit = bvh_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, 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, -primAddr-1);
-
-# if BVH_FEATURE(BVH_MOTION)
- qbvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &isect->t, &nodeDist, &ob_itfm);
-# else
- qbvh_instance_push(kg, object, ray, &P, &dir, &idir, &isect->t, &nodeDist);
-# endif
-
- 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; }
- tfar = ssef(isect->t);
- 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);
-# else
- org = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
-# endif
- triangle_intersect_precalc(dir, &isect_precalc);
-
- ++stackPtr;
- kernel_assert(stackPtr < BVH_QSTACK_SIZE);
- traversalStack[stackPtr].addr = ENTRYPOINT_SENTINEL;
- traversalStack[stackPtr].dist = -FLT_MAX;
-
- nodeAddr = kernel_tex_fetch(__object_node, object);
-
-# if defined(__KERNEL_DEBUG__)
- isect->num_traversed_instances++;
-# endif
- }
- }
-#endif /* FEATURE(BVH_INSTANCING) */
- } while(nodeAddr != ENTRYPOINT_SENTINEL);
-
-#if BVH_FEATURE(BVH_INSTANCING)
- if(stackPtr >= 0) {
- kernel_assert(object != OBJECT_NONE);
-
- /* Instance pop. */
-# if BVH_FEATURE(BVH_MOTION)
- bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, &isect->t, &ob_itfm);
-# else
- bvh_instance_pop(kg, object, ray, &P, &dir, &idir, &isect->t);
-# endif
-
- 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; }
- tfar = ssef(isect->t);
- 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);
-# else
- org = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
-# endif
- triangle_intersect_precalc(dir, &isect_precalc);
-
- object = OBJECT_NONE;
- nodeAddr = traversalStack[stackPtr].addr;
- nodeDist = traversalStack[stackPtr].dist;
- --stackPtr;
- }
-#endif /* FEATURE(BVH_INSTANCING) */
- } while(nodeAddr != ENTRYPOINT_SENTINEL);
-
- return (isect->prim != PRIM_NONE);
-}
diff --git a/intern/cycles/kernel/geom/geom_subd_triangle.h b/intern/cycles/kernel/geom/geom_subd_triangle.h
new file mode 100644
index 00000000000..e4597aba56e
--- /dev/null
+++ b/intern/cycles/kernel/geom/geom_subd_triangle.h
@@ -0,0 +1,262 @@
+/*
+ * Copyright 2011-2016 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* Functions for retrieving attributes on triangles produced from subdivision meshes */
+
+CCL_NAMESPACE_BEGIN
+
+/* Patch index for triangle, -1 if not subdivision triangle */
+
+ccl_device_inline uint subd_triangle_patch(KernelGlobals *kg, const ShaderData *sd)
+{
+ return kernel_tex_fetch(__tri_patch, ccl_fetch(sd, prim));
+}
+
+/* UV coords of triangle within patch */
+
+ccl_device_inline void subd_triangle_patch_uv(KernelGlobals *kg, const ShaderData *sd, float2 uv[3])
+{
+ uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, ccl_fetch(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);
+}
+
+/* Vertex indices of patch */
+
+ccl_device_inline uint4 subd_triangle_patch_indices(KernelGlobals *kg, int patch)
+{
+ 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);
+
+ 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);
+}
+
+/* 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;
+}
+
+/* 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);
+ }
+}
+
+/* Reading attributes on various subdivision triangle elements */
+
+ccl_device float subd_triangle_attribute_float(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float *dx, float *dy)
+{
+ int patch = subd_triangle_patch(kg, sd);
+
+ if(elem == ATTR_ELEMENT_FACE) {
+ if(dx) *dx = 0.0f;
+ if(dy) *dy = 0.0f;
+
+ return kernel_tex_fetch(__attributes_float, offset + subd_triangle_patch_face(kg, patch));
+ }
+ else if(elem == ATTR_ELEMENT_VERTEX || elem == ATTR_ELEMENT_VERTEX_MOTION) {
+ float2 uv[3];
+ subd_triangle_patch_uv(kg, sd, uv);
+ uint4 v = subd_triangle_patch_indices(kg, patch);
+
+ float a, b, c;
+
+ float f0 = kernel_tex_fetch(__attributes_float, offset + v.x);
+ float f1 = kernel_tex_fetch(__attributes_float, offset + v.y);
+ float f2 = kernel_tex_fetch(__attributes_float, offset + v.z);
+ float f3 = kernel_tex_fetch(__attributes_float, offset + v.w);
+
+ if(subd_triangle_patch_num_corners(kg, patch) != 4) {
+ f1 = (f1+f0)*0.5f;
+ f3 = (f3+f0)*0.5f;
+ }
+
+ a = mix(mix(f0, f1, uv[0].x), mix(f3, f2, uv[0].x), uv[0].y);
+ b = mix(mix(f0, f1, uv[1].x), mix(f3, f2, uv[1].x), uv[1].y);
+ c = mix(mix(f0, f1, uv[2].x), mix(f3, f2, uv[2].x), uv[2].y);
+
+#ifdef __RAY_DIFFERENTIALS__
+ if(dx) *dx = ccl_fetch(sd, du).dx*a + ccl_fetch(sd, dv).dx*b - (ccl_fetch(sd, du).dx + ccl_fetch(sd, dv).dx)*c;
+ if(dy) *dy = ccl_fetch(sd, du).dy*a + ccl_fetch(sd, dv).dy*b - (ccl_fetch(sd, du).dy + ccl_fetch(sd, dv).dy)*c;
+#endif
+
+ return ccl_fetch(sd, u)*a + ccl_fetch(sd, v)*b + (1.0f - ccl_fetch(sd, u) - ccl_fetch(sd, v))*c;
+ }
+ else if(elem == ATTR_ELEMENT_CORNER) {
+ int corners[4];
+ subd_triangle_patch_corners(kg, patch, corners);
+
+ float2 uv[3];
+ subd_triangle_patch_uv(kg, sd, uv);
+
+ float a, b, c;
+
+ float f0 = kernel_tex_fetch(__attributes_float, corners[0] + offset);
+ float f1 = kernel_tex_fetch(__attributes_float, corners[1] + offset);
+ float f2 = kernel_tex_fetch(__attributes_float, corners[2] + offset);
+ float f3 = kernel_tex_fetch(__attributes_float, corners[3] + offset);
+
+ if(subd_triangle_patch_num_corners(kg, patch) != 4) {
+ f1 = (f1+f0)*0.5f;
+ f3 = (f3+f0)*0.5f;
+ }
+
+ a = mix(mix(f0, f1, uv[0].x), mix(f3, f2, uv[0].x), uv[0].y);
+ b = mix(mix(f0, f1, uv[1].x), mix(f3, f2, uv[1].x), uv[1].y);
+ c = mix(mix(f0, f1, uv[2].x), mix(f3, f2, uv[2].x), uv[2].y);
+
+#ifdef __RAY_DIFFERENTIALS__
+ if(dx) *dx = ccl_fetch(sd, du).dx*a + ccl_fetch(sd, dv).dx*b - (ccl_fetch(sd, du).dx + ccl_fetch(sd, dv).dx)*c;
+ if(dy) *dy = ccl_fetch(sd, du).dy*a + ccl_fetch(sd, dv).dy*b - (ccl_fetch(sd, du).dy + ccl_fetch(sd, dv).dy)*c;
+#endif
+
+ return ccl_fetch(sd, u)*a + ccl_fetch(sd, v)*b + (1.0f - ccl_fetch(sd, u) - ccl_fetch(sd, v))*c;
+ }
+ else {
+ if(dx) *dx = 0.0f;
+ if(dy) *dy = 0.0f;
+
+ return 0.0f;
+ }
+}
+
+ccl_device float3 subd_triangle_attribute_float3(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float3 *dx, float3 *dy)
+{
+ int patch = subd_triangle_patch(kg, sd);
+
+ if(elem == 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, offset + subd_triangle_patch_face(kg, patch)));
+ }
+ else if(elem == ATTR_ELEMENT_VERTEX || elem == ATTR_ELEMENT_VERTEX_MOTION) {
+ float2 uv[3];
+ subd_triangle_patch_uv(kg, sd, uv);
+ uint4 v = subd_triangle_patch_indices(kg, patch);
+
+ float3 a, b, c;
+
+ float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + v.x));
+ float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + v.y));
+ float3 f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + v.z));
+ float3 f3 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + v.w));
+
+ if(subd_triangle_patch_num_corners(kg, patch) != 4) {
+ f1 = (f1+f0)*0.5f;
+ f3 = (f3+f0)*0.5f;
+ }
+
+ a = mix(mix(f0, f1, uv[0].x), mix(f3, f2, uv[0].x), uv[0].y);
+ b = mix(mix(f0, f1, uv[1].x), mix(f3, f2, uv[1].x), uv[1].y);
+ c = mix(mix(f0, f1, uv[2].x), mix(f3, f2, uv[2].x), uv[2].y);
+
+#ifdef __RAY_DIFFERENTIALS__
+ if(dx) *dx = ccl_fetch(sd, du).dx*a + ccl_fetch(sd, dv).dx*b - (ccl_fetch(sd, du).dx + ccl_fetch(sd, dv).dx)*c;
+ if(dy) *dy = ccl_fetch(sd, du).dy*a + ccl_fetch(sd, dv).dy*b - (ccl_fetch(sd, du).dy + ccl_fetch(sd, dv).dy)*c;
+#endif
+
+ return ccl_fetch(sd, u)*a + ccl_fetch(sd, v)*b + (1.0f - ccl_fetch(sd, u) - ccl_fetch(sd, v))*c;
+ }
+ else if(elem == ATTR_ELEMENT_CORNER || elem == ATTR_ELEMENT_CORNER_BYTE) {
+ int corners[4];
+ subd_triangle_patch_corners(kg, patch, corners);
+
+ float2 uv[3];
+ subd_triangle_patch_uv(kg, sd, uv);
+
+ float3 a, b, c;
+ float3 f0, f1, f2, f3;
+
+ if(elem == ATTR_ELEMENT_CORNER) {
+ f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, corners[0] + offset));
+ f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, corners[1] + offset));
+ f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, corners[2] + offset));
+ f3 = float4_to_float3(kernel_tex_fetch(__attributes_float3, corners[3] + offset));
+ }
+ else {
+ f0 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, corners[0] + offset));
+ f1 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, corners[1] + offset));
+ f2 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, corners[2] + offset));
+ f3 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, corners[3] + offset));
+ }
+
+ if(subd_triangle_patch_num_corners(kg, patch) != 4) {
+ f1 = (f1+f0)*0.5f;
+ f3 = (f3+f0)*0.5f;
+ }
+
+ a = mix(mix(f0, f1, uv[0].x), mix(f3, f2, uv[0].x), uv[0].y);
+ b = mix(mix(f0, f1, uv[1].x), mix(f3, f2, uv[1].x), uv[1].y);
+ c = mix(mix(f0, f1, uv[2].x), mix(f3, f2, uv[2].x), uv[2].y);
+
+#ifdef __RAY_DIFFERENTIALS__
+ if(dx) *dx = ccl_fetch(sd, du).dx*a + ccl_fetch(sd, dv).dx*b - (ccl_fetch(sd, du).dx + ccl_fetch(sd, dv).dx)*c;
+ if(dy) *dy = ccl_fetch(sd, du).dy*a + ccl_fetch(sd, dv).dy*b - (ccl_fetch(sd, du).dy + ccl_fetch(sd, dv).dy)*c;
+#endif
+
+ return ccl_fetch(sd, u)*a + ccl_fetch(sd, v)*b + (1.0f - ccl_fetch(sd, u) - ccl_fetch(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);
+ }
+}
+
+CCL_NAMESPACE_END
+
diff --git a/intern/cycles/kernel/geom/geom_triangle.h b/intern/cycles/kernel/geom/geom_triangle.h
index 995dfac5b09..0c2351e1d1b 100644
--- a/intern/cycles/kernel/geom/geom_triangle.h
+++ b/intern/cycles/kernel/geom/geom_triangle.h
@@ -27,12 +27,11 @@ CCL_NAMESPACE_BEGIN
ccl_device_inline float3 triangle_normal(KernelGlobals *kg, ShaderData *sd)
{
/* load triangle vertices */
- float4 tri_vindex = kernel_tex_fetch(__tri_vindex, ccl_fetch(sd, prim));
+ const uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, ccl_fetch(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));
- float3 v0 = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.x)));
- float3 v1 = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.y)));
- float3 v2 = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.z)));
-
/* return normal */
if(ccl_fetch(sd, flag) & SD_NEGATIVE_SCALE_APPLIED)
return normalize(cross(v2 - v0, v1 - v0));
@@ -44,11 +43,10 @@ ccl_device_inline float3 triangle_normal(KernelGlobals *kg, ShaderData *sd)
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 */
- float4 tri_vindex = kernel_tex_fetch(__tri_vindex, prim);
-
- float3 v0 = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.x)));
- float3 v1 = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.y)));
- float3 v2 = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.z)));
+ 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;
@@ -71,11 +69,10 @@ ccl_device_inline void triangle_point_normal(KernelGlobals *kg, int object, int
ccl_device_inline void triangle_vertices(KernelGlobals *kg, int prim, float3 P[3])
{
- float4 tri_vindex = kernel_tex_fetch(__tri_vindex, prim);
-
- P[0] = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.x)));
- P[1] = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.y)));
- P[2] = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.z)));
+ 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 */
@@ -83,11 +80,10 @@ ccl_device_inline void triangle_vertices(KernelGlobals *kg, int prim, float3 P[3
ccl_device_inline float3 triangle_smooth_normal(KernelGlobals *kg, int prim, float u, float v)
{
/* load triangle vertices */
- float4 tri_vindex = kernel_tex_fetch(__tri_vindex, prim);
-
- float3 n0 = float4_to_float3(kernel_tex_fetch(__tri_vnormal, __float_as_int(tri_vindex.x)));
- float3 n1 = float4_to_float3(kernel_tex_fetch(__tri_vnormal, __float_as_int(tri_vindex.y)));
- float3 n2 = float4_to_float3(kernel_tex_fetch(__tri_vnormal, __float_as_int(tri_vindex.z)));
+ 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));
return normalize((1.0f - u - v)*n2 + u*n0 + v*n1);
}
@@ -97,11 +93,10 @@ ccl_device_inline float3 triangle_smooth_normal(KernelGlobals *kg, int prim, flo
ccl_device_inline void triangle_dPdudv(KernelGlobals *kg, int prim, ccl_addr_space float3 *dPdu, ccl_addr_space float3 *dPdv)
{
/* fetch triangle vertex coordinates */
- float4 tri_vindex = kernel_tex_fetch(__tri_vindex, prim);
-
- float3 p0 = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.x)));
- float3 p1 = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.y)));
- float3 p2 = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.z)));
+ 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);
@@ -119,11 +114,11 @@ ccl_device float triangle_attribute_float(KernelGlobals *kg, const ShaderData *s
return kernel_tex_fetch(__attributes_float, offset + ccl_fetch(sd, prim));
}
else if(elem == ATTR_ELEMENT_VERTEX || elem == ATTR_ELEMENT_VERTEX_MOTION) {
- float4 tri_vindex = kernel_tex_fetch(__tri_vindex, ccl_fetch(sd, prim));
+ uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, ccl_fetch(sd, prim));
- float f0 = kernel_tex_fetch(__attributes_float, offset + __float_as_int(tri_vindex.x));
- float f1 = kernel_tex_fetch(__attributes_float, offset + __float_as_int(tri_vindex.y));
- float f2 = kernel_tex_fetch(__attributes_float, offset + __float_as_int(tri_vindex.z));
+ float f0 = kernel_tex_fetch(__attributes_float, offset + tri_vindex.x);
+ float f1 = kernel_tex_fetch(__attributes_float, offset + tri_vindex.y);
+ float f2 = kernel_tex_fetch(__attributes_float, offset + tri_vindex.z);
#ifdef __RAY_DIFFERENTIALS__
if(dx) *dx = ccl_fetch(sd, du).dx*f0 + ccl_fetch(sd, dv).dx*f1 - (ccl_fetch(sd, du).dx + ccl_fetch(sd, dv).dx)*f2;
@@ -162,11 +157,11 @@ ccl_device float3 triangle_attribute_float3(KernelGlobals *kg, const ShaderData
return float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + ccl_fetch(sd, prim)));
}
else if(elem == ATTR_ELEMENT_VERTEX || elem == ATTR_ELEMENT_VERTEX_MOTION) {
- float4 tri_vindex = kernel_tex_fetch(__tri_vindex, ccl_fetch(sd, prim));
+ uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, ccl_fetch(sd, prim));
- float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(tri_vindex.x)));
- float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(tri_vindex.y)));
- float3 f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(tri_vindex.z)));
+ float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + tri_vindex.x));
+ float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + tri_vindex.y));
+ float3 f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + tri_vindex.z));
#ifdef __RAY_DIFFERENTIALS__
if(dx) *dx = ccl_fetch(sd, du).dx*f0 + ccl_fetch(sd, dv).dx*f1 - (ccl_fetch(sd, du).dx + ccl_fetch(sd, dv).dx)*f2;
diff --git a/intern/cycles/kernel/geom/geom_triangle_intersect.h b/intern/cycles/kernel/geom/geom_triangle_intersect.h
index d2957ad5474..dd5328220ab 100644
--- a/intern/cycles/kernel/geom/geom_triangle_intersect.h
+++ b/intern/cycles/kernel/geom/geom_triangle_intersect.h
@@ -106,9 +106,10 @@ ccl_device_inline bool triangle_intersect(KernelGlobals *kg,
const float Sz = isect_precalc->Sz;
/* Calculate vertices relative to ray origin. */
- const float4 tri_a = kernel_tex_fetch(__tri_storage, triAddr*TRI_NODE_SIZE+0),
- tri_b = kernel_tex_fetch(__tri_storage, triAddr*TRI_NODE_SIZE+1),
- tri_c = kernel_tex_fetch(__tri_storage, triAddr*TRI_NODE_SIZE+2);
+ const uint tri_vindex = kernel_tex_fetch(__prim_tri_index, triAddr);
+ 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 float3 A = make_float3(tri_a.x - P.x, tri_a.y - P.y, tri_a.z - P.z);
const float3 B = make_float3(tri_b.x - P.x, tri_b.y - P.y, tri_b.z - P.z);
const float3 C = make_float3(tri_c.x - P.x, tri_c.y - P.y, tri_c.z - P.z);
@@ -159,16 +160,11 @@ ccl_device_inline bool triangle_intersect(KernelGlobals *kg,
if(kernel_tex_fetch(__prim_visibility, triAddr) & visibility)
#endif
{
-#ifdef __KERNEL_GPU__
- float4 a = tri_b - tri_a, b = tri_c - tri_a;
- if(len_squared(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)) == 0.0f)
- {
+#ifdef __KERNEL_CUDA__
+ if(A == B && B == C) {
return false;
}
#endif
-
/* Normalize U, V, W, and T. */
const float inv_det = 1.0f / det;
isect->prim = triAddr;
@@ -207,9 +203,10 @@ ccl_device_inline void triangle_intersect_subsurface(
const float Sz = isect_precalc->Sz;
/* Calculate vertices relative to ray origin. */
- const float4 tri_a = kernel_tex_fetch(__tri_storage, triAddr*TRI_NODE_SIZE+0),
- tri_b = kernel_tex_fetch(__tri_storage, triAddr*TRI_NODE_SIZE+1),
- tri_c = kernel_tex_fetch(__tri_storage, triAddr*TRI_NODE_SIZE+2);
+ const uint tri_vindex = kernel_tex_fetch(__prim_tri_index, triAddr);
+ 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 float3 A = make_float3(tri_a.x - P.x, tri_a.y - P.y, tri_a.z - P.z);
const float3 B = make_float3(tri_b.x - P.x, tri_b.y - P.y, tri_b.z - P.z);
const float3 C = make_float3(tri_c.x - P.x, tri_c.y - P.y, tri_c.z - P.z);
@@ -258,6 +255,13 @@ ccl_device_inline void triangle_intersect_subsurface(
/* Normalize U, V, W, and T. */
const float inv_det = 1.0f / det;
+ const float t = T * inv_det;
+ for(int i = min(max_hits, ss_isect->num_hits) - 1; i >= 0; --i) {
+ if(ss_isect->hits[i].t == t) {
+ return;
+ }
+ }
+
ss_isect->num_hits++;
int hit;
@@ -280,7 +284,7 @@ ccl_device_inline void triangle_intersect_subsurface(
isect->type = PRIMITIVE_TRIANGLE;
isect->u = U * inv_det;
isect->v = V * inv_det;
- isect->t = T * inv_det;
+ isect->t = t;
/* Record geometric normal. */
/* TODO(sergey): Use float4_to_float3() on just an edges. */
@@ -329,17 +333,25 @@ ccl_device_inline float3 triangle_refine(KernelGlobals *kg,
P = P + D*t;
- const float4 tri_a = kernel_tex_fetch(__tri_storage, isect->prim*TRI_NODE_SIZE+0),
- tri_b = kernel_tex_fetch(__tri_storage, isect->prim*TRI_NODE_SIZE+1),
- tri_c = kernel_tex_fetch(__tri_storage, isect->prim*TRI_NODE_SIZE+2);
+ 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 rt = dot(edge2, qvec) / dot(edge1, pvec);
-
- P = P + D*rt;
+ 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__
@@ -386,17 +398,25 @@ ccl_device_inline float3 triangle_refine_subsurface(KernelGlobals *kg,
P = P + D*t;
#ifdef __INTERSECTION_REFINE__
- const float4 tri_a = kernel_tex_fetch(__tri_storage, isect->prim*TRI_NODE_SIZE+0),
- tri_b = kernel_tex_fetch(__tri_storage, isect->prim*TRI_NODE_SIZE+1),
- tri_c = kernel_tex_fetch(__tri_storage, isect->prim*TRI_NODE_SIZE+2);
+ 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 rt = dot(edge2, qvec) / dot(edge1, pvec);
-
- P = P + D*rt;
+ 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) {
diff --git a/intern/cycles/kernel/kernel_accumulate.h b/intern/cycles/kernel/kernel_accumulate.h
index 5f5a3609ded..0e13b22bd2c 100644
--- a/intern/cycles/kernel/kernel_accumulate.h
+++ b/intern/cycles/kernel/kernel_accumulate.h
@@ -50,7 +50,7 @@ ccl_device_inline void bsdf_eval_init(BsdfEval *eval, ClosureType type, float3 v
else
eval->diffuse = value;
#else
- *eval = value;
+ eval->diffuse = value;
#endif
}
@@ -80,7 +80,7 @@ void bsdf_eval_accum(BsdfEval *eval, ClosureType type, float3 value)
else
eval->diffuse += value;
#else
- *eval += value;
+ eval->diffuse += value;
#endif
}
@@ -98,7 +98,7 @@ ccl_device_inline bool bsdf_eval_is_zero(BsdfEval *eval)
else
return is_zero(eval->diffuse);
#else
- return is_zero(*eval);
+ return is_zero(eval->diffuse);
#endif
}
@@ -117,7 +117,7 @@ ccl_device_inline void bsdf_eval_mul(BsdfEval *eval, float3 value)
else
eval->diffuse *= value;
#else
- *eval *= value;
+ eval->diffuse *= value;
#endif
}
@@ -172,7 +172,7 @@ ccl_device_inline void path_radiance_init(PathRadiance *L, int use_light_pass)
else
L->emission = make_float3(0.0f, 0.0f, 0.0f);
#else
- *L = make_float3(0.0f, 0.0f, 0.0f);
+ L->emission = make_float3(0.0f, 0.0f, 0.0f);
#endif
}
@@ -207,7 +207,7 @@ ccl_device_inline void path_radiance_bsdf_bounce(PathRadiance *L, ccl_addr_space
else
*throughput *= bsdf_eval->diffuse*inverse_pdf;
#else
- *throughput *= *bsdf_eval*inverse_pdf;
+ *throughput *= bsdf_eval->diffuse*inverse_pdf;
#endif
}
@@ -225,7 +225,7 @@ ccl_device_inline void path_radiance_accum_emission(PathRadiance *L, float3 thro
else
L->emission += throughput*value;
#else
- *L += throughput*value;
+ L->emission += throughput*value;
#endif
}
@@ -246,7 +246,7 @@ ccl_device_inline void path_radiance_accum_ao(PathRadiance *L, float3 throughput
else
L->emission += throughput*bsdf*ao;
#else
- *L += throughput*bsdf*ao;
+ L->emission += throughput*bsdf*ao;
#endif
}
@@ -277,7 +277,7 @@ ccl_device_inline void path_radiance_accum_light(PathRadiance *L, float3 through
else
L->emission += throughput*bsdf_eval->diffuse*shadow;
#else
- *L += throughput*(*bsdf_eval)*shadow;
+ L->emission += throughput*bsdf_eval->diffuse*shadow;
#endif
}
@@ -295,7 +295,7 @@ ccl_device_inline void path_radiance_accum_background(PathRadiance *L, float3 th
else
L->emission += throughput*value;
#else
- *L += throughput*value;
+ L->emission += throughput*value;
#endif
}
@@ -441,7 +441,7 @@ ccl_device_inline float3 path_radiance_clamp_and_sum(KernelGlobals *kg, PathRadi
else
L_sum = L->emission;
#else
- L_sum = *L;
+ L_sum = L->emission;
#endif
/* Reject invalid value */
@@ -477,7 +477,7 @@ ccl_device_inline void path_radiance_accum_sample(PathRadiance *L, PathRadiance
L->shadow += L_sample->shadow*fac;
L->mist += L_sample->mist*fac;
#else
- *L += *L_sample * fac;
+ L->emission += L_sample->emission * fac;
#endif
}
diff --git a/intern/cycles/kernel/kernel_bake.h b/intern/cycles/kernel/kernel_bake.h
index 77982ee548a..9ee0b09529e 100644
--- a/intern/cycles/kernel/kernel_bake.h
+++ b/intern/cycles/kernel/kernel_bake.h
@@ -30,8 +30,8 @@ ccl_device void compute_light_pass(KernelGlobals *kg, ShaderData *sd, PathRadian
Ray ray;
float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
- /* emission shader data memory used by various functions */
- ShaderData emission_sd;
+ /* 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;
@@ -48,7 +48,7 @@ ccl_device void compute_light_pass(KernelGlobals *kg, ShaderData *sd, PathRadian
/* evaluate surface shader */
float rbsdf = path_state_rng_1D(kg, &rng, &state, PRNG_BSDF);
- shader_eval_surface(kg, sd, &state, rbsdf, state.flag, SHADER_CONTEXT_MAIN);
+ shader_eval_surface(kg, sd, &rng, &state, rbsdf, state.flag, SHADER_CONTEXT_MAIN);
/* TODO, disable the closures we won't need */
@@ -94,6 +94,7 @@ ccl_device void compute_light_pass(KernelGlobals *kg, ShaderData *sd, PathRadian
&L_sample,
&throughput);
kernel_path_indirect(kg,
+ &indirect_sd,
&emission_sd,
&rng,
&ray,
@@ -117,7 +118,7 @@ ccl_device void compute_light_pass(KernelGlobals *kg, ShaderData *sd, PathRadian
state.ray_t = 0.0f;
#endif
/* compute indirect light */
- kernel_path_indirect(kg, &emission_sd, &rng, &ray, throughput, 1, &state, &L_sample);
+ kernel_path_indirect(kg, &indirect_sd, &emission_sd, &rng, &ray, throughput, 1, &state, &L_sample);
/* sum and reset indirect light pass variables for the next samples */
path_radiance_sum_indirect(&L_sample);
@@ -144,7 +145,8 @@ ccl_device void compute_light_pass(KernelGlobals *kg, ShaderData *sd, PathRadian
/* 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, &emission_sd, &L_sample, &state, &rng, &ray, throughput);
+ kernel_branched_path_subsurface_scatter(kg, sd, &indirect_sd,
+ &emission_sd, &L_sample, &state, &rng, &ray, throughput);
}
#endif
@@ -161,7 +163,7 @@ ccl_device void compute_light_pass(KernelGlobals *kg, ShaderData *sd, PathRadian
/* indirect light */
kernel_branched_path_surface_indirect_light(kg, &rng,
- sd, &emission_sd, throughput, 1.0f, &state, &L_sample);
+ sd, &indirect_sd, &emission_sd, throughput, 1.0f, &state, &L_sample);
}
}
#endif
@@ -218,6 +220,7 @@ ccl_device_inline float3 kernel_bake_shader_bsdf(KernelGlobals *kg,
ccl_device float3 kernel_bake_evaluate_direct_indirect(KernelGlobals *kg,
ShaderData *sd,
+ RNG *rng,
PathState *state,
float3 direct,
float3 indirect,
@@ -237,12 +240,12 @@ ccl_device float3 kernel_bake_evaluate_direct_indirect(KernelGlobals *kg,
}
else {
/* surface color of the pass only */
- shader_eval_surface(kg, sd, state, 0.0f, 0, SHADER_CONTEXT_MAIN);
+ shader_eval_surface(kg, sd, rng, state, 0.0f, 0, SHADER_CONTEXT_MAIN);
return kernel_bake_shader_bsdf(kg, sd, type);
}
}
else {
- shader_eval_surface(kg, sd, state, 0.0f, 0, SHADER_CONTEXT_MAIN);
+ shader_eval_surface(kg, sd, rng, state, 0.0f, 0, SHADER_CONTEXT_MAIN);
color = kernel_bake_shader_bsdf(kg, sd, type);
}
@@ -334,7 +337,7 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input,
case SHADER_EVAL_NORMAL:
{
if((sd.flag & SD_HAS_BUMP)) {
- shader_eval_surface(kg, &sd, &state, 0.f, 0, SHADER_CONTEXT_MAIN);
+ shader_eval_surface(kg, &sd, &rng, &state, 0.f, 0, SHADER_CONTEXT_MAIN);
}
/* compression: normal = (2 * color) - 1 */
@@ -348,7 +351,7 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input,
}
case SHADER_EVAL_EMISSION:
{
- shader_eval_surface(kg, &sd, &state, 0.f, 0, SHADER_CONTEXT_EMISSION);
+ shader_eval_surface(kg, &sd, &rng, &state, 0.f, 0, SHADER_CONTEXT_EMISSION);
out = shader_emissive_eval(kg, &sd);
break;
}
@@ -401,6 +404,7 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input,
{
out = kernel_bake_evaluate_direct_indirect(kg,
&sd,
+ &rng,
&state,
L.direct_diffuse,
L.indirect_diffuse,
@@ -412,6 +416,7 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input,
{
out = kernel_bake_evaluate_direct_indirect(kg,
&sd,
+ &rng,
&state,
L.direct_glossy,
L.indirect_glossy,
@@ -423,6 +428,7 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input,
{
out = kernel_bake_evaluate_direct_indirect(kg,
&sd,
+ &rng,
&state,
L.direct_transmission,
L.indirect_transmission,
@@ -435,6 +441,7 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input,
#ifdef __SUBSURFACE__
out = kernel_bake_evaluate_direct_indirect(kg,
&sd,
+ &rng,
&state,
L.direct_subsurface,
L.indirect_subsurface,
@@ -480,12 +487,10 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input,
}
/* write output */
- float output_fac = is_aa_pass(type)? 1.0f/num_samples: 1.0f;
+ const float output_fac = is_aa_pass(type)? 1.0f/num_samples: 1.0f;
+ const float4 scaled_result = make_float4(out.x, out.y, out.z, 1.0f) * output_fac;
- if(sample == 0)
- output[i] = make_float4(out.x, out.y, out.z, 1.0f) * output_fac;
- else
- output[i] += make_float4(out.x, out.y, out.z, 1.0f) * output_fac;
+ output[i] = (sample == 0)? scaled_result: output[i] + scaled_result;
}
#endif /* __BAKING__ */
diff --git a/intern/cycles/kernel/kernel_compat_cpu.h b/intern/cycles/kernel/kernel_compat_cpu.h
index bb303b32705..c882b477c35 100644
--- a/intern/cycles/kernel/kernel_compat_cpu.h
+++ b/intern/cycles/kernel/kernel_compat_cpu.h
@@ -122,6 +122,17 @@ template<typename T> struct texture_image {
return make_float4(r, r, r, 1.0f);
}
+ ccl_always_inline float4 read(half4 r)
+ {
+ return half4_to_float4(r);
+ }
+
+ ccl_always_inline float4 read(half r)
+ {
+ float f = half_to_float(r);
+ return make_float4(f, f, f, 1.0f);
+ }
+
ccl_always_inline int wrap_periodic(int x, int width)
{
x %= width;
@@ -486,8 +497,10 @@ typedef texture<uint4> texture_uint4;
typedef texture<uchar4> texture_uchar4;
typedef texture_image<float> texture_image_float;
typedef texture_image<uchar> texture_image_uchar;
+typedef texture_image<half> texture_image_half;
typedef texture_image<float4> texture_image_float4;
typedef texture_image<uchar4> texture_image_uchar4;
+typedef texture_image<half4> texture_image_half4;
/* Macros to handle different memory storage on different devices */
diff --git a/intern/cycles/kernel/kernel_compat_cuda.h b/intern/cycles/kernel/kernel_compat_cuda.h
index 42314756f02..08f6f457805 100644
--- a/intern/cycles/kernel/kernel_compat_cuda.h
+++ b/intern/cycles/kernel/kernel_compat_cuda.h
@@ -42,6 +42,7 @@
#define ccl_constant
#define ccl_may_alias
#define ccl_addr_space
+#define ccl_restrict __restrict__
/* No assert supported for CUDA */
diff --git a/intern/cycles/kernel/kernel_compat_opencl.h b/intern/cycles/kernel/kernel_compat_opencl.h
index a5708448e23..8505cb85576 100644
--- a/intern/cycles/kernel/kernel_compat_opencl.h
+++ b/intern/cycles/kernel/kernel_compat_opencl.h
@@ -39,6 +39,7 @@
#define ccl_global __global
#define ccl_local __local
#define ccl_private __private
+#define ccl_restrict restrict
#ifdef __SPLIT_KERNEL__
# define ccl_addr_space __global
diff --git a/intern/cycles/kernel/kernel_emission.h b/intern/cycles/kernel/kernel_emission.h
index 4de8e0f698a..149ac3ed4f9 100644
--- a/intern/cycles/kernel/kernel_emission.h
+++ b/intern/cycles/kernel/kernel_emission.h
@@ -57,7 +57,7 @@ ccl_device_noinline float3 direct_emissive_eval(KernelGlobals *kg,
/* no 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, 0.0f, 0, SHADER_CONTEXT_EMISSION);
+ shader_eval_surface(kg, emission_sd, NULL, state, 0.0f, 0, SHADER_CONTEXT_EMISSION);
path_state_modify_bounce(state, false);
/* evaluate emissive closure */
@@ -124,8 +124,10 @@ ccl_device_noinline bool direct_emission(KernelGlobals *kg,
#ifdef __PASSES__
/* use visibility flag to skip lights */
if(ls->shader & SHADER_EXCLUDE_ANY) {
- if(ls->shader & SHADER_EXCLUDE_DIFFUSE)
+ 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)
diff --git a/intern/cycles/kernel/kernel_globals.h b/intern/cycles/kernel/kernel_globals.h
index 7e6cdf93fb9..8e66a3a0340 100644
--- a/intern/cycles/kernel/kernel_globals.h
+++ b/intern/cycles/kernel/kernel_globals.h
@@ -35,10 +35,12 @@ struct Intersection;
struct VolumeStep;
typedef struct KernelGlobals {
- texture_image_uchar4 texture_byte4_images[TEX_NUM_BYTE4_IMAGES_CPU];
- texture_image_float4 texture_float4_images[TEX_NUM_FLOAT4_IMAGES_CPU];
- texture_image_float texture_float_images[TEX_NUM_FLOAT_IMAGES_CPU];
- texture_image_uchar texture_byte_images[TEX_NUM_BYTE_IMAGES_CPU];
+ texture_image_uchar4 texture_byte4_images[TEX_NUM_BYTE4_CPU];
+ texture_image_float4 texture_float4_images[TEX_NUM_FLOAT4_CPU];
+ texture_image_half4 texture_half4_images[TEX_NUM_HALF4_CPU];
+ texture_image_float texture_float_images[TEX_NUM_FLOAT_CPU];
+ texture_image_uchar texture_byte_images[TEX_NUM_BYTE_CPU];
+ texture_image_half texture_half_images[TEX_NUM_HALF_CPU];
# define KERNEL_TEX(type, ttype, name) ttype name;
# define KERNEL_IMAGE_TEX(type, ttype, name)
diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h
index 675eacfc5ee..93c4bd3f7d5 100644
--- a/intern/cycles/kernel/kernel_light.h
+++ b/intern/cycles/kernel/kernel_light.h
@@ -51,8 +51,8 @@ ccl_device float area_light_sample(float3 P,
bool sample_coord)
{
/* In our name system we're using P for the center,
- * which is o in the paper.
- */
+ * which is o in the paper.
+ */
float3 corner = *light_p - axisu * 0.5f - axisv * 0.5f;
float axisu_len, axisv_len;
@@ -291,24 +291,13 @@ ccl_device float background_portal_pdf(KernelGlobals *kg,
}
num_possible++;
- float t = -(dot(P, dir) - dot(lightpos, dir)) / dot(direction, dir);
- if(t <= 1e-4f) {
- /* Either behind the portal or too close. */
- continue;
- }
-
float4 data1 = kernel_tex_fetch(__light_data, (p + kernel_data.integrator.portal_offset)*LIGHT_SIZE + 1);
float4 data2 = kernel_tex_fetch(__light_data, (p + kernel_data.integrator.portal_offset)*LIGHT_SIZE + 2);
float3 axisu = make_float3(data1.y, data1.z, data1.w);
float3 axisv = make_float3(data2.y, data2.z, data2.w);
- float3 hit = P + t*direction;
- float3 inplane = hit - lightpos;
- /* Skip if the the ray doesn't pass through portal. */
- if(fabsf(dot(inplane, axisu) / dot(axisu, axisu)) > 0.5f)
- continue;
- if(fabsf(dot(inplane, axisv) / dot(axisv, axisv)) > 0.5f)
+ if(!ray_quad_intersect(P, direction, 1e-4f, FLT_MAX, lightpos, axisu, axisv, dir, NULL, NULL))
continue;
portal_pdf += area_light_sample(P, &lightpos, axisu, axisv, 0.0f, 0.0f, false);
@@ -729,8 +718,8 @@ ccl_device bool lamp_light_eval(KernelGlobals *kg, int lamp, float3 P, float3 D,
float3 light_P = make_float3(data0.y, data0.z, data0.w);
- if(!ray_quad_intersect(P, D, t,
- light_P, axisu, axisv, &ls->P, &ls->t))
+ if(!ray_quad_intersect(P, D, 0.0f, t,
+ light_P, axisu, axisv, Ng, &ls->P, &ls->t))
{
return false;
}
diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h
index 5527d8aa861..d5b31037723 100644
--- a/intern/cycles/kernel/kernel_path.h
+++ b/intern/cycles/kernel/kernel_path.h
@@ -25,6 +25,7 @@
#include "kernel_camera.h"
#include "geom/geom.h"
+#include "bvh/bvh.h"
#include "kernel_accumulate.h"
#include "kernel_shader.h"
@@ -53,6 +54,7 @@
CCL_NAMESPACE_BEGIN
ccl_device void kernel_path_indirect(KernelGlobals *kg,
+ ShaderData *sd,
ShaderData *emission_sd,
RNG *rng,
Ray *ray,
@@ -61,9 +63,6 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
PathState *state,
PathRadiance *L)
{
- /* shader data memory used for both volumes and surfaces, saves stack space */
- ShaderData sd;
-
/* path iteration */
for(;;) {
/* intersect scene */
@@ -121,12 +120,12 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
VolumeSegment volume_segment;
shader_setup_from_volume(kg,
- &sd,
+ sd,
&volume_ray);
kernel_volume_decoupled_record(kg,
state,
&volume_ray,
- &sd,
+ sd,
&volume_segment,
heterogeneous);
@@ -149,7 +148,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
/* direct light sampling */
kernel_branched_path_volume_connect_light(kg,
rng,
- &sd,
+ sd,
emission_sd,
throughput,
state,
@@ -167,7 +166,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
result = kernel_volume_decoupled_scatter(kg,
state,
&volume_ray,
- &sd,
+ sd,
&throughput,
rphase,
rscatter,
@@ -182,7 +181,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
if(result == VOLUME_PATH_SCATTERED) {
if(kernel_path_volume_bounce(kg,
rng,
- &sd,
+ sd,
&throughput,
state,
L,
@@ -203,14 +202,14 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
{
/* integrate along volume segment with distance sampling */
VolumeIntegrateResult result = kernel_volume_integrate(
- kg, state, &sd, &volume_ray, L, &throughput, rng, heterogeneous);
+ kg, state, sd, &volume_ray, L, &throughput, rng, heterogeneous);
# ifdef __VOLUME_SCATTER__
if(result == VOLUME_PATH_SCATTERED) {
/* direct lighting */
kernel_path_volume_connect_light(kg,
rng,
- &sd,
+ sd,
emission_sd,
throughput,
state,
@@ -219,7 +218,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
/* indirect light bounce */
if(kernel_path_volume_bounce(kg,
rng,
- &sd,
+ sd,
&throughput,
state,
L,
@@ -251,13 +250,13 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
/* setup shading */
shader_setup_from_ray(kg,
- &sd,
+ sd,
&isect,
ray);
float rbsdf = path_state_rng_1D_for_decision(kg, rng, state, PRNG_BSDF);
- shader_eval_surface(kg, &sd, state, rbsdf, state->flag, SHADER_CONTEXT_INDIRECT);
+ shader_eval_surface(kg, sd, rng, state, rbsdf, state->flag, SHADER_CONTEXT_INDIRECT);
#ifdef __BRANCHED_PATH__
- shader_merge_closures(&sd);
+ shader_merge_closures(sd);
#endif
/* blurring of bsdf after bounces, for rays that have a small likelihood
@@ -267,15 +266,15 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
if(blur_pdf < 1.0f) {
float blur_roughness = sqrtf(1.0f - blur_pdf)*0.5f;
- shader_bsdf_blur(kg, &sd, blur_roughness);
+ shader_bsdf_blur(kg, sd, blur_roughness);
}
}
#ifdef __EMISSION__
/* emission */
- if(sd.flag & SD_EMISSION) {
+ if(sd->flag & SD_EMISSION) {
float3 emission = indirect_primitive_emission(kg,
- &sd,
+ sd,
isect.t,
state->flag,
state->ray_pdf);
@@ -305,30 +304,30 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
#ifdef __AO__
/* ambient occlusion */
- if(kernel_data.integrator.use_ambient_occlusion || (sd.flag & SD_AO)) {
+ if(kernel_data.integrator.use_ambient_occlusion || (sd->flag & SD_AO)) {
float bsdf_u, bsdf_v;
path_state_rng_2D(kg, rng, state, PRNG_BSDF_U, &bsdf_u, &bsdf_v);
float ao_factor = kernel_data.background.ao_factor;
float3 ao_N;
- float3 ao_bsdf = shader_bsdf_ao(kg, &sd, ao_factor, &ao_N);
+ float3 ao_bsdf = shader_bsdf_ao(kg, sd, ao_factor, &ao_N);
float3 ao_D;
float ao_pdf;
float3 ao_alpha = make_float3(0.0f, 0.0f, 0.0f);
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) {
+ 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.P = ray_offset(sd->P, sd->Ng);
light_ray.D = ao_D;
light_ray.t = kernel_data.background.ao_distance;
# ifdef __OBJECT_MOTION__
- light_ray.time = sd.time;
+ light_ray.time = sd->time;
# endif
- light_ray.dP = sd.dP;
+ light_ray.dP = sd->dP;
light_ray.dD = differential3_zero();
if(!shadow_blocked(kg, emission_sd, state, &light_ray, &ao_shadow)) {
@@ -346,9 +345,9 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
#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(sd->flag & SD_BSSRDF) {
float bssrdf_probability;
- ShaderClosure *sc = subsurface_scatter_pick_closure(kg, &sd, &bssrdf_probability);
+ ShaderClosure *sc = subsurface_scatter_pick_closure(kg, sd, &bssrdf_probability);
/* modify throughput for picking bssrdf or bsdf */
throughput *= bssrdf_probability;
@@ -364,7 +363,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
PRNG_BSDF_U,
&bssrdf_u, &bssrdf_v);
subsurface_scatter_step(kg,
- &sd,
+ sd,
state,
state->flag,
sc,
@@ -380,7 +379,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
int all = kernel_data.integrator.sample_all_lights_indirect;
kernel_branched_path_surface_connect_light(kg,
rng,
- &sd,
+ sd,
emission_sd,
state,
throughput,
@@ -390,7 +389,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
}
#endif
- if(!kernel_path_surface_bounce(kg, rng, &sd, &throughput, state, L, ray))
+ if(!kernel_path_surface_bounce(kg, rng, sd, &throughput, state, L, ray))
break;
}
}
@@ -793,7 +792,7 @@ ccl_device_inline float4 kernel_path_integrate(KernelGlobals *kg,
/* setup shading */
shader_setup_from_ray(kg, &sd, &isect, &ray);
float rbsdf = path_state_rng_1D_for_decision(kg, rng, &state, PRNG_BSDF);
- shader_eval_surface(kg, &sd, &state, rbsdf, state.flag, SHADER_CONTEXT_MAIN);
+ shader_eval_surface(kg, &sd, rng, &state, rbsdf, state.flag, SHADER_CONTEXT_MAIN);
/* holdout */
#ifdef __HOLDOUT__
diff --git a/intern/cycles/kernel/kernel_path_branched.h b/intern/cycles/kernel/kernel_path_branched.h
index b4dee220aa5..56516967d8f 100644
--- a/intern/cycles/kernel/kernel_path_branched.h
+++ b/intern/cycles/kernel/kernel_path_branched.h
@@ -64,8 +64,8 @@ ccl_device void kernel_branched_path_ao(KernelGlobals *kg,
/* bounce off surface and integrate indirect light */
ccl_device_noinline void kernel_branched_path_surface_indirect_light(KernelGlobals *kg,
- RNG *rng, ShaderData *sd, ShaderData *emission_sd, float3 throughput,
- float num_samples_adjust, PathState *state, PathRadiance *L)
+ RNG *rng, ShaderData *sd, ShaderData *indirect_sd, ShaderData *emission_sd,
+ float3 throughput, float num_samples_adjust, PathState *state, PathRadiance *L)
{
for(int i = 0; i < ccl_fetch(sd, num_closure); i++) {
const ShaderClosure *sc = &ccl_fetch(sd, closure)[i];
@@ -112,6 +112,7 @@ ccl_device_noinline void kernel_branched_path_surface_indirect_light(KernelGloba
}
kernel_path_indirect(kg,
+ indirect_sd,
emission_sd,
rng,
&bsdf_ray,
@@ -131,6 +132,7 @@ ccl_device_noinline void kernel_branched_path_surface_indirect_light(KernelGloba
#ifdef __SUBSURFACE__
ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg,
ShaderData *sd,
+ ShaderData *indirect_sd,
ShaderData *emission_sd,
PathRadiance *L,
PathState *state,
@@ -222,6 +224,7 @@ ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg,
kg,
rng,
&bssrdf_sd,
+ indirect_sd,
emission_sd,
throughput,
num_samples_inv,
@@ -244,8 +247,8 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in
/* shader data memory used for both volumes and surfaces, saves stack space */
ShaderData sd;
- /* shader data used by emission, shadows, volume stacks */
- ShaderData emission_sd;
+ /* shader data used by emission, shadows, volume stacks, indirect path */
+ ShaderData emission_sd, indirect_sd;
PathState state;
path_state_init(kg, &emission_sd, &state, rng, sample, &ray);
@@ -356,6 +359,7 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in
&pray))
{
kernel_path_indirect(kg,
+ &indirect_sd,
&emission_sd,
rng,
&pray,
@@ -413,6 +417,7 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in
&pray))
{
kernel_path_indirect(kg,
+ &indirect_sd,
&emission_sd,
rng,
&pray,
@@ -458,7 +463,7 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in
/* setup shading */
shader_setup_from_ray(kg, &sd, &isect, &ray);
- shader_eval_surface(kg, &sd, &state, 0.0f, state.flag, SHADER_CONTEXT_MAIN);
+ shader_eval_surface(kg, &sd, rng, &state, 0.0f, state.flag, SHADER_CONTEXT_MAIN);
shader_merge_closures(&sd);
/* holdout */
@@ -522,8 +527,8 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in
#ifdef __SUBSURFACE__
/* bssrdf scatter to a different location on the same object */
if(sd.flag & SD_BSSRDF) {
- kernel_branched_path_subsurface_scatter(kg, &sd, &emission_sd, &L, &state,
- rng, &ray, throughput);
+ kernel_branched_path_subsurface_scatter(kg, &sd, &indirect_sd, &emission_sd,
+ &L, &state, rng, &ray, throughput);
}
#endif
@@ -541,7 +546,7 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in
/* indirect light */
kernel_branched_path_surface_indirect_light(kg, rng,
- &sd, &emission_sd, throughput, 1.0f, &hit_state, &L);
+ &sd, &indirect_sd, &emission_sd, throughput, 1.0f, &hit_state, &L);
/* continue in case of transparency */
throughput *= shader_bsdf_transparency(kg, &sd);
diff --git a/intern/cycles/kernel/kernel_random.h b/intern/cycles/kernel/kernel_random.h
index 631a2cb75de..731dc0407c5 100644
--- a/intern/cycles/kernel/kernel_random.h
+++ b/intern/cycles/kernel/kernel_random.h
@@ -314,5 +314,21 @@ ccl_device_inline uint lcg_state_init(RNG *rng, const PathState *state, uint scr
return lcg_init(*rng + state->rng_offset + state->sample*scramble);
}
+/* TODO(sergey): For until we can use generic address space from OpenCL 2.0. */
+
+ccl_device_inline uint lcg_state_init_addrspace(ccl_addr_space RNG *rng,
+ const ccl_addr_space PathState *state,
+ uint scramble)
+{
+ return lcg_init(*rng + 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);
+}
+
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h
index a0b56118ab7..b7641c37d93 100644
--- a/intern/cycles/kernel/kernel_shader.h
+++ b/intern/cycles/kernel/kernel_shader.h
@@ -24,6 +24,7 @@
*
*/
+#include "closure/alloc.h"
#include "closure/bsdf_util.h"
#include "closure/bsdf.h"
#include "closure/emissive.h"
@@ -453,21 +454,11 @@ ccl_device void shader_merge_closures(ShaderData *sd)
for(int j = i + 1; j < sd->num_closure; j++) {
ShaderClosure *scj = &sd->closure[j];
-#ifdef __OSL__
- if(sci->prim || scj->prim)
+ if(sci->type != scj->type)
continue;
-#endif
-
- if(!(sci->type == scj->type && sci->data0 == scj->data0 && sci->data1 == scj->data1 && sci->data2 == scj->data2))
+ if(!bsdf_merge(sci, scj))
continue;
- if(CLOSURE_IS_BSDF_OR_BSSRDF(sci->type)) {
- if(sci->N != scj->N)
- continue;
- else if(CLOSURE_IS_BSDF_ANISOTROPIC(sci->type) && sci->T != scj->T)
- continue;
- }
-
sci->weight += scj->weight;
sci->sample_weight += scj->sample_weight;
@@ -488,7 +479,7 @@ ccl_device void shader_merge_closures(ShaderData *sd)
/* BSDF */
-ccl_device_inline void _shader_bsdf_multi_eval(KernelGlobals *kg, const ShaderData *sd, const float3 omega_in, float *pdf,
+ccl_device_inline void _shader_bsdf_multi_eval(KernelGlobals *kg, ShaderData *sd, const float3 omega_in, float *pdf,
int skip_bsdf, BsdfEval *result_eval, float sum_pdf, float sum_sample_weight)
{
/* this is the veach one-sample model with balance heuristic, some pdf
@@ -517,7 +508,7 @@ ccl_device_inline void _shader_bsdf_multi_eval(KernelGlobals *kg, const ShaderDa
#ifdef __BRANCHED_PATH__
ccl_device_inline void _shader_bsdf_multi_eval_branched(KernelGlobals *kg,
- const ShaderData *sd,
+ ShaderData *sd,
const float3 omega_in,
BsdfEval *result_eval,
float light_pdf,
@@ -563,7 +554,7 @@ ccl_device void shader_bsdf_eval(KernelGlobals *kg,
}
}
-ccl_device int shader_bsdf_sample(KernelGlobals *kg, const ShaderData *sd,
+ccl_device int shader_bsdf_sample(KernelGlobals *kg, ShaderData *sd,
float randu, float randv, BsdfEval *bsdf_eval,
float3 *omega_in, differential3 *domega_in, float *pdf)
{
@@ -620,7 +611,7 @@ ccl_device int shader_bsdf_sample(KernelGlobals *kg, const ShaderData *sd,
return label;
}
-ccl_device int shader_bsdf_sample_closure(KernelGlobals *kg, const ShaderData *sd,
+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)
{
@@ -738,8 +729,9 @@ ccl_device float3 shader_bsdf_ao(KernelGlobals *kg, ShaderData *sd, float ao_fac
ShaderClosure *sc = ccl_fetch_array(sd, closure, i);
if(CLOSURE_IS_BSDF_DIFFUSE(sc->type)) {
+ const DiffuseBsdf *bsdf = (const DiffuseBsdf*)sc;
eval += sc->weight*ao_factor;
- N += sc->N*average(sc->weight);
+ N += bsdf->N*average(sc->weight);
}
else if(CLOSURE_IS_AMBIENT_OCCLUSION(sc->type)) {
eval += sc->weight;
@@ -756,6 +748,7 @@ ccl_device float3 shader_bsdf_ao(KernelGlobals *kg, ShaderData *sd, float ao_fac
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);
@@ -766,11 +759,12 @@ ccl_device float3 shader_bssrdf_sum(ShaderData *sd, float3 *N_, float *texture_b
ShaderClosure *sc = ccl_fetch_array(sd, closure, i);
if(CLOSURE_IS_BSSRDF(sc->type)) {
+ const Bssrdf *bssrdf = (const Bssrdf*)sc;
float avg_weight = fabsf(average(sc->weight));
- N += sc->N*avg_weight;
+ N += bssrdf->N*avg_weight;
eval += sc->weight;
- texture_blur += sc->data1*avg_weight;
+ texture_blur += bssrdf->texture_blur*avg_weight;
weight_sum += avg_weight;
}
}
@@ -783,6 +777,7 @@ ccl_device float3 shader_bssrdf_sum(ShaderData *sd, float3 *N_, float *texture_b
return eval;
}
+#endif
/* Emission */
@@ -824,10 +819,11 @@ ccl_device float3 shader_holdout_eval(KernelGlobals *kg, ShaderData *sd)
/* Surface Evaluation */
-ccl_device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd,
+ccl_device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd, ccl_addr_space RNG *rng,
ccl_addr_space PathState *state, float randb, int path_flag, ShaderContext ctx)
{
ccl_fetch(sd, num_closure) = 0;
+ ccl_fetch(sd, num_closure_extra) = 0;
ccl_fetch(sd, randb_closure) = randb;
#ifdef __OSL__
@@ -846,6 +842,10 @@ ccl_device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd,
ccl_fetch(sd, flag) |= bsdf_diffuse_setup(ccl_fetch_array(sd, closure, 0));
#endif
}
+
+ if(rng && (ccl_fetch(sd, flag) & SD_BSDF_NEEDS_LCG)) {
+ ccl_fetch(sd, lcg_state) = lcg_state_init_addrspace(rng, state, 0xb4bc3953);
+ }
}
/* Background Evaluation */
@@ -854,33 +854,33 @@ ccl_device float3 shader_eval_background(KernelGlobals *kg, ShaderData *sd,
ccl_addr_space PathState *state, int path_flag, ShaderContext ctx)
{
ccl_fetch(sd, num_closure) = 0;
+ ccl_fetch(sd, num_closure_extra) = 0;
ccl_fetch(sd, randb_closure) = 0.0f;
+#ifdef __SVM__
#ifdef __OSL__
if(kg->osl) {
- return OSLShader::eval_background(kg, sd, state, path_flag, ctx);
+ OSLShader::eval_background(kg, sd, state, path_flag, ctx);
}
else
#endif
-
{
-#ifdef __SVM__
svm_eval_nodes(kg, sd, state, SHADER_TYPE_SURFACE, path_flag);
+ }
- 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 < ccl_fetch(sd, num_closure); i++) {
- const ShaderClosure *sc = ccl_fetch_array(sd, closure, i);
+ for(int i = 0; i < ccl_fetch(sd, num_closure); i++) {
+ const ShaderClosure *sc = ccl_fetch_array(sd, closure, i);
- if(CLOSURE_IS_BACKGROUND(sc->type))
- eval += sc->weight;
- }
+ if(CLOSURE_IS_BACKGROUND(sc->type))
+ eval += sc->weight;
+ }
- return eval;
+ return eval;
#else
- return make_float3(0.8f, 0.8f, 0.8f);
+ return make_float3(0.8f, 0.8f, 0.8f);
#endif
- }
}
/* Volume */
@@ -997,6 +997,7 @@ ccl_device void shader_eval_volume(KernelGlobals *kg, ShaderData *sd,
/* 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_extra = 0;
sd->flag = 0;
for(int i = 0; stack[i].shader != SHADER_NONE; i++) {
@@ -1044,6 +1045,7 @@ ccl_device void shader_eval_volume(KernelGlobals *kg, ShaderData *sd,
ccl_device void shader_eval_displacement(KernelGlobals *kg, ShaderData *sd, ccl_addr_space PathState *state, ShaderContext ctx)
{
ccl_fetch(sd, num_closure) = 0;
+ ccl_fetch(sd, num_closure_extra) = 0;
ccl_fetch(sd, randb_closure) = 0.0f;
/* this will modify sd->P */
diff --git a/intern/cycles/kernel/kernel_shadow.h b/intern/cycles/kernel/kernel_shadow.h
index 1abbbb2ddad..db2fc84834a 100644
--- a/intern/cycles/kernel/kernel_shadow.h
+++ b/intern/cycles/kernel/kernel_shadow.h
@@ -117,7 +117,7 @@ ccl_device_inline bool shadow_blocked(KernelGlobals *kg, ShaderData *shadow_sd,
/* 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, 0.0f, PATH_RAY_SHADOW, SHADER_CONTEXT_SHADOW);
+ shader_eval_surface(kg, shadow_sd, NULL, state, 0.0f, PATH_RAY_SHADOW, SHADER_CONTEXT_SHADOW);
path_state_modify_bounce(state, false);
throughput *= shader_bsdf_transparency(kg, shadow_sd);
@@ -252,7 +252,7 @@ ccl_device_noinline bool shadow_blocked(KernelGlobals *kg,
/* attenuation from transparent surface */
if(!(ccl_fetch(shadow_sd, flag) & SD_HAS_ONLY_VOLUME)) {
path_state_modify_bounce(state, true);
- shader_eval_surface(kg, shadow_sd, state, 0.0f, PATH_RAY_SHADOW, SHADER_CONTEXT_SHADOW);
+ shader_eval_surface(kg, shadow_sd, NULL, state, 0.0f, PATH_RAY_SHADOW, SHADER_CONTEXT_SHADOW);
path_state_modify_bounce(state, false);
throughput *= shader_bsdf_transparency(kg, shadow_sd);
diff --git a/intern/cycles/kernel/kernel_subsurface.h b/intern/cycles/kernel/kernel_subsurface.h
index f64b3472739..888df7f06fd 100644
--- a/intern/cycles/kernel/kernel_subsurface.h
+++ b/intern/cycles/kernel/kernel_subsurface.h
@@ -136,38 +136,42 @@ ccl_device float3 subsurface_scatter_eval(ShaderData *sd, ShaderClosure *sc, flo
}
/* replace closures with a single diffuse bsdf closure after scatter step */
-ccl_device void subsurface_scatter_setup_diffuse_bsdf(ShaderData *sd, float3 weight, bool hit, float3 N)
+ccl_device void subsurface_scatter_setup_diffuse_bsdf(ShaderData *sd, ShaderClosure *sc, float3 weight, bool hit, float3 N)
{
sd->flag &= ~SD_CLOSURE_FLAGS;
sd->randb_closure = 0.0f;
+ sd->num_closure = 0;
+ sd->num_closure_extra = 0;
if(hit) {
- ShaderClosure *sc = &sd->closure[0];
- sd->num_closure = 1;
-
- sc->weight = weight;
- sc->sample_weight = 1.0f;
- sc->N = N;
- if (sc->type == CLOSURE_BSSRDF_DISNEY_ID) {
- sc->data0 = sc->data3;
- sd->flag |= bsdf_disney_diffuse_setup(sc);
-
- /* replace CLOSURE_BSDF_DISNEY_DIFFUSE_ID with this special ID so render passes
- * can recognize it as not being a regular Disney diffuse closure */
- sc->type = CLOSURE_BSDF_BSSRDF_DISNEY_ID;
+ Bssrdf *bssrdf = (Bssrdf *)sc;
+ if (bssrdf->type == CLOSURE_BSSRDF_DISNEY_ID) {
+ DisneyDiffuseBsdf *bsdf = (DisneyDiffuseBsdf*)bsdf_alloc(sd, sizeof(DisneyDiffuseBsdf), weight);
+
+ if (bsdf) {
+ bsdf->N = N;
+ bsdf->roughness = bssrdf->roughness;
+ bsdf->baseColor = bssrdf->baseColor;
+ sd->flag |= bsdf_disney_diffuse_setup(bsdf);
+
+ /* replace CLOSURE_BSDF_DISNEY_DIFFUSE_ID with this special ID so render passes
+ * can recognize it as not being a regular Disney diffuse closure */
+ bsdf->type = CLOSURE_BSDF_BSSRDF_DISNEY_ID;
+ }
}
else {
- sc->data0 = 0.0f;
- sc->data1 = 0.0f;
- sd->flag |= bsdf_diffuse_setup(sc);
+ 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 */
- sc->type = CLOSURE_BSDF_BSSRDF_ID;
+ /* 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;
+ }
}
}
- else
- sd->num_closure = 0;
}
/* optionally do blurring of color and/or bump mapping, at the cost of a shader evaluation */
@@ -208,7 +212,7 @@ ccl_device void subsurface_color_bump_blur(KernelGlobals *kg,
if(bump || texture_blur > 0.0f) {
/* average color and normal at incoming point */
- shader_eval_surface(kg, sd, state, 0.0f, state_flag, SHADER_CONTEXT_SSS);
+ shader_eval_surface(kg, sd, NULL, state, 0.0f, state_flag, SHADER_CONTEXT_SSS);
float3 in_color = shader_bssrdf_sum(sd, (bump)? N: NULL, NULL);
/* we simply divide out the average color and multiply with the average
@@ -377,7 +381,7 @@ ccl_device void subsurface_scatter_multi_setup(KernelGlobals *kg,
subsurface_color_bump_blur(kg, sd, state, state_flag, &weight, &N);
/* Setup diffuse BSDF. */
- subsurface_scatter_setup_diffuse_bsdf(sd, weight, true, N);
+ subsurface_scatter_setup_diffuse_bsdf(sd, sc, weight, true, N);
}
/* subsurface scattering step, from a point on the surface to another nearby point on the same object */
@@ -467,7 +471,7 @@ ccl_device void subsurface_scatter_step(KernelGlobals *kg, ShaderData *sd, PathS
subsurface_color_bump_blur(kg, sd, state, state_flag, &eval, &N);
/* setup diffuse bsdf */
- subsurface_scatter_setup_diffuse_bsdf(sd, eval, (ss_isect.num_hits > 0), N);
+ subsurface_scatter_setup_diffuse_bsdf(sd, sc, eval, (ss_isect.num_hits > 0), N);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernel_textures.h b/intern/cycles/kernel/kernel_textures.h
index 245d236ff97..7d6fec02331 100644
--- a/intern/cycles/kernel/kernel_textures.h
+++ b/intern/cycles/kernel/kernel_textures.h
@@ -25,7 +25,8 @@
/* bvh */
KERNEL_TEX(float4, texture_float4, __bvh_nodes)
KERNEL_TEX(float4, texture_float4, __bvh_leaf_nodes)
-KERNEL_TEX(float4, texture_float4, __tri_storage)
+KERNEL_TEX(float4, texture_float4, __prim_tri_verts)
+KERNEL_TEX(uint, texture_uint, __prim_tri_index)
KERNEL_TEX(uint, texture_uint, __prim_type)
KERNEL_TEX(uint, texture_uint, __prim_visibility)
KERNEL_TEX(uint, texture_uint, __prim_index)
@@ -39,13 +40,17 @@ KERNEL_TEX(float4, texture_float4, __objects_vector)
/* triangles */
KERNEL_TEX(uint, texture_uint, __tri_shader)
KERNEL_TEX(float4, texture_float4, __tri_vnormal)
-KERNEL_TEX(float4, texture_float4, __tri_vindex)
-KERNEL_TEX(float4, texture_float4, __tri_verts)
+KERNEL_TEX(uint4, texture_uint4, __tri_vindex)
+KERNEL_TEX(uint, texture_uint, __tri_patch)
+KERNEL_TEX(float2, texture_float2, __tri_patch_uv)
/* curves */
KERNEL_TEX(float4, texture_float4, __curves)
KERNEL_TEX(float4, texture_float4, __curve_keys)
+/* patches */
+KERNEL_TEX(uint, texture_uint, __patches)
+
/* attributes */
KERNEL_TEX(uint4, texture_uint4, __attributes_map)
KERNEL_TEX(float, texture_float, __attributes_float)
@@ -173,9 +178,6 @@ KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_086)
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_087)
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_088)
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_089)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_090)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_091)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_092)
# else
/* bindless textures */
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index df5e5d803fa..18b5c35c768 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -121,9 +121,7 @@ CCL_NAMESPACE_BEGIN
# define __OBJECT_MOTION__
# define __HAIR__
# define __BAKING__
-# ifdef __KERNEL_EXPERIMENTAL__
-# define __TRANSPARENT_SHADOWS__
-# endif
+# define __TRANSPARENT_SHADOWS__
# endif /* __KERNEL_OPENCL_AMD__ */
# ifdef __KERNEL_OPENCL_INTEL_CPU__
@@ -294,12 +292,14 @@ enum PathRayFlag {
PATH_RAY_CURVE = 512, /* visibility flag to define curve segments */
PATH_RAY_VOLUME_SCATTER = 1024, /* volume scattering */
- /* note that these can use maximum 12 bits, the other are for layers */
- PATH_RAY_ALL_VISIBILITY = (1|2|4|8|16|32|64|128|256|512|1024),
+ /* Special flag to tag unaligned BVH nodes. */
+ PATH_RAY_NODE_UNALIGNED = 2048,
+
+ PATH_RAY_ALL_VISIBILITY = (1|2|4|8|16|32|64|128|256|512|1024|2048),
- PATH_RAY_MIS_SKIP = 2048,
- PATH_RAY_DIFFUSE_ANCESTOR = 4096,
- PATH_RAY_SINGLE_PASS_DONE = 8192,
+ PATH_RAY_MIS_SKIP = 4096,
+ PATH_RAY_DIFFUSE_ANCESTOR = 8192,
+ PATH_RAY_SINGLE_PASS_DONE = 16384,
};
/* Closure Label */
@@ -387,12 +387,13 @@ typedef enum BakePassFilterCombos {
BAKE_FILTER_SUBSURFACE_INDIRECT = (BAKE_FILTER_INDIRECT | BAKE_FILTER_SUBSURFACE),
} BakePassFilterCombos;
-#ifdef __PASSES__
-
typedef ccl_addr_space struct PathRadiance {
+#ifdef __PASSES__
int use_light_pass;
+#endif
float3 emission;
+#ifdef __PASSES__
float3 background;
float3 ao;
@@ -426,25 +427,23 @@ typedef ccl_addr_space struct PathRadiance {
float4 shadow;
float mist;
+#endif
} PathRadiance;
typedef struct BsdfEval {
+#ifdef __PASSES__
int use_light_pass;
+#endif
float3 diffuse;
+#ifdef __PASSES__
float3 glossy;
float3 transmission;
float3 transparent;
float3 subsurface;
float3 scatter;
-} BsdfEval;
-
-#else
-
-typedef ccl_addr_space float3 PathRadiance;
-typedef float3 BsdfEval;
-
#endif
+} BsdfEval;
/* Shader Flag */
@@ -574,8 +573,13 @@ typedef enum PrimitiveType {
/* Attributes */
-#define ATTR_PRIM_TYPES 2
-#define ATTR_PRIM_CURVE 1
+typedef enum AttributePrimitive {
+ ATTR_PRIM_TRIANGLE = 0,
+ ATTR_PRIM_CURVE,
+ ATTR_PRIM_SUBD,
+
+ ATTR_PRIM_TYPES
+} AttributePrimitive;
typedef enum AttributeElement {
ATTR_ELEMENT_NONE,
@@ -632,37 +636,30 @@ typedef enum AttributeStandard {
# define MAX_CLOSURE 1
#endif
-/* This struct is to be 16 bytes aligned, we also keep some extra precautions:
- * - All the float3 members are in the beginning of the struct, so compiler
- * does not put own padding trying to align this members.
- * - We make sure OSL pointer is also 16 bytes aligned.
- */
+/* This struct is the base class for all closures. The common members are
+ * duplicated in all derived classes since we don't have C++ in the kernel
+ * yet, and because it lets us lay out the members to minimize padding. The
+ * weight member is located at the beginning of the struct for this reason.
+ *
+ * ShaderClosure has a fixed size, and any extra space must be allocated
+ * with closure_alloc_extra().
+ *
+ * float3 is 12 bytes on CUDA and 16 bytes on CPU/OpenCL, we set the data
+ * size to ensure ShaderClosure is 80 bytes total everywhere. */
+
+#define SHADER_CLOSURE_BASE \
+ float3 weight; \
+ ClosureType type; \
+ float sample_weight \
+
typedef ccl_addr_space struct ShaderClosure {
- float3 weight;
- float3 N;
- float3 T;
-
- float3 color0;
-
- ClosureType type;
- float sample_weight;
- float data0;
- float data1;
- float data2;
- float data3;
- float data4;
-
- /* Following fields could be used to store pre-calculated
- * values by various BSDF closures for more effective sampling
- * and evaluation.
- */
- float custom1;
- float custom2;
- float custom3;
- float3 custom_color0;
+ SHADER_CLOSURE_BASE;
-#ifdef __OSL__
- void *prim, *pad4;
+ /* pad to 80 bytes, data types are aligned to own size */
+#ifdef __KERNEL_CUDA__
+ float data[15];
+#else
+ float data[14];
#endif
} ShaderClosure;
@@ -687,31 +684,33 @@ typedef enum ShaderContext {
enum ShaderDataFlag {
/* runtime flags */
- SD_BACKFACING = (1 << 0), /* backside of surface? */
- SD_EMISSION = (1 << 1), /* have emissive closure? */
- SD_BSDF = (1 << 2), /* have bsdf closure? */
- SD_BSDF_HAS_EVAL = (1 << 3), /* have non-singular bsdf closure? */
- SD_BSSRDF = (1 << 4), /* have bssrdf */
- SD_HOLDOUT = (1 << 5), /* have holdout closure? */
- SD_ABSORPTION = (1 << 6), /* have volume absorption closure? */
- SD_SCATTER = (1 << 7), /* have volume phase closure? */
- SD_AO = (1 << 8), /* have ao closure? */
- SD_TRANSPARENT = (1 << 9), /* have transparent closure? */
+ SD_BACKFACING = (1 << 0), /* backside of surface? */
+ SD_EMISSION = (1 << 1), /* have emissive closure? */
+ SD_BSDF = (1 << 2), /* have bsdf closure? */
+ SD_BSDF_HAS_EVAL = (1 << 3), /* have non-singular bsdf closure? */
+ SD_BSSRDF = (1 << 4), /* have bssrdf */
+ SD_HOLDOUT = (1 << 5), /* have holdout closure? */
+ SD_ABSORPTION = (1 << 6), /* have volume absorption closure? */
+ SD_SCATTER = (1 << 7), /* have volume phase closure? */
+ SD_AO = (1 << 8), /* have ao closure? */
+ SD_TRANSPARENT = (1 << 9), /* have transparent closure? */
+ SD_BSDF_NEEDS_LCG = (1 << 10),
SD_CLOSURE_FLAGS = (SD_EMISSION|SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSSRDF|
- SD_HOLDOUT|SD_ABSORPTION|SD_SCATTER|SD_AO),
+ SD_HOLDOUT|SD_ABSORPTION|SD_SCATTER|SD_AO|
+ SD_BSDF_NEEDS_LCG),
/* shader flags */
- SD_USE_MIS = (1 << 10), /* direct light sample */
- SD_HAS_TRANSPARENT_SHADOW = (1 << 11), /* has transparent shadow */
- SD_HAS_VOLUME = (1 << 12), /* has volume shader */
- SD_HAS_ONLY_VOLUME = (1 << 13), /* has only volume shader, no surface */
- SD_HETEROGENEOUS_VOLUME = (1 << 14), /* has heterogeneous volume */
- SD_HAS_BSSRDF_BUMP = (1 << 15), /* bssrdf normal uses bump */
- SD_VOLUME_EQUIANGULAR = (1 << 16), /* use equiangular sampling */
- SD_VOLUME_MIS = (1 << 17), /* use multiple importance sampling */
- SD_VOLUME_CUBIC = (1 << 18), /* use cubic interpolation for voxels */
- SD_HAS_BUMP = (1 << 19), /* has data connected to the displacement input */
+ SD_USE_MIS = (1 << 12), /* direct light sample */
+ SD_HAS_TRANSPARENT_SHADOW = (1 << 13), /* has transparent shadow */
+ SD_HAS_VOLUME = (1 << 14), /* has volume shader */
+ SD_HAS_ONLY_VOLUME = (1 << 15), /* has only volume shader, no surface */
+ SD_HETEROGENEOUS_VOLUME = (1 << 16), /* has heterogeneous volume */
+ SD_HAS_BSSRDF_BUMP = (1 << 17), /* bssrdf normal uses bump */
+ SD_VOLUME_EQUIANGULAR = (1 << 18), /* use equiangular sampling */
+ SD_VOLUME_MIS = (1 << 19), /* use multiple importance sampling */
+ SD_VOLUME_CUBIC = (1 << 20), /* use cubic interpolation for voxels */
+ SD_HAS_BUMP = (1 << 21), /* has data connected to the displacement input */
SD_SHADER_FLAGS = (SD_USE_MIS|SD_HAS_TRANSPARENT_SHADOW|SD_HAS_VOLUME|
SD_HAS_ONLY_VOLUME|SD_HETEROGENEOUS_VOLUME|
@@ -719,104 +718,110 @@ enum ShaderDataFlag {
SD_VOLUME_CUBIC|SD_HAS_BUMP),
/* object flags */
- SD_HOLDOUT_MASK = (1 << 20), /* holdout for camera rays */
- SD_OBJECT_MOTION = (1 << 21), /* has object motion blur */
- SD_TRANSFORM_APPLIED = (1 << 22), /* vertices have transform applied */
- SD_NEGATIVE_SCALE_APPLIED = (1 << 23), /* vertices have negative scale applied */
- SD_OBJECT_HAS_VOLUME = (1 << 24), /* object has a volume shader */
- SD_OBJECT_INTERSECTS_VOLUME = (1 << 25), /* object intersects AABB of an object with volume shader */
- SD_OBJECT_HAS_VERTEX_MOTION = (1 << 26), /* has position for motion vertices */
+ SD_HOLDOUT_MASK = (1 << 22), /* holdout for camera rays */
+ SD_OBJECT_MOTION = (1 << 23), /* has object motion blur */
+ SD_TRANSFORM_APPLIED = (1 << 24), /* vertices have transform applied */
+ SD_NEGATIVE_SCALE_APPLIED = (1 << 25), /* vertices have negative scale applied */
+ SD_OBJECT_HAS_VOLUME = (1 << 26), /* object has a volume shader */
+ SD_OBJECT_INTERSECTS_VOLUME = (1 << 27), /* object intersects AABB of an object with volume shader */
+ SD_OBJECT_HAS_VERTEX_MOTION = (1 << 28), /* has position for motion vertices */
SD_OBJECT_FLAGS = (SD_HOLDOUT_MASK|SD_OBJECT_MOTION|SD_TRANSFORM_APPLIED|
SD_NEGATIVE_SCALE_APPLIED|SD_OBJECT_HAS_VOLUME|
SD_OBJECT_INTERSECTS_VOLUME)
};
-struct KernelGlobals;
-
#ifdef __SPLIT_KERNEL__
# define SD_THREAD (get_global_id(1) * get_global_size(0) + get_global_id(0))
# if defined(__SPLIT_KERNEL_AOS__)
/* ShaderData is stored as an Array-of-Structures */
-# define ccl_fetch(s, t) (s[SD_THREAD].t)
-# define ccl_fetch_array(s, t, index) (&s[SD_THREAD].t[index])
+# define ccl_soa_member(type, name) type soa_##name;
+# define ccl_fetch(s, t) (s[SD_THREAD].soa_##t)
+# define ccl_fetch_array(s, t, index) (&s[SD_THREAD].soa_##t[index])
# else
/* ShaderData is stored as an Structure-of-Arrays */
# define SD_GLOBAL_SIZE (get_global_size(0) * get_global_size(1))
# define SD_FIELD_SIZE(t) sizeof(((struct ShaderData*)0)->t)
# define SD_OFFSETOF(t) ((char*)(&((struct ShaderData*)0)->t) - (char*)0)
-# define ccl_fetch(s, t) (((ShaderData*)((ccl_addr_space char*)s + SD_GLOBAL_SIZE * SD_OFFSETOF(t) + SD_FIELD_SIZE(t) * SD_THREAD - SD_OFFSETOF(t)))->t)
+# define ccl_soa_member(type, name) type soa_##name;
+# define ccl_fetch(s, t) (((ShaderData*)((ccl_addr_space char*)s + SD_GLOBAL_SIZE * SD_OFFSETOF(soa_##t) + SD_FIELD_SIZE(soa_##t) * SD_THREAD - SD_OFFSETOF(soa_##t)))->soa_##t)
# define ccl_fetch_array(s, t, index) (&ccl_fetch(s, t)[index])
# endif
#else
+# define ccl_soa_member(type, name) type name
# define ccl_fetch(s, t) (s->t)
# define ccl_fetch_array(s, t, index) (&s->t[index])
#endif
typedef ccl_addr_space struct ShaderData {
/* position */
- float3 P;
+ ccl_soa_member(float3, P);
/* smooth normal for shading */
- float3 N;
+ ccl_soa_member(float3, N);
/* true geometric normal */
- float3 Ng;
+ ccl_soa_member(float3, Ng);
/* view/incoming direction */
- float3 I;
+ ccl_soa_member(float3, I);
/* shader id */
- int shader;
+ ccl_soa_member(int, shader);
/* booleans describing shader, see ShaderDataFlag */
- int flag;
+ ccl_soa_member(int, flag);
/* primitive id if there is one, ~0 otherwise */
- int prim;
+ ccl_soa_member(int, prim);
/* combined type and curve segment for hair */
- int type;
+ ccl_soa_member(int, type);
/* parametric coordinates
- * - barycentric weights for triangles */
- float u;
- float v;
+ * - barycentric weights for triangles */
+ ccl_soa_member(float, u);
+ ccl_soa_member(float, v);
/* object id if there is one, ~0 otherwise */
- int object;
+ ccl_soa_member(int, object);
/* motion blur sample time */
- float time;
+ ccl_soa_member(float, time);
/* length of the ray being shaded */
- float ray_length;
+ ccl_soa_member(float, ray_length);
#ifdef __RAY_DIFFERENTIALS__
/* differential of P. these are orthogonal to Ng, not N */
- differential3 dP;
+ ccl_soa_member(differential3, dP);
/* differential of I */
- differential3 dI;
+ ccl_soa_member(differential3, dI);
/* differential of u, v */
- differential du;
- differential dv;
+ ccl_soa_member(differential, du);
+ ccl_soa_member(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;
+ * not readily suitable as a tangent for shading on triangles. */
+ ccl_soa_member(float3, dPdu);
+ ccl_soa_member(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;
+ * re-interpolating them constantly for shading */
+ ccl_soa_member(Transform, ob_tfm);
+ ccl_soa_member(Transform, ob_itfm);
#endif
/* Closure data, we store a fixed array of closures */
- struct ShaderClosure closure[MAX_CLOSURE];
- int num_closure;
- float randb_closure;
+ ccl_soa_member(struct ShaderClosure, closure[MAX_CLOSURE]);
+ ccl_soa_member(int, num_closure);
+ ccl_soa_member(int, num_closure_extra);
+ ccl_soa_member(float, randb_closure);
+ ccl_soa_member(float3, svm_closure_weight);
+
+ /* LCG state for closures that require additional random numbers. */
+ ccl_soa_member(uint, lcg_state);
/* ray start position, only set for backgrounds */
- float3 ray_P;
- differential3 ray_dP;
+ ccl_soa_member(float3, ray_P);
+ ccl_soa_member(differential3, ray_dP);
#ifdef __OSL__
struct KernelGlobals * osl_globals;
@@ -1173,11 +1178,11 @@ typedef ccl_addr_space struct DebugData {
#define QUEUE_EMPTY_SLOT -1
/*
-* Queue 1 - Active rays
-* Queue 2 - Background queue
-* Queue 3 - Shadow ray cast kernel - AO
-* Queeu 4 - Shadow ray cast kernel - direct lighting
-*/
+ * Queue 1 - Active rays
+ * Queue 2 - Background queue
+ * Queue 3 - Shadow ray cast kernel - AO
+ * Queeu 4 - Shadow ray cast kernel - direct lighting
+ */
#define NUM_QUEUES 4
/* Queue names */
diff --git a/intern/cycles/kernel/kernel_volume.h b/intern/cycles/kernel/kernel_volume.h
index e1ea60f372e..01c87e6d89d 100644
--- a/intern/cycles/kernel/kernel_volume.h
+++ b/intern/cycles/kernel/kernel_volume.h
@@ -276,7 +276,7 @@ ccl_device float kernel_volume_distance_sample(float max_t, float3 sigma_t, int
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 = (sigma_t * *transmittance)/(make_float3(1.0f, 1.0f, 1.0f) - full_transmittance);
+ *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
@@ -290,7 +290,7 @@ ccl_device float3 kernel_volume_distance_pdf(float max_t, float3 sigma_t, float
float3 full_transmittance = volume_color_transmittance(sigma_t, max_t);
float3 transmittance = volume_color_transmittance(sigma_t, sample_t);
- return (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 */
@@ -625,11 +625,13 @@ ccl_device void kernel_volume_decoupled_record(KernelGlobals *kg, PathState *sta
const int global_max_steps = kernel_data.integrator.volume_max_steps;
step_size = kernel_data.integrator.volume_step_size;
/* compute exact steps in advance for malloc */
- max_steps = max((int)ceilf(ray->t/step_size), 1);
- if(max_steps > global_max_steps) {
+ if(ray->t > global_max_steps*step_size) {
max_steps = global_max_steps;
step_size = ray->t / (float)max_steps;
}
+ else {
+ max_steps = max((int)ceilf(ray->t/step_size), 1);
+ }
#ifdef __KERNEL_CPU__
/* NOTE: For the branched path tracing it's possible to have direct
* and indirect light integration both having volume segments allocated.
@@ -1027,7 +1029,7 @@ ccl_device void kernel_volume_stack_init(KernelGlobals *kg,
int stack_index = 0, enclosed_index = 0;
#ifdef __VOLUME_RECORD_ALL__
- Intersection hits[2*VOLUME_STACK_SIZE];
+ Intersection hits[2*VOLUME_STACK_SIZE + 1];
uint num_hits = scene_intersect_volume_all(kg,
&volume_ray,
hits,
@@ -1197,7 +1199,7 @@ ccl_device void kernel_volume_stack_update_for_subsurface(KernelGlobals *kg,
Ray volume_ray = *ray;
# ifdef __VOLUME_RECORD_ALL__
- Intersection hits[2*VOLUME_STACK_SIZE];
+ Intersection hits[2*VOLUME_STACK_SIZE + 1];
uint num_hits = scene_intersect_volume_all(kg,
&volume_ray,
hits,
@@ -1216,6 +1218,7 @@ ccl_device void kernel_volume_stack_update_for_subsurface(KernelGlobals *kg,
# 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,
@@ -1227,7 +1230,9 @@ ccl_device void kernel_volume_stack_update_for_subsurface(KernelGlobals *kg,
/* Move ray forward. */
volume_ray.P = ray_offset(stack_sd->P, -stack_sd->Ng);
- volume_ray.t -= stack_sd->ray_length;
+ if(volume_ray.t != FLT_MAX) {
+ volume_ray.D = normalize_len(Pend - volume_ray.P, &volume_ray.t);
+ }
++step;
}
# endif
diff --git a/intern/cycles/kernel/kernels/cpu/kernel.cpp b/intern/cycles/kernel/kernels/cpu/kernel.cpp
index 365ce891354..f11c85d5f6a 100644
--- a/intern/cycles/kernel/kernels/cpu/kernel.cpp
+++ b/intern/cycles/kernel/kernels/cpu/kernel.cpp
@@ -95,7 +95,7 @@ void kernel_tex_copy(KernelGlobals *kg,
int id = atoi(name + strlen("__tex_image_float4_"));
int array_index = id;
- if(array_index >= 0 && array_index < TEX_NUM_FLOAT4_IMAGES_CPU) {
+ if(array_index >= 0 && array_index < TEX_NUM_FLOAT4_CPU) {
tex = &kg->texture_float4_images[array_index];
}
@@ -109,9 +109,9 @@ void kernel_tex_copy(KernelGlobals *kg,
else if(strstr(name, "__tex_image_float")) {
texture_image_float *tex = NULL;
int id = atoi(name + strlen("__tex_image_float_"));
- int array_index = id - TEX_IMAGE_FLOAT_START_CPU;
+ int array_index = id - TEX_START_FLOAT_CPU;
- if(array_index >= 0 && array_index < TEX_NUM_FLOAT_IMAGES_CPU) {
+ if(array_index >= 0 && array_index < TEX_NUM_FLOAT_CPU) {
tex = &kg->texture_float_images[array_index];
}
@@ -125,9 +125,9 @@ void kernel_tex_copy(KernelGlobals *kg,
else if(strstr(name, "__tex_image_byte4")) {
texture_image_uchar4 *tex = NULL;
int id = atoi(name + strlen("__tex_image_byte4_"));
- int array_index = id - TEX_IMAGE_BYTE4_START_CPU;
+ int array_index = id - TEX_START_BYTE4_CPU;
- if(array_index >= 0 && array_index < TEX_NUM_BYTE4_IMAGES_CPU) {
+ if(array_index >= 0 && array_index < TEX_NUM_BYTE4_CPU) {
tex = &kg->texture_byte4_images[array_index];
}
@@ -141,9 +141,9 @@ void kernel_tex_copy(KernelGlobals *kg,
else if(strstr(name, "__tex_image_byte")) {
texture_image_uchar *tex = NULL;
int id = atoi(name + strlen("__tex_image_byte_"));
- int array_index = id - TEX_IMAGE_BYTE_START_CPU;
+ int array_index = id - TEX_START_BYTE_CPU;
- if(array_index >= 0 && array_index < TEX_NUM_BYTE_IMAGES_CPU) {
+ if(array_index >= 0 && array_index < TEX_NUM_BYTE_CPU) {
tex = &kg->texture_byte_images[array_index];
}
@@ -154,6 +154,38 @@ void kernel_tex_copy(KernelGlobals *kg,
tex->extension = extension;
}
}
+ else if(strstr(name, "__tex_image_half4")) {
+ texture_image_half4 *tex = NULL;
+ int id = atoi(name + strlen("__tex_image_half4_"));
+ int array_index = id - TEX_START_HALF4_CPU;
+
+ if(array_index >= 0 && array_index < TEX_NUM_HALF4_CPU) {
+ tex = &kg->texture_half4_images[array_index];
+ }
+
+ if(tex) {
+ tex->data = (half4*)mem;
+ tex->dimensions_set(width, height, depth);
+ tex->interpolation = interpolation;
+ tex->extension = extension;
+ }
+ }
+ else if(strstr(name, "__tex_image_half")) {
+ texture_image_half *tex = NULL;
+ int id = atoi(name + strlen("__tex_image_half_"));
+ int array_index = id - TEX_START_HALF_CPU;
+
+ if(array_index >= 0 && array_index < TEX_NUM_HALF_CPU) {
+ tex = &kg->texture_half_images[array_index];
+ }
+
+ if(tex) {
+ tex->data = (half*)mem;
+ tex->dimensions_set(width, height, depth);
+ tex->interpolation = interpolation;
+ tex->extension = extension;
+ }
+ }
else
assert(0);
}
diff --git a/intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h b/intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h
index 4807f96a0df..47383140170 100644
--- a/intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h
+++ b/intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h
@@ -23,24 +23,32 @@ CCL_NAMESPACE_BEGIN
ccl_device float4 kernel_tex_image_interp_impl(KernelGlobals *kg, int tex, float x, float y)
{
- if(tex >= TEX_IMAGE_BYTE_START_CPU)
- return kg->texture_byte_images[tex - TEX_IMAGE_BYTE_START_CPU].interp(x, y);
- else if(tex >= TEX_IMAGE_FLOAT_START_CPU)
- return kg->texture_float_images[tex - TEX_IMAGE_FLOAT_START_CPU].interp(x, y);
- else if(tex >= TEX_IMAGE_BYTE4_START_CPU)
- return kg->texture_byte4_images[tex - TEX_IMAGE_BYTE4_START_CPU].interp(x, y);
+ if(tex >= TEX_START_HALF_CPU)
+ return kg->texture_half_images[tex - TEX_START_HALF_CPU].interp(x, y);
+ else if(tex >= TEX_START_HALF4_CPU)
+ return kg->texture_half4_images[tex - TEX_START_HALF4_CPU].interp(x, y);
+ else if(tex >= TEX_START_BYTE_CPU)
+ return kg->texture_byte_images[tex - TEX_START_BYTE_CPU].interp(x, y);
+ else if(tex >= TEX_START_FLOAT_CPU)
+ return kg->texture_float_images[tex - TEX_START_FLOAT_CPU].interp(x, y);
+ else if(tex >= TEX_START_BYTE4_CPU)
+ return kg->texture_byte4_images[tex - TEX_START_BYTE4_CPU].interp(x, y);
else
return kg->texture_float4_images[tex].interp(x, y);
}
ccl_device float4 kernel_tex_image_interp_3d_impl(KernelGlobals *kg, int tex, float x, float y, float z)
{
- if(tex >= TEX_IMAGE_BYTE_START_CPU)
- return kg->texture_byte_images[tex - TEX_IMAGE_BYTE_START_CPU].interp_3d(x, y, z);
- else if(tex >= TEX_IMAGE_FLOAT_START_CPU)
- return kg->texture_float_images[tex - TEX_IMAGE_FLOAT_START_CPU].interp_3d(x, y, z);
- else if(tex >= TEX_IMAGE_BYTE4_START_CPU)
- return kg->texture_byte4_images[tex - TEX_IMAGE_BYTE4_START_CPU].interp_3d(x, y, z);
+ if(tex >= TEX_START_HALF_CPU)
+ return kg->texture_half_images[tex - TEX_START_HALF_CPU].interp_3d(x, y, z);
+ else if(tex >= TEX_START_HALF4_CPU)
+ return kg->texture_half4_images[tex - TEX_START_HALF4_CPU].interp_3d(x, y, z);
+ else if(tex >= TEX_START_BYTE_CPU)
+ return kg->texture_byte_images[tex - TEX_START_BYTE_CPU].interp_3d(x, y, z);
+ else if(tex >= TEX_START_FLOAT_CPU)
+ return kg->texture_float_images[tex - TEX_START_FLOAT_CPU].interp_3d(x, y, z);
+ else if(tex >= TEX_START_BYTE4_CPU)
+ return kg->texture_byte4_images[tex - TEX_START_BYTE4_CPU].interp_3d(x, y, z);
else
return kg->texture_float4_images[tex].interp_3d(x, y, z);
@@ -48,12 +56,16 @@ ccl_device float4 kernel_tex_image_interp_3d_impl(KernelGlobals *kg, int tex, fl
ccl_device float4 kernel_tex_image_interp_3d_ex_impl(KernelGlobals *kg, int tex, float x, float y, float z, int interpolation)
{
- if(tex >= TEX_IMAGE_BYTE_START_CPU)
- return kg->texture_byte_images[tex - TEX_IMAGE_BYTE_START_CPU].interp_3d_ex(x, y, z, interpolation);
- else if(tex >= TEX_IMAGE_FLOAT_START_CPU)
- return kg->texture_float_images[tex - TEX_IMAGE_FLOAT_START_CPU].interp_3d_ex(x, y, z, interpolation);
- else if(tex >= TEX_IMAGE_BYTE4_START_CPU)
- return kg->texture_byte4_images[tex - TEX_IMAGE_BYTE4_START_CPU].interp_3d_ex(x, y, z, interpolation);
+ if(tex >= TEX_START_HALF_CPU)
+ return kg->texture_half4_images[tex - TEX_START_HALF_CPU].interp_3d_ex(x, y, z, interpolation);
+ else if(tex >= TEX_START_HALF4_CPU)
+ return kg->texture_half_images[tex - TEX_START_HALF4_CPU].interp_3d_ex(x, y, z, interpolation);
+ else if(tex >= TEX_START_BYTE_CPU)
+ return kg->texture_byte_images[tex - TEX_START_BYTE_CPU].interp_3d_ex(x, y, z, interpolation);
+ else if(tex >= TEX_START_FLOAT_CPU)
+ return kg->texture_float_images[tex - TEX_START_FLOAT_CPU].interp_3d_ex(x, y, z, interpolation);
+ else if(tex >= TEX_START_BYTE4_CPU)
+ return kg->texture_byte4_images[tex - TEX_START_BYTE4_CPU].interp_3d_ex(x, y, z, interpolation);
else
return kg->texture_float4_images[tex].interp_3d_ex(x, y, z, interpolation);
}
diff --git a/intern/cycles/kernel/kernels/cpu/kernel_cpu_impl.h b/intern/cycles/kernel/kernels/cpu/kernel_cpu_impl.h
index 962196ccbdd..ec82d4b4c22 100644
--- a/intern/cycles/kernel/kernels/cpu/kernel_cpu_impl.h
+++ b/intern/cycles/kernel/kernels/cpu/kernel_cpu_impl.h
@@ -109,6 +109,7 @@ void KERNEL_FUNCTION_FULL_NAME(shader)(KernelGlobals *kg,
{
if(type >= SHADER_EVAL_BAKE) {
kernel_assert(output_luma == NULL);
+#ifdef __BAKING__
kernel_bake_evaluate(kg,
input,
output,
@@ -117,6 +118,7 @@ void KERNEL_FUNCTION_FULL_NAME(shader)(KernelGlobals *kg,
i,
offset,
sample);
+#endif
}
else {
kernel_shader_evaluate(kg,
diff --git a/intern/cycles/kernel/kernels/cuda/kernel.cu b/intern/cycles/kernel/kernels/cuda/kernel.cu
index 37fae54faf0..eb2b6ea5414 100644
--- a/intern/cycles/kernel/kernels/cuda/kernel.cu
+++ b/intern/cycles/kernel/kernels/cuda/kernel.cu
@@ -77,8 +77,8 @@
# define CUDA_KERNEL_MAX_REGISTERS 63
# define CUDA_KERNEL_BRANCHED_MAX_REGISTERS 63
-/* 5.0, 5.2 and 5.3 */
-#elif __CUDA_ARCH__ == 500 || __CUDA_ARCH__ == 520 || __CUDA_ARCH__ == 530
+/* 5.0, 5.2, 5.3, 6.0, 6.1 */
+#elif __CUDA_ARCH__ >= 500
# define CUDA_MULTIPRESSOR_MAX_REGISTERS 65536
# define CUDA_MULTIPROCESSOR_MAX_BLOCKS 32
# define CUDA_BLOCK_MAX_THREADS 1024
@@ -86,7 +86,7 @@
/* tunable parameters */
# define CUDA_THREADS_BLOCK_WIDTH 16
-# define CUDA_KERNEL_MAX_REGISTERS 40
+# define CUDA_KERNEL_MAX_REGISTERS 48
# define CUDA_KERNEL_BRANCHED_MAX_REGISTERS 63
/* unknown architecture */
diff --git a/intern/cycles/kernel/kernels/opencl/kernel.cl b/intern/cycles/kernel/kernels/opencl/kernel.cl
index aad06ed5c76..37907cd8fdc 100644
--- a/intern/cycles/kernel/kernels/opencl/kernel.cl
+++ b/intern/cycles/kernel/kernels/opencl/kernel.cl
@@ -35,6 +35,7 @@
# include "../../kernel_montecarlo.h"
# include "../../kernel_projection.h"
# include "../../geom/geom.h"
+# include "../../bvh/bvh.h"
# include "../../kernel_accumulate.h"
# include "../../kernel_camera.h"
diff --git a/intern/cycles/kernel/osl/CMakeLists.txt b/intern/cycles/kernel/osl/CMakeLists.txt
index 9cf4f2d759a..98de40e5a8a 100644
--- a/intern/cycles/kernel/osl/CMakeLists.txt
+++ b/intern/cycles/kernel/osl/CMakeLists.txt
@@ -25,7 +25,6 @@ set(SRC
)
set(HEADER_SRC
- osl_bssrdf.h
osl_closures.h
osl_globals.h
osl_services.h
diff --git a/intern/cycles/kernel/osl/background.cpp b/intern/cycles/kernel/osl/background.cpp
index 85fa7b34bcc..d835f9be45c 100644
--- a/intern/cycles/kernel/osl/background.cpp
+++ b/intern/cycles/kernel/osl/background.cpp
@@ -36,6 +36,9 @@
#include "osl_closures.h"
+#include "kernel_compat_cpu.h"
+#include "closure/alloc.h"
+
CCL_NAMESPACE_BEGIN
using namespace OSL;
@@ -48,7 +51,10 @@ using namespace OSL;
///
class GenericBackgroundClosure : public CClosurePrimitive {
public:
- GenericBackgroundClosure() : CClosurePrimitive(Background) {}
+ void setup(ShaderData *sd, int /* path_flag */, float3 weight)
+ {
+ closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_BACKGROUND_ID, weight);
+ }
};
/// Holdout closure
@@ -60,7 +66,11 @@ public:
///
class HoldoutClosure : CClosurePrimitive {
public:
- HoldoutClosure () : CClosurePrimitive(Holdout) {}
+ void setup(ShaderData *sd, int /* path_flag */, float3 weight)
+ {
+ closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_HOLDOUT_ID, weight);
+ sd->flag |= SD_HOLDOUT;
+ }
};
/// ambient occlusion closure
@@ -71,7 +81,11 @@ public:
///
class AmbientOcclusionClosure : public CClosurePrimitive {
public:
- AmbientOcclusionClosure () : CClosurePrimitive(AmbientOcclusion) {}
+ void setup(ShaderData *sd, int /* path_flag */, float3 weight)
+ {
+ closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_AMBIENT_OCCLUSION_ID, weight);
+ sd->flag |= SD_AO;
+ }
};
ClosureParam *closure_background_params()
diff --git a/intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp b/intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp
index b5c0d76cf37..bc26f42b559 100644
--- a/intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp
+++ b/intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp
@@ -39,6 +39,7 @@
#include "kernel_types.h"
#include "kernel_montecarlo.h"
+#include "closure/alloc.h"
#include "closure/bsdf_diffuse_ramp.h"
CCL_NAMESPACE_BEGIN
@@ -47,51 +48,30 @@ using namespace OSL;
class DiffuseRampClosure : public CBSDFClosure {
public:
+ DiffuseRampBsdf params;
Color3 colors[8];
- float3 fcolors[8];
- DiffuseRampClosure() : CBSDFClosure(LABEL_DIFFUSE)
- {}
-
- void setup()
+ void setup(ShaderData *sd, int /* path_flag */, float3 weight)
{
- sc.prim = this;
- m_shaderdata_flag = bsdf_diffuse_ramp_setup(&sc);
+ DiffuseRampBsdf *bsdf = (DiffuseRampBsdf*)bsdf_alloc_osl(sd, sizeof(DiffuseRampBsdf), weight, &params);
- for(int i = 0; i < 8; i++)
- fcolors[i] = TO_FLOAT3(colors[i]);
- }
+ if(bsdf) {
+ bsdf->colors = (float3*)closure_alloc_extra(sd, sizeof(float3)*8);
- void blur(float roughness)
- {
- bsdf_diffuse_ramp_blur(&sc, roughness);
- }
+ if(bsdf->colors) {
+ for(int i = 0; i < 8; i++)
+ bsdf->colors[i] = TO_FLOAT3(colors[i]);
- float3 eval_reflect(const float3 &omega_out, const float3 &omega_in, float& pdf) const
- {
- return bsdf_diffuse_ramp_eval_reflect(&sc, fcolors, omega_out, omega_in, &pdf);
- }
-
- float3 eval_transmit(const float3 &omega_out, const float3 &omega_in, float& pdf) const
- {
- return bsdf_diffuse_ramp_eval_transmit(&sc, fcolors, omega_out, omega_in, &pdf);
- }
-
- int sample(const float3 &Ng,
- const float3 &omega_out, const float3 &domega_out_dx, const float3 &domega_out_dy,
- float randu, float randv,
- float3 &omega_in, float3 &domega_in_dx, float3 &domega_in_dy,
- float &pdf, float3 &eval) const
- {
- return bsdf_diffuse_ramp_sample(&sc, fcolors, Ng, omega_out, domega_out_dx, domega_out_dy,
- randu, randv, &eval, &omega_in, &domega_in_dx, &domega_in_dy, &pdf);
+ sd->flag |= bsdf_diffuse_ramp_setup(bsdf);
+ }
+ }
}
};
ClosureParam *closure_bsdf_diffuse_ramp_params()
{
static ClosureParam params[] = {
- CLOSURE_FLOAT3_PARAM(DiffuseRampClosure, sc.N),
+ CLOSURE_FLOAT3_PARAM(DiffuseRampClosure, params.N),
CLOSURE_COLOR_ARRAY_PARAM(DiffuseRampClosure, colors, 8),
CLOSURE_STRING_KEYPARAM(DiffuseRampClosure, label, "label"),
CLOSURE_FINISH_PARAM(DiffuseRampClosure)
diff --git a/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp b/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp
index bc73d80cd78..14c7644936e 100644
--- a/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp
+++ b/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp
@@ -38,6 +38,7 @@
#include "osl_closures.h"
#include "kernel_types.h"
+#include "closure/alloc.h"
#include "closure/bsdf_phong_ramp.h"
CCL_NAMESPACE_BEGIN
@@ -46,52 +47,31 @@ using namespace OSL;
class PhongRampClosure : public CBSDFClosure {
public:
+ PhongRampBsdf params;
Color3 colors[8];
- float3 fcolors[8];
- PhongRampClosure() : CBSDFClosure(LABEL_GLOSSY)
- {}
-
- void setup()
+ void setup(ShaderData *sd, int /* path_flag */, float3 weight)
{
- sc.prim = this;
- m_shaderdata_flag = bsdf_phong_ramp_setup(&sc);
+ PhongRampBsdf *bsdf = (PhongRampBsdf*)bsdf_alloc_osl(sd, sizeof(PhongRampBsdf), weight, &params);
- for(int i = 0; i < 8; i++)
- fcolors[i] = TO_FLOAT3(colors[i]);
- }
+ if(bsdf) {
+ bsdf->colors = (float3*)closure_alloc_extra(sd, sizeof(float3)*8);
- void blur(float roughness)
- {
- bsdf_phong_ramp_blur(&sc, roughness);
- }
+ if(bsdf->colors) {
+ for(int i = 0; i < 8; i++)
+ bsdf->colors[i] = TO_FLOAT3(colors[i]);
- float3 eval_reflect(const float3 &omega_out, const float3 &omega_in, float& pdf) const
- {
- return bsdf_phong_ramp_eval_reflect(&sc, fcolors, omega_out, omega_in, &pdf);
- }
-
- float3 eval_transmit(const float3 &omega_out, const float3 &omega_in, float& pdf) const
- {
- return bsdf_phong_ramp_eval_transmit(&sc, fcolors, omega_out, omega_in, &pdf);
- }
-
- int sample(const float3 &Ng,
- const float3 &omega_out, const float3 &domega_out_dx, const float3 &domega_out_dy,
- float randu, float randv,
- float3 &omega_in, float3 &domega_in_dx, float3 &domega_in_dy,
- float &pdf, float3 &eval) const
- {
- return bsdf_phong_ramp_sample(&sc, fcolors, Ng, omega_out, domega_out_dx, domega_out_dy,
- randu, randv, &eval, &omega_in, &domega_in_dx, &domega_in_dy, &pdf);
+ sd->flag |= bsdf_phong_ramp_setup(bsdf);
+ }
+ }
}
};
ClosureParam *closure_bsdf_phong_ramp_params()
{
static ClosureParam params[] = {
- CLOSURE_FLOAT3_PARAM(PhongRampClosure, sc.N),
- CLOSURE_FLOAT_PARAM(PhongRampClosure, sc.data0),
+ 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)
diff --git a/intern/cycles/kernel/osl/emissive.cpp b/intern/cycles/kernel/osl/emissive.cpp
index f91fd6e015c..3f13e08b302 100644
--- a/intern/cycles/kernel/osl/emissive.cpp
+++ b/intern/cycles/kernel/osl/emissive.cpp
@@ -36,7 +36,9 @@
#include "osl_closures.h"
+#include "kernel_compat_cpu.h"
#include "kernel_types.h"
+#include "closure/alloc.h"
#include "closure/emissive.h"
CCL_NAMESPACE_BEGIN
@@ -52,25 +54,10 @@ using namespace OSL;
///
class GenericEmissiveClosure : public CClosurePrimitive {
public:
- GenericEmissiveClosure() : CClosurePrimitive(Emissive) { }
-
- Color3 eval(const Vec3 &Ng, const Vec3 &omega_out) const
- {
- float3 result = emissive_simple_eval(TO_FLOAT3(Ng), TO_FLOAT3(omega_out));
- return TO_COLOR3(result);
- }
-
- void sample(const Vec3 &Ng, float randu, float randv,
- Vec3 &omega_out, float &pdf) const
- {
- float3 omega_out_;
- emissive_sample(TO_FLOAT3(Ng), randu, randv, &omega_out_, &pdf);
- omega_out = TO_VEC3(omega_out_);
- }
-
- float pdf(const Vec3 &Ng, const Vec3 &omega_out) const
+ void setup(ShaderData *sd, int /* path_flag */, float3 weight)
{
- return emissive_pdf(TO_FLOAT3(Ng), TO_FLOAT3(omega_out));
+ closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_EMISSION_ID, weight);
+ sd->flag |= SD_EMISSION;
}
};
diff --git a/intern/cycles/kernel/osl/osl_bssrdf.cpp b/intern/cycles/kernel/osl/osl_bssrdf.cpp
index f5284653c49..b76f2b4713a 100644
--- a/intern/cycles/kernel/osl/osl_bssrdf.cpp
+++ b/intern/cycles/kernel/osl/osl_bssrdf.cpp
@@ -30,17 +30,15 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <OpenImageIO/fmath.h>
-
#include <OSL/genclosure.h>
#include "kernel_compat_cpu.h"
-#include "osl_bssrdf.h"
#include "osl_closures.h"
#include "kernel_types.h"
#include "kernel_montecarlo.h"
+#include "closure/alloc.h"
#include "closure/bsdf_util.h"
#include "closure/bsdf_diffuse.h"
#include "closure/bsdf_disney_diffuse.h"
@@ -50,27 +48,83 @@ CCL_NAMESPACE_BEGIN
using namespace OSL;
+class CBSSRDFClosure : public CClosurePrimitive {
+public:
+ Bssrdf params;
+ float3 radius;
+ float3 albedo;
+
+ void alloc(ShaderData *sd, int path_flag, float3 weight, ClosureType type)
+ {
+ float sample_weight = fabsf(average(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) {
+ radius = make_float3(0.0f, 0.0f, 0.0f);
+ }
+
+ if(sample_weight > CLOSURE_WEIGHT_CUTOFF) {
+ /* sharpness */
+ float sharpness = params.sharpness;
+ /* texture color blur */
+ float texture_blur = params.texture_blur;
+
+ /* create one closure per color channel */
+ Bssrdf *bssrdf = bssrdf_alloc(sd, make_float3(weight.x, 0.0f, 0.0f));
+ if(bssrdf) {
+ bssrdf->sample_weight = sample_weight;
+ bssrdf->radius = radius.x;
+ bssrdf->texture_blur = texture_blur;
+ bssrdf->albedo = albedo.x;
+ bssrdf->sharpness = sharpness;
+ bssrdf->N = params.N;
+ ccl_fetch(sd, flag) |= bssrdf_setup(bssrdf, (ClosureType)type);
+ }
+
+ bssrdf = bssrdf_alloc(sd, make_float3(0.0f, weight.y, 0.0f));
+ if(bssrdf) {
+ bssrdf->sample_weight = sample_weight;
+ bssrdf->radius = radius.y;
+ bssrdf->texture_blur = texture_blur;
+ bssrdf->albedo = albedo.y;
+ bssrdf->sharpness = sharpness;
+ bssrdf->N = params.N;
+ ccl_fetch(sd, flag) |= bssrdf_setup(bssrdf, (ClosureType)type);
+ }
+
+ bssrdf = bssrdf_alloc(sd, make_float3(0.0f, 0.0f, weight.z));
+ if(bssrdf) {
+ bssrdf->sample_weight = sample_weight;
+ bssrdf->radius = radius.z;
+ bssrdf->texture_blur = texture_blur;
+ bssrdf->albedo = albedo.z;
+ bssrdf->sharpness = sharpness;
+ bssrdf->N = params.N;
+ ccl_fetch(sd, flag) |= bssrdf_setup(bssrdf, (ClosureType)type);
+ }
+ }
+ }
+};
+
/* Cubic */
class CubicBSSRDFClosure : public CBSSRDFClosure {
public:
- CubicBSSRDFClosure()
- {}
-
- void setup()
+ void setup(ShaderData *sd, int path_flag, float3 weight)
{
- sc.type = CLOSURE_BSSRDF_CUBIC_ID;
- sc.data0 = fabsf(average(radius));
+ alloc(sd, path_flag, weight, CLOSURE_BSSRDF_CUBIC_ID);
}
};
ClosureParam *closure_bssrdf_cubic_params()
{
static ClosureParam params[] = {
- CLOSURE_FLOAT3_PARAM(CubicBSSRDFClosure, sc.N),
+ CLOSURE_FLOAT3_PARAM(CubicBSSRDFClosure, params.N),
CLOSURE_FLOAT3_PARAM(CubicBSSRDFClosure, radius),
- CLOSURE_FLOAT_PARAM(CubicBSSRDFClosure, sc.data1),
- CLOSURE_FLOAT_PARAM(CubicBSSRDFClosure, sc.T.x),
+ CLOSURE_FLOAT_PARAM(CubicBSSRDFClosure, params.texture_blur),
+ CLOSURE_FLOAT_PARAM(CubicBSSRDFClosure, params.sharpness),
CLOSURE_STRING_KEYPARAM(CubicBSSRDFClosure, label, "label"),
CLOSURE_FINISH_PARAM(CubicBSSRDFClosure)
};
@@ -83,22 +137,18 @@ CCLOSURE_PREPARE(closure_bssrdf_cubic_prepare, CubicBSSRDFClosure)
class GaussianBSSRDFClosure : public CBSSRDFClosure {
public:
- GaussianBSSRDFClosure()
- {}
-
- void setup()
+ void setup(ShaderData *sd, int path_flag, float3 weight)
{
- sc.type = CLOSURE_BSSRDF_GAUSSIAN_ID;
- sc.data0 = fabsf(average(radius));
+ alloc(sd, path_flag, weight, CLOSURE_BSSRDF_GAUSSIAN_ID);
}
};
ClosureParam *closure_bssrdf_gaussian_params()
{
static ClosureParam params[] = {
- CLOSURE_FLOAT3_PARAM(GaussianBSSRDFClosure, sc.N),
+ CLOSURE_FLOAT3_PARAM(GaussianBSSRDFClosure, params.N),
CLOSURE_FLOAT3_PARAM(GaussianBSSRDFClosure, radius),
- CLOSURE_FLOAT_PARAM(GaussianBSSRDFClosure, sc.data1),
+ CLOSURE_FLOAT_PARAM(GaussianBSSRDFClosure, params.texture_blur),
CLOSURE_STRING_KEYPARAM(GaussianBSSRDFClosure, label, "label"),
CLOSURE_FINISH_PARAM(GaussianBSSRDFClosure)
};
@@ -111,22 +161,18 @@ CCLOSURE_PREPARE(closure_bssrdf_gaussian_prepare, GaussianBSSRDFClosure)
class BurleyBSSRDFClosure : public CBSSRDFClosure {
public:
- BurleyBSSRDFClosure()
- {}
-
- void setup()
+ void setup(ShaderData *sd, int path_flag, float3 weight)
{
- sc.type = CLOSURE_BSSRDF_BURLEY_ID;
- sc.data0 = fabsf(average(radius));
+ alloc(sd, path_flag, weight, CLOSURE_BSSRDF_BURLEY_ID);
}
};
ClosureParam *closure_bssrdf_burley_params()
{
static ClosureParam params[] = {
- CLOSURE_FLOAT3_PARAM(BurleyBSSRDFClosure, sc.N),
+ CLOSURE_FLOAT3_PARAM(BurleyBSSRDFClosure, params.N),
CLOSURE_FLOAT3_PARAM(BurleyBSSRDFClosure, radius),
- CLOSURE_FLOAT_PARAM(BurleyBSSRDFClosure, sc.data1),
+ CLOSURE_FLOAT_PARAM(BurleyBSSRDFClosure, params.texture_blur),
CLOSURE_FLOAT3_PARAM(BurleyBSSRDFClosure, albedo),
CLOSURE_STRING_KEYPARAM(BurleyBSSRDFClosure, label, "label"),
CLOSURE_FINISH_PARAM(BurleyBSSRDFClosure)
diff --git a/intern/cycles/kernel/osl/osl_bssrdf.h b/intern/cycles/kernel/osl/osl_bssrdf.h
deleted file mode 100644
index d81ecade543..00000000000
--- a/intern/cycles/kernel/osl/osl_bssrdf.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Adapted from Open Shading Language with this license:
- *
- * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
- * All Rights Reserved.
- *
- * Modifications Copyright 2011, Blender Foundation.
- *
- * Redistribution and use in source and binary forms, with or without
- * 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.
- * * 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.
- * * 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.
- * 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
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __OSL_BSSRDF_H__
-#define __OSL_BSSRDF_H__
-
-#include <OSL/oslclosure.h>
-#include <OSL/oslexec.h>
-#include <OSL/genclosure.h>
-
-#include "osl_closures.h"
-
-#include "kernel_types.h"
-
-#include "util_types.h"
-
-CCL_NAMESPACE_BEGIN
-
-class CBSSRDFClosure : public CClosurePrimitive {
-public:
- ShaderClosure sc;
- float3 radius;
- float3 albedo;
-
- CBSSRDFClosure() : CClosurePrimitive(BSSRDF) { }
- int scattering() const { return LABEL_DIFFUSE; }
-};
-
-CCL_NAMESPACE_END
-
-#endif /* __OSL_BSSRDF_H__ */
-
diff --git a/intern/cycles/kernel/osl/osl_closures.cpp b/intern/cycles/kernel/osl/osl_closures.cpp
index 838c651a71c..2c7772fb25e 100644
--- a/intern/cycles/kernel/osl/osl_closures.cpp
+++ b/intern/cycles/kernel/osl/osl_closures.cpp
@@ -44,11 +44,14 @@
#include "kernel_compat_cpu.h"
#include "kernel_globals.h"
#include "kernel_montecarlo.h"
+#include "kernel_random.h"
+#include "closure/alloc.h"
#include "closure/bsdf_util.h"
#include "closure/bsdf_ashikhmin_velvet.h"
#include "closure/bsdf_diffuse.h"
#include "closure/bsdf_microfacet.h"
+#include "closure/bsdf_microfacet_multi.h"
#include "closure/bsdf_oren_nayar.h"
#include "closure/bsdf_reflection.h"
#include "closure/bsdf_refraction.h"
@@ -68,117 +71,145 @@ using namespace OSL;
/* BSDF class definitions */
-BSDF_CLOSURE_CLASS_BEGIN(Diffuse, diffuse, diffuse, LABEL_DIFFUSE)
- CLOSURE_FLOAT3_PARAM(DiffuseClosure, sc.N),
+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, translucent, LABEL_DIFFUSE)
- CLOSURE_FLOAT3_PARAM(TranslucentClosure, sc.N),
+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, oren_nayar, LABEL_DIFFUSE)
- CLOSURE_FLOAT3_PARAM(OrenNayarClosure, sc.N),
- CLOSURE_FLOAT_PARAM(OrenNayarClosure, sc.data0),
+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, reflection, LABEL_SINGULAR)
- CLOSURE_FLOAT3_PARAM(ReflectionClosure, sc.N),
+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, refraction, LABEL_SINGULAR)
- CLOSURE_FLOAT3_PARAM(RefractionClosure, sc.N),
- CLOSURE_FLOAT_PARAM(RefractionClosure, sc.data0),
+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(Transparent, transparent, transparent, LABEL_SINGULAR)
+BSDF_CLOSURE_CLASS_BEGIN(Transparent, transparent, ShaderClosure, LABEL_SINGULAR)
BSDF_CLOSURE_CLASS_END(Transparent, transparent)
-BSDF_CLOSURE_CLASS_BEGIN(AshikhminVelvet, ashikhmin_velvet, ashikhmin_velvet, LABEL_DIFFUSE)
- CLOSURE_FLOAT3_PARAM(AshikhminVelvetClosure, sc.N),
- CLOSURE_FLOAT_PARAM(AshikhminVelvetClosure, sc.data0),
+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, ashikhmin_shirley, LABEL_GLOSSY|LABEL_REFLECT)
- CLOSURE_FLOAT3_PARAM(AshikhminShirleyClosure, sc.N),
- CLOSURE_FLOAT3_PARAM(AshikhminShirleyClosure, sc.T),
- CLOSURE_FLOAT_PARAM(AshikhminShirleyClosure, sc.data0),
- CLOSURE_FLOAT_PARAM(AshikhminShirleyClosure, sc.data1),
+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, diffuse_toon, LABEL_DIFFUSE)
- CLOSURE_FLOAT3_PARAM(DiffuseToonClosure, sc.N),
- CLOSURE_FLOAT_PARAM(DiffuseToonClosure, sc.data0),
- CLOSURE_FLOAT_PARAM(DiffuseToonClosure, sc.data1),
+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, glossy_toon, LABEL_GLOSSY)
- CLOSURE_FLOAT3_PARAM(GlossyToonClosure, sc.N),
- CLOSURE_FLOAT_PARAM(GlossyToonClosure, sc.data0),
- CLOSURE_FLOAT_PARAM(GlossyToonClosure, sc.data1),
+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, microfacet_ggx, LABEL_GLOSSY|LABEL_REFLECT)
- CLOSURE_FLOAT3_PARAM(MicrofacetGGXClosure, sc.N),
- CLOSURE_FLOAT_PARAM(MicrofacetGGXClosure, sc.data0),
+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, microfacet_ggx, LABEL_GLOSSY|LABEL_REFLECT)
- CLOSURE_FLOAT3_PARAM(MicrofacetGGXAnisoClosure, sc.N),
- CLOSURE_FLOAT3_PARAM(MicrofacetGGXAnisoClosure, sc.T),
- CLOSURE_FLOAT_PARAM(MicrofacetGGXAnisoClosure, sc.data0),
- CLOSURE_FLOAT_PARAM(MicrofacetGGXAnisoClosure, sc.data1),
+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, microfacet_beckmann, LABEL_GLOSSY|LABEL_REFLECT)
- CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannClosure, sc.N),
- CLOSURE_FLOAT_PARAM(MicrofacetBeckmannClosure, sc.data0),
+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, microfacet_beckmann, LABEL_GLOSSY|LABEL_REFLECT)
- CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannAnisoClosure, sc.N),
- CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannAnisoClosure, sc.T),
- CLOSURE_FLOAT_PARAM(MicrofacetBeckmannAnisoClosure, sc.data0),
- CLOSURE_FLOAT_PARAM(MicrofacetBeckmannAnisoClosure, sc.data1),
+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, microfacet_ggx, LABEL_GLOSSY|LABEL_TRANSMIT)
- CLOSURE_FLOAT3_PARAM(MicrofacetGGXRefractionClosure, sc.N),
- CLOSURE_FLOAT_PARAM(MicrofacetGGXRefractionClosure, sc.data0),
- CLOSURE_FLOAT_PARAM(MicrofacetGGXRefractionClosure, sc.data2),
+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, microfacet_beckmann, LABEL_GLOSSY|LABEL_TRANSMIT)
- CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannRefractionClosure, sc.N),
- CLOSURE_FLOAT_PARAM(MicrofacetBeckmannRefractionClosure, sc.data0),
- CLOSURE_FLOAT_PARAM(MicrofacetBeckmannRefractionClosure, sc.data2),
+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, hair_reflection, LABEL_GLOSSY)
- CLOSURE_FLOAT3_PARAM(HairReflectionClosure, sc.N),
- CLOSURE_FLOAT_PARAM(HairReflectionClosure, sc.data0),
- CLOSURE_FLOAT_PARAM(HairReflectionClosure, sc.data1),
- CLOSURE_FLOAT3_PARAM(HairReflectionClosure, sc.T),
- CLOSURE_FLOAT_PARAM(HairReflectionClosure, sc.data2),
+BSDF_CLOSURE_CLASS_BEGIN(HairReflection, hair_reflection, HairBsdf, LABEL_GLOSSY)
+ CLOSURE_FLOAT3_PARAM(HairReflectionClosure, unused),
+ 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, hair_transmission, LABEL_GLOSSY)
- CLOSURE_FLOAT3_PARAM(HairTransmissionClosure, sc.N),
- CLOSURE_FLOAT_PARAM(HairTransmissionClosure, sc.data0),
- CLOSURE_FLOAT_PARAM(HairTransmissionClosure, sc.data1),
- CLOSURE_FLOAT3_PARAM(HairReflectionClosure, sc.T),
- CLOSURE_FLOAT_PARAM(HairReflectionClosure, sc.data2),
+BSDF_CLOSURE_CLASS_BEGIN(HairTransmission, hair_transmission, HairBsdf, LABEL_GLOSSY)
+ CLOSURE_FLOAT3_PARAM(HairTransmissionClosure, unused),
+ 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)
-VOLUME_CLOSURE_CLASS_BEGIN(VolumeHenyeyGreenstein, henyey_greenstein, LABEL_VOLUME_SCATTER)
- CLOSURE_FLOAT_PARAM(VolumeHenyeyGreensteinClosure, sc.data0),
+VOLUME_CLOSURE_CLASS_BEGIN(VolumeHenyeyGreenstein, henyey_greenstein, HenyeyGreensteinVolume, LABEL_VOLUME_SCATTER)
+ CLOSURE_FLOAT_PARAM(VolumeHenyeyGreensteinClosure, params.g),
VOLUME_CLOSURE_CLASS_END(VolumeHenyeyGreenstein, henyey_greenstein)
-VOLUME_CLOSURE_CLASS_BEGIN(VolumeAbsorption, absorption, LABEL_SINGULAR)
+VOLUME_CLOSURE_CLASS_BEGIN(VolumeAbsorption, absorption, ShaderClosure, LABEL_SINGULAR)
VOLUME_CLOSURE_CLASS_END(VolumeAbsorption, absorption)
+BSDF_CLOSURE_CLASS_BEGIN(DisneyDiffuse, disney_diffuse, DisneyDiffuseBsdf, LABEL_DIFFUSE)
+ CLOSURE_FLOAT3_PARAM(DisneyDiffuseClosure, params.N),
+ CLOSURE_FLOAT3_PARAM(DisneyDiffuseClosure, params.baseColor),
+ CLOSURE_FLOAT_PARAM(DisneyDiffuseClosure, params.roughness),
+BSDF_CLOSURE_CLASS_END(DisneyDiffuse, disney_diffuse)
+
+BSDF_CLOSURE_CLASS_BEGIN(DisneySheen, disney_sheen, DisneySheenBsdf, LABEL_DIFFUSE)
+ CLOSURE_FLOAT3_PARAM(DisneySheenClosure, params.N),
+ CLOSURE_FLOAT_PARAM(DisneySheenClosure, params.sheen),
+ CLOSURE_FLOAT_PARAM(DisneySheenClosure, params.sheenTint),
+BSDF_CLOSURE_CLASS_END(DisneySheen, disney_sheen)
+
+BSDF_CLOSURE_CLASS_BEGIN(DisneySpecular, disney_specular, DisneySpecularBsdf, LABEL_GLOSSY | LABEL_REFLECT)
+ CLOSURE_FLOAT3_PARAM(DisneySpecularClosure, params.N),
+ CLOSURE_FLOAT3_PARAM(DisneySpecularClosure, params.T),
+ CLOSURE_FLOAT3_PARAM(DisneySpecularClosure, params.baseColor),
+ CLOSURE_FLOAT_PARAM(DisneySpecularClosure, params.metallic),
+ CLOSURE_FLOAT_PARAM(DisneySpecularClosure, params.specular),
+ CLOSURE_FLOAT_PARAM(DisneySpecularClosure, params.specularTint),
+ CLOSURE_FLOAT_PARAM(DisneySpecularClosure, params.roughness),
+ CLOSURE_FLOAT_PARAM(DisneySpecularClosure, params.anisotropic),
+BSDF_CLOSURE_CLASS_END(DisneySpecular, disney_specular)
+
+BSDF_CLOSURE_CLASS_BEGIN(DisneyClearcoat, disney_clearcoat, DisneyClearcoatBsdf, LABEL_GLOSSY|LABEL_REFLECT)
+ CLOSURE_FLOAT3_PARAM(DisneyClearcoatClosure, params.N),
+ CLOSURE_FLOAT_PARAM(DisneyClearcoatClosure, params.clearcoat),
+ CLOSURE_FLOAT_PARAM(DisneyClearcoatClosure, params.clearcoatGloss),
+BSDF_CLOSURE_CLASS_END(DisneyClearcoat, disney_clearcoat)
/* DISNEY CLEARCOAT */
-class DisneyClearcoatClosure : public CBSDFClosure {
+/*class DisneyClearcoatClosure : public CBSDFClosure {
public:
DisneyClearcoatClosure() : CBSDFClosure(LABEL_REFLECT | LABEL_GLOSSY)
{}
@@ -227,10 +258,10 @@ ClosureParam *bsdf_disney_clearcoat_params()
}
CCLOSURE_PREPARE(bsdf_disney_clearcoat_prepare, DisneyClearcoatClosure)
-
+*/
/* DISNEY DIFFUSE */
-class DisneyDiffuseClosure : public CBSDFClosure {
+/*class DisneyDiffuseClosure : public CBSDFClosure {
public:
DisneyDiffuseClosure() : CBSDFClosure(LABEL_DIFFUSE)
{}
@@ -277,10 +308,10 @@ ClosureParam *bsdf_disney_diffuse_params()
}
CCLOSURE_PREPARE(bsdf_disney_diffuse_prepare, DisneyDiffuseClosure)
-
+*/
/* DISNEY SHEEN */
-class DisneySheenClosure : public CBSDFClosure {
+/*class DisneySheenClosure : public CBSDFClosure {
public:
DisneySheenClosure() : CBSDFClosure(LABEL_DIFFUSE)
{}
@@ -328,10 +359,10 @@ ClosureParam *bsdf_disney_sheen_params()
}
CCLOSURE_PREPARE(bsdf_disney_sheen_prepare, DisneySheenClosure)
-
+*/
/* DISNEY SPECULAR */
-class DisneySpecularClosure : public CBSDFClosure {
+/*class DisneySpecularClosure : public CBSDFClosure {
public:
DisneySpecularClosure() : CBSDFClosure(LABEL_REFLECT | LABEL_GLOSSY)
{}
@@ -383,6 +414,7 @@ ClosureParam *bsdf_disney_specular_params()
}
CCLOSURE_PREPARE(bsdf_disney_specular_prepare, DisneySpecularClosure)
+*/
/* Registration */
@@ -417,6 +449,12 @@ void OSLShader::register_closures(OSLShadingSystem *ss_)
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_beckmann", id++,
bsdf_microfacet_beckmann_params(), bsdf_microfacet_beckmann_prepare);
register_closure(ss, "microfacet_beckmann_aniso", id++,
@@ -470,5 +508,120 @@ void OSLShader::register_closures(OSLShadingSystem *ss_)
volume_absorption_params(), volume_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;
+}
+
+/* Multiscattering GGX closures */
+
+class MicrofacetMultiClosure : public CBSDFClosure {
+public:
+ MicrofacetBsdf params;
+ float3 color;
+
+ 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)) {
+ MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc_osl(sd, sizeof(MicrofacetBsdf), weight, &params);
+ MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
+ if(bsdf && extra) {
+ bsdf->extra = extra;
+ bsdf->extra->color = color;
+ return bsdf;
+ }
+ }
+
+ return NULL;
+ }
+};
+
+class MicrofacetMultiGGXClosure : public MicrofacetMultiClosure {
+public:
+ void setup(ShaderData *sd, int path_flag, float3 weight)
+ {
+ MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
+ sd->flag |= (bsdf) ? bsdf_microfacet_multi_ggx_setup(bsdf) : 0;
+ }
+};
+
+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;
+}
+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);
+ sd->flag |= (bsdf) ? bsdf_microfacet_multi_ggx_aniso_setup(bsdf) : 0;
+ }
+};
+
+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;
+}
+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);
+ sd->flag |= (bsdf) ? bsdf_microfacet_multi_ggx_glass_setup(bsdf) : 0;
+ }
+};
+
+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;
+}
+CCLOSURE_PREPARE(closure_bsdf_microfacet_multi_ggx_glass_prepare, MicrofacetMultiGGXGlassClosure);
+
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/osl/osl_closures.h b/intern/cycles/kernel/osl/osl_closures.h
index 1578d06cd56..cd7b33703ff 100644
--- a/intern/cycles/kernel/osl/osl_closures.h
+++ b/intern/cycles/kernel/osl/osl_closures.h
@@ -52,6 +52,9 @@ OSL::ClosureParam *closure_bssrdf_cubic_params();
OSL::ClosureParam *closure_bssrdf_gaussian_params();
OSL::ClosureParam *closure_bssrdf_burley_params();
OSL::ClosureParam *closure_henyey_greenstein_volume_params();
+OSL::ClosureParam *closure_bsdf_microfacet_multi_ggx_params();
+OSL::ClosureParam *closure_bsdf_microfacet_multi_ggx_glass_params();
+OSL::ClosureParam *closure_bsdf_microfacet_multi_ggx_aniso_params();
void closure_emission_prepare(OSL::RendererServices *, int id, void *data);
void closure_background_prepare(OSL::RendererServices *, int id, void *data);
@@ -63,6 +66,9 @@ void closure_bssrdf_cubic_prepare(OSL::RendererServices *, int id, void *data);
void closure_bssrdf_gaussian_prepare(OSL::RendererServices *, int id, void *data);
void closure_bssrdf_burley_prepare(OSL::RendererServices *, int id, void *data);
void closure_henyey_greenstein_volume_prepare(OSL::RendererServices *, int id, void *data);
+void closure_bsdf_microfacet_multi_ggx_prepare(OSL::RendererServices *, int id, void *data);
+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);
#define CCLOSURE_PREPARE(name, classname) \
void name(RendererServices *, int id, void *data) \
@@ -84,21 +90,7 @@ void name(RendererServices *, int id, void *data) \
class CClosurePrimitive {
public:
- enum Category {
- BSDF, ///< Reflective and/or transmissive surface
- BSSRDF, ///< Sub-surface light transfer
- Emissive, ///< Light emission
- Background, ///< Background emission
- Volume, ///< Volume scattering
- Holdout, ///< Holdout from alpha
- AmbientOcclusion, ///< Ambient occlusion
- };
-
- CClosurePrimitive (Category category_) : category (category_) {}
- virtual ~CClosurePrimitive() {}
- virtual void setup() {}
-
- Category category;
+ virtual void setup(ShaderData *sd, int path_flag, float3 weight) = 0;
OSL::ustring label;
};
@@ -107,68 +99,22 @@ public:
class CBSDFClosure : public CClosurePrimitive {
public:
- ShaderClosure sc;
-
- CBSDFClosure(int scattering) : CClosurePrimitive(BSDF),
- m_scattering_label(scattering), m_shaderdata_flag(0)
- {}
-
- int scattering() const { return m_scattering_label; }
- int shaderdata_flag() const { return m_shaderdata_flag; }
-
- virtual void blur(float roughness) = 0;
- virtual float3 eval_reflect(const float3 &omega_out, const float3 &omega_in, float &pdf) const = 0;
- virtual float3 eval_transmit(const float3 &omega_out, const float3 &omega_in, float &pdf) const = 0;
-
- virtual int sample(const float3 &Ng,
- const float3 &omega_out, const float3 &domega_out_dx, const float3 &domega_out_dy,
- float randu, float randv,
- float3 &omega_in, float3 &domega_in_dx, float3 &domega_in_dy,
- float &pdf, float3 &eval) const = 0;
-
-protected:
- int m_scattering_label;
- int m_shaderdata_flag;
+ bool skip(const ShaderData *sd, int path_flag, int scattering);
};
-#define BSDF_CLOSURE_CLASS_BEGIN(Upper, lower, svmlower, TYPE) \
+#define BSDF_CLOSURE_CLASS_BEGIN(Upper, lower, structname, TYPE) \
\
class Upper##Closure : public CBSDFClosure { \
public: \
- Upper##Closure() : CBSDFClosure(TYPE) \
- { \
- } \
+ structname params; \
+ float3 unused; \
\
- void setup() \
+ void setup(ShaderData *sd, int path_flag, float3 weight) \
{ \
- sc.prim = NULL; \
- m_shaderdata_flag = bsdf_##lower##_setup(&sc); \
- } \
-\
- void blur(float roughness) \
- { \
- } \
-\
- float3 eval_reflect(const float3 &omega_out, const float3 &omega_in, float& pdf) const \
- { \
- pdf = 0.0f; \
- return make_float3(0.0f, 0.0f, 0.0f); \
- } \
-\
- float3 eval_transmit(const float3 &omega_out, const float3 &omega_in, float& pdf) const \
- { \
- pdf = 0.0f; \
- return make_float3(0.0f, 0.0f, 0.0f); \
- } \
-\
- int sample(const float3 &Ng, \
- const float3 &omega_out, const float3 &domega_out_dx, const float3 &domega_out_dy, \
- float randu, float randv, \
- float3 &omega_in, float3 &domega_in_dx, float3 &domega_in_dy, \
- float &pdf, float3 &eval) const \
- { \
- pdf = 0; \
- return LABEL_NONE; \
+ 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; \
+ } \
} \
}; \
\
@@ -187,36 +133,18 @@ static ClosureParam *bsdf_##lower##_params() \
\
CCLOSURE_PREPARE_STATIC(bsdf_##lower##_prepare, Upper##Closure)
-
/* Volume */
-class CVolumeClosure : public CClosurePrimitive {
-public:
- ShaderClosure sc;
-
- CVolumeClosure(int scattering) : CClosurePrimitive(Volume),
- m_scattering_label(scattering), m_shaderdata_flag(0)
- {}
- ~CVolumeClosure() { }
-
- int scattering() const { return m_scattering_label; }
- int shaderdata_flag() const { return m_shaderdata_flag; }
-
-protected:
- int m_scattering_label;
- int m_shaderdata_flag;
-};
-
-#define VOLUME_CLOSURE_CLASS_BEGIN(Upper, lower, TYPE) \
+#define VOLUME_CLOSURE_CLASS_BEGIN(Upper, lower, structname, TYPE) \
\
-class Upper##Closure : public CVolumeClosure { \
+class Upper##Closure : public CBSDFClosure { \
public: \
- Upper##Closure() : CVolumeClosure(TYPE) {} \
+ structname params; \
\
- void setup() \
+ void setup(ShaderData *sd, int path_flag, float3 weight) \
{ \
- sc.prim = NULL; \
- m_shaderdata_flag = volume_##lower##_setup(&sc); \
+ structname *volume = (structname*)bsdf_alloc_osl(sd, sizeof(structname), weight, &params); \
+ sd->flag |= (volume) ? volume_##lower##_setup(volume) : 0; \
} \
}; \
\
diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp
index ebe739ebd0e..caae24405f1 100644
--- a/intern/cycles/kernel/osl/osl_services.cpp
+++ b/intern/cycles/kernel/osl/osl_services.cpp
@@ -47,6 +47,7 @@
#include "kernel_camera.h"
#include "kernels/cpu/kernel_cpu_image.h"
#include "geom/geom.h"
+#include "bvh/bvh.h"
#include "kernel_projection.h"
#include "kernel_accumulate.h"
@@ -786,7 +787,7 @@ bool OSLRenderServices::get_attribute(ShaderData *sd, bool derivatives, ustring
TypeDesc type, ustring name, void *val)
{
KernelGlobals *kg = sd->osl_globals;
- bool is_curve;
+ int prim_type = 0;
int object;
/* lookup of attribute on another object */
@@ -797,18 +798,17 @@ bool OSLRenderServices::get_attribute(ShaderData *sd, bool derivatives, ustring
return false;
object = it->second;
- is_curve = false;
}
else {
object = sd->object;
- is_curve = (sd->type & PRIMITIVE_ALL_CURVE) != 0;
+ 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 + (is_curve == true);
+ object = object*ATTR_PRIM_TYPES + prim_type;
OSLGlobals::AttributeMap& attribute_map = kg->osl->attribute_map[object];
OSLGlobals::AttributeMap::iterator it = attribute_map.find(name);
@@ -912,7 +912,7 @@ bool OSLRenderServices::texture(ustring filename,
#endif
bool status;
- if(filename[0] == '@') {
+ if(filename.length() && filename[0] == '@') {
int slot = atoi(filename.c_str() + 1);
float4 rgba = kernel_tex_image_interp(slot, s, 1.0f - t);
@@ -993,7 +993,7 @@ bool OSLRenderServices::texture3d(ustring filename,
}
bool status;
- if(filename[0] == '@') {
+ if(filename.length() && filename[0] == '@') {
int slot = atoi(filename.c_str() + 1);
float4 rgba = kernel_tex_image_interp_3d(slot, P.x, P.y, P.z);
diff --git a/intern/cycles/kernel/osl/osl_shader.cpp b/intern/cycles/kernel/osl/osl_shader.cpp
index a2f1c31a7c5..784e468635c 100644
--- a/intern/cycles/kernel/osl/osl_shader.cpp
+++ b/intern/cycles/kernel/osl/osl_shader.cpp
@@ -23,12 +23,12 @@
#include "geom/geom_object.h"
-#include "closure/bsdf_util.h"
+/*#include "closure/bsdf_util.h"
#include "closure/bsdf_diffuse.h"
#include "closure/bsdf_disney_diffuse.h"
#include "closure/bssrdf.h"
-#include "osl_bssrdf.h"
+#include "osl_bssrdf.h"*/
#include "osl_closures.h"
#include "osl_globals.h"
#include "osl_services.h"
@@ -143,8 +143,10 @@ static void shaderdata_to_shaderglobals(KernelGlobals *kg, ShaderData *sd, PathS
/* Surface */
-static void flatten_surface_closure_tree(ShaderData *sd, int path_flag,
- const OSL::ClosureColor *closure, float3 weight = make_float3(1.0f, 1.0f, 1.0f))
+static void flatten_surface_closure_tree(ShaderData *sd,
+ int path_flag,
+ 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. */
@@ -165,159 +167,11 @@ static void flatten_surface_closure_tree(ShaderData *sd, int path_flag,
OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure;
CClosurePrimitive *prim = (CClosurePrimitive *)comp->data();
- if(prim) {
- ShaderClosure sc;
-
+ if (prim) {
#ifdef OSL_SUPPORTS_WEIGHTED_CLOSURE_COMPONENTS
weight = weight*TO_FLOAT3(comp->w);
#endif
- sc.weight = weight;
-
- prim->setup();
-
- switch(prim->category) {
- case CClosurePrimitive::BSDF: {
- CBSDFClosure *bsdf = (CBSDFClosure *)prim;
- int scattering = bsdf->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;
- }
- }
-
- /* sample weight */
- float sample_weight = fabsf(average(weight));
-
- sc.sample_weight = sample_weight;
-
- sc.type = bsdf->sc.type;
- sc.N = bsdf->sc.N;
- sc.T = bsdf->sc.T;
- sc.data0 = bsdf->sc.data0;
- sc.data1 = bsdf->sc.data1;
- sc.data2 = bsdf->sc.data2;
- sc.prim = bsdf->sc.prim;
-
- /* add */
- if(sc.sample_weight > CLOSURE_WEIGHT_CUTOFF && sd->num_closure < MAX_CLOSURE) {
- sd->closure[sd->num_closure++] = sc;
- sd->flag |= bsdf->shaderdata_flag();
- }
- break;
- }
- case CClosurePrimitive::Emissive: {
- /* sample weight */
- float sample_weight = fabsf(average(weight));
-
- sc.sample_weight = sample_weight;
- sc.type = CLOSURE_EMISSION_ID;
- sc.data0 = 0.0f;
- sc.data1 = 0.0f;
- sc.data2 = 0.0f;
- sc.prim = NULL;
-
- /* flag */
- if(sd->num_closure < MAX_CLOSURE) {
- sd->closure[sd->num_closure++] = sc;
- sd->flag |= SD_EMISSION;
- }
- break;
- }
- case CClosurePrimitive::AmbientOcclusion: {
- /* sample weight */
- float sample_weight = fabsf(average(weight));
-
- sc.sample_weight = sample_weight;
- sc.type = CLOSURE_AMBIENT_OCCLUSION_ID;
- sc.data0 = 0.0f;
- sc.data1 = 0.0f;
- sc.data2 = 0.0f;
- sc.prim = NULL;
-
- if(sd->num_closure < MAX_CLOSURE) {
- sd->closure[sd->num_closure++] = sc;
- sd->flag |= SD_AO;
- }
- break;
- }
- case CClosurePrimitive::Holdout: {
- sc.sample_weight = 0.0f;
- sc.type = CLOSURE_HOLDOUT_ID;
- sc.data0 = 0.0f;
- sc.data1 = 0.0f;
- sc.data2 = 0.0f;
- sc.prim = NULL;
-
- if(sd->num_closure < MAX_CLOSURE) {
- sd->closure[sd->num_closure++] = sc;
- sd->flag |= SD_HOLDOUT;
- }
- break;
- }
- case CClosurePrimitive::BSSRDF: {
- CBSSRDFClosure *bssrdf = (CBSSRDFClosure *)prim;
- float sample_weight = fabsf(average(weight));
-
- if(sample_weight > CLOSURE_WEIGHT_CUTOFF && sd->num_closure+2 < MAX_CLOSURE) {
- sc.sample_weight = sample_weight;
-
- sc.type = bssrdf->sc.type;
- sc.N = bssrdf->sc.N;
- sc.data1 = bssrdf->sc.data1;
- sc.T.x = bssrdf->sc.T.x;
- sc.prim = NULL;
-
- /* 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)
- bssrdf->radius = make_float3(0.0f, 0.0f, 0.0f);
-
- float3 albedo =
- (bssrdf->sc.type == CLOSURE_BSSRDF_BURLEY_ID || bssrdf->sc.type == CLOSURE_BSSRDF_DISNEY_ID)
- ? bssrdf->albedo
- : make_float3(0.0f, 0.0f, 0.0f);
-
- /* create one closure for each color channel */
- if(fabsf(weight.x) > 0.0f) {
- sc.weight = make_float3(weight.x, 0.0f, 0.0f);
- sc.data0 = bssrdf->radius.x;
- sc.data1 = 0.0f;
- sc.data2 = albedo.x;
- sd->flag |= bssrdf_setup(&sc, sc.type);
- sd->closure[sd->num_closure++] = sc;
- }
-
- if(fabsf(weight.y) > 0.0f) {
- sc.weight = make_float3(0.0f, weight.y, 0.0f);
- sc.data0 = bssrdf->radius.y;
- sc.data1 = 0.0f;
- sc.data2 = albedo.y;
- sd->flag |= bssrdf_setup(&sc, sc.type);
- sd->closure[sd->num_closure++] = sc;
- }
-
- if(fabsf(weight.z) > 0.0f) {
- sc.weight = make_float3(0.0f, 0.0f, weight.z);
- sc.data0 = bssrdf->radius.z;
- sc.data1 = 0.0f;
- sc.data2 = albedo.z;
- sd->flag |= bssrdf_setup(&sc, sc.type);
- sd->closure[sd->num_closure++] = sc;
- }
- }
- break;
- }
- case CClosurePrimitive::Background:
- case CClosurePrimitive::Volume:
- break; /* not relevant */
- }
+ prim->setup(sd, path_flag, weight);
}
break;
}
@@ -347,7 +201,9 @@ void OSLShader::eval_surface(KernelGlobals *kg, ShaderData *sd, PathState *state
/* Background */
-static float3 flatten_background_closure_tree(const OSL::ClosureColor *closure)
+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
@@ -356,32 +212,32 @@ static float3 flatten_background_closure_tree(const OSL::ClosureColor *closure)
switch(closure->id) {
case OSL::ClosureColor::MUL: {
OSL::ClosureMul *mul = (OSL::ClosureMul *)closure;
-
- return TO_FLOAT3(mul->weight) * flatten_background_closure_tree(mul->closure);
+ flatten_background_closure_tree(sd, mul->closure, weight * TO_FLOAT3(mul->weight));
+ break;
}
case OSL::ClosureColor::ADD: {
OSL::ClosureAdd *add = (OSL::ClosureAdd *)closure;
- return flatten_background_closure_tree(add->closureA) +
- flatten_background_closure_tree(add->closureB);
+ 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 && prim->category == CClosurePrimitive::Background)
+ if(prim) {
#ifdef OSL_SUPPORTS_WEIGHTED_CLOSURE_COMPONENTS
- return TO_FLOAT3(comp->w);
-#else
- return make_float3(1.0f, 1.0f, 1.0f);
+ weight = weight*TO_FLOAT3(comp->w);
#endif
+ prim->setup(sd, 0, weight);
+ }
+ break;
}
}
-
- return make_float3(0.0f, 0.0f, 0.0f);
}
-float3 OSLShader::eval_background(KernelGlobals *kg, ShaderData *sd, PathState *state, int path_flag, ShaderContext ctx)
+void OSLShader::eval_background(KernelGlobals *kg, ShaderData *sd, PathState *state, int path_flag, ShaderContext ctx)
{
/* setup shader globals from shader data */
OSLThreadData *tdata = kg->osl_tdata;
@@ -398,15 +254,14 @@ float3 OSLShader::eval_background(KernelGlobals *kg, ShaderData *sd, PathState *
/* return background color immediately */
if(globals->Ci)
- return flatten_background_closure_tree(globals->Ci);
-
- return make_float3(0.0f, 0.0f, 0.0f);
+ flatten_background_closure_tree(sd, globals->Ci);
}
/* Volume */
static void flatten_volume_closure_tree(ShaderData *sd,
- const OSL::ClosureColor *closure, float3 weight = make_float3(1.0f, 1.0f, 1.0f))
+ 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. */
@@ -428,60 +283,10 @@ static void flatten_volume_closure_tree(ShaderData *sd,
CClosurePrimitive *prim = (CClosurePrimitive *)comp->data();
if(prim) {
- ShaderClosure sc;
-
#ifdef OSL_SUPPORTS_WEIGHTED_CLOSURE_COMPONENTS
weight = weight*TO_FLOAT3(comp->w);
#endif
- sc.weight = weight;
-
- prim->setup();
-
- switch(prim->category) {
- case CClosurePrimitive::Volume: {
- CVolumeClosure *volume = (CVolumeClosure *)prim;
- /* sample weight */
- float sample_weight = fabsf(average(weight));
-
- sc.sample_weight = sample_weight;
- sc.type = volume->sc.type;
- sc.data0 = volume->sc.data0;
- sc.data1 = volume->sc.data1;
-
- /* add */
- if((sc.sample_weight > CLOSURE_WEIGHT_CUTOFF) &&
- (sd->num_closure < MAX_CLOSURE))
- {
- sd->closure[sd->num_closure++] = sc;
- sd->flag |= volume->shaderdata_flag();
- }
- break;
- }
- case CClosurePrimitive::Emissive: {
- /* sample weight */
- float sample_weight = fabsf(average(weight));
-
- sc.sample_weight = sample_weight;
- sc.type = CLOSURE_EMISSION_ID;
- sc.data0 = 0.0f;
- sc.data1 = 0.0f;
- sc.prim = NULL;
-
- /* flag */
- if(sd->num_closure < MAX_CLOSURE) {
- sd->closure[sd->num_closure++] = sc;
- sd->flag |= SD_EMISSION;
- }
- break;
- }
- case CClosurePrimitive::Holdout:
- break; /* not implemented */
- case CClosurePrimitive::Background:
- case CClosurePrimitive::BSDF:
- case CClosurePrimitive::BSSRDF:
- case CClosurePrimitive::AmbientOcclusion:
- break; /* not relevant */
- }
+ prim->setup(sd, 0, weight);
}
}
}
@@ -533,40 +338,6 @@ void OSLShader::eval_displacement(KernelGlobals *kg, ShaderData *sd, ShaderConte
sd->P = TO_FLOAT3(globals->P);
}
-/* BSDF Closure */
-
-int OSLShader::bsdf_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3& eval, float3& omega_in, differential3& domega_in, float& pdf)
-{
- CBSDFClosure *sample_bsdf = (CBSDFClosure *)sc->prim;
-
- pdf = 0.0f;
-
- return sample_bsdf->sample(sd->Ng,
- sd->I, sd->dI.dx, sd->dI.dy,
- randu, randv,
- omega_in, domega_in.dx, domega_in.dy,
- pdf, eval);
-}
-
-float3 OSLShader::bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, const float3& omega_in, float& pdf)
-{
- CBSDFClosure *bsdf = (CBSDFClosure *)sc->prim;
- float3 bsdf_eval;
-
- if(dot(sd->Ng, omega_in) >= 0.0f)
- bsdf_eval = bsdf->eval_reflect(sd->I, omega_in, pdf);
- else
- bsdf_eval = bsdf->eval_transmit(sd->I, omega_in, pdf);
-
- return bsdf_eval;
-}
-
-void OSLShader::bsdf_blur(ShaderClosure *sc, float roughness)
-{
- CBSDFClosure *bsdf = (CBSDFClosure *)sc->prim;
- bsdf->blur(roughness);
-}
-
/* Attributes */
int OSLShader::find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id, AttributeElement *elem)
diff --git a/intern/cycles/kernel/osl/osl_shader.h b/intern/cycles/kernel/osl/osl_shader.h
index 7d26cd40da5..a185b8b8c05 100644
--- a/intern/cycles/kernel/osl/osl_shader.h
+++ b/intern/cycles/kernel/osl/osl_shader.h
@@ -54,18 +54,10 @@ public:
/* eval */
static void eval_surface(KernelGlobals *kg, ShaderData *sd, PathState *state, int path_flag, ShaderContext ctx);
- static float3 eval_background(KernelGlobals *kg, ShaderData *sd, PathState *state, int path_flag, ShaderContext ctx);
+ static void eval_background(KernelGlobals *kg, ShaderData *sd, PathState *state, int path_flag, ShaderContext ctx);
static void eval_volume(KernelGlobals *kg, ShaderData *sd, PathState *state, int path_flag, ShaderContext ctx);
static void eval_displacement(KernelGlobals *kg, ShaderData *sd, ShaderContext ctx);
- /* sample & eval */
- static int bsdf_sample(const ShaderData *sd, const ShaderClosure *sc,
- float randu, float randv,
- float3& eval, float3& omega_in, differential3& domega_in, float& pdf);
- static float3 bsdf_eval(const ShaderData *sd, const ShaderClosure *sc,
- const float3& omega_in, float& pdf);
- static void bsdf_blur(ShaderClosure *sc, float roughness);
-
/* attributes */
static int find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id, AttributeElement *elem);
};
diff --git a/intern/cycles/kernel/shaders/CMakeLists.txt b/intern/cycles/kernel/shaders/CMakeLists.txt
index 5dab03bcb16..39dbd185018 100644
--- a/intern/cycles/kernel/shaders/CMakeLists.txt
+++ b/intern/cycles/kernel/shaders/CMakeLists.txt
@@ -82,6 +82,7 @@ set(SRC_OSL
node_hair_bsdf.osl
node_uv_map.osl
node_disney_bsdf.osl
+ node_rgb_to_bw.osl
)
set(SRC_OSL_HEADERS
diff --git a/intern/cycles/kernel/shaders/node_anisotropic_bsdf.osl b/intern/cycles/kernel/shaders/node_anisotropic_bsdf.osl
index 281ed4e8726..bef6d7e8809 100644
--- a/intern/cycles/kernel/shaders/node_anisotropic_bsdf.osl
+++ b/intern/cycles/kernel/shaders/node_anisotropic_bsdf.osl
@@ -45,12 +45,14 @@ shader node_anisotropic_bsdf(
RoughnessV = Roughness / (1.0 - aniso);
}
- if (distribution == "Sharp")
+ if (distribution == "sharp")
BSDF = Color * reflection(Normal);
- else if (distribution == "Beckmann")
+ else if (distribution == "beckmann")
BSDF = Color * microfacet_beckmann_aniso(Normal, T, RoughnessU, RoughnessV);
else if (distribution == "GGX")
BSDF = Color * microfacet_ggx_aniso(Normal, T, RoughnessU, RoughnessV);
+ else if (distribution == "Multiscatter GGX")
+ BSDF = Color * microfacet_multi_ggx_aniso(Normal, T, RoughnessU, RoughnessV, Color);
else
BSDF = Color * ashikhmin_shirley(Normal, T, RoughnessU, RoughnessV);
}
diff --git a/intern/cycles/kernel/shaders/node_brick_texture.osl b/intern/cycles/kernel/shaders/node_brick_texture.osl
index 35e01178ba8..d5e0a7d4c8c 100644
--- a/intern/cycles/kernel/shaders/node_brick_texture.osl
+++ b/intern/cycles/kernel/shaders/node_brick_texture.osl
@@ -59,10 +59,10 @@ float brick(point p, float mortar_size, float bias,
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 OffsetFrequency = 2,
- float Squash = 1.0,
- int SquashFrequency = 1,
+ 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,
@@ -84,7 +84,7 @@ shader node_brick_texture(
color Col = Color1;
Fac = brick(p * Scale, MortarSize, Bias, BrickWidth, RowHeight,
- Offset, OffsetFrequency, Squash, SquashFrequency, tint);
+ offset, offset_frequency, squash, squash_frequency, tint);
if (Fac != 1.0) {
float facm = 1.0 - tint;
diff --git a/intern/cycles/kernel/shaders/node_convert_from_color.osl b/intern/cycles/kernel/shaders/node_convert_from_color.osl
index 44074317f42..e95a17f6fa1 100644
--- a/intern/cycles/kernel/shaders/node_convert_from_color.osl
+++ b/intern/cycles/kernel/shaders/node_convert_from_color.osl
@@ -17,18 +17,18 @@
#include "stdosl.h"
shader node_convert_from_color(
- color Color = 0.0,
- output string String = "",
- output float Val = 0.0,
- output int ValInt = 0,
- output vector Vector = vector(0.0, 0.0, 0.0),
- output point Point = point(0.0, 0.0, 0.0),
- output normal Normal = normal(0.0, 0.0, 0.0))
+ 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))
{
- Val = Color[0] * 0.2126 + Color[1] * 0.7152 + Color[2] * 0.0722;
- ValInt = (int)(Color[0] * 0.2126 + Color[1] * 0.7152 + Color[2] * 0.0722);
- Vector = vector(Color[0], Color[1], Color[2]);
- Point = point(Color[0], Color[1], Color[2]);
- Normal = normal(Color[0], Color[1], 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 fc5c79c4c64..a5c2e3b26ad 100644
--- a/intern/cycles/kernel/shaders/node_convert_from_float.osl
+++ b/intern/cycles/kernel/shaders/node_convert_from_float.osl
@@ -17,18 +17,18 @@
#include "stdosl.h"
shader node_convert_from_float(
- float Val = 0.0,
- output string String = "",
- output int ValInt = 0,
- output color Color = 0.0,
- output vector Vector = vector(0.0, 0.0, 0.0),
- output point Point = point(0.0, 0.0, 0.0),
- output normal Normal = normal(0.0, 0.0, 0.0))
+ 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))
{
- ValInt = (int)Val;
- Color = color(Val, Val, Val);
- Vector = vector(Val, Val, Val);
- Point = point(Val, Val, Val);
- Normal = normal(Val, Val, Val);
+ 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 3c3785ebc0d..0e6ae711210 100644
--- a/intern/cycles/kernel/shaders/node_convert_from_int.osl
+++ b/intern/cycles/kernel/shaders/node_convert_from_int.osl
@@ -17,19 +17,19 @@
#include "stdosl.h"
shader node_convert_from_int(
- int ValInt = 0,
- output string String = "",
- output float Val = 0.0,
- output color Color = 0.0,
- output vector Vector = vector(0.0, 0.0, 0.0),
- output point Point = point(0.0, 0.0, 0.0),
- output normal Normal = normal(0.0, 0.0, 0.0))
+ 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)ValInt;
- Val = f;
- Color = color(f, f, f);
- Vector = vector(f, f, f);
- Point = point(f, f, f);
- 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 8ecc56ac8ce..7fffa7f6169 100644
--- a/intern/cycles/kernel/shaders/node_convert_from_normal.osl
+++ b/intern/cycles/kernel/shaders/node_convert_from_normal.osl
@@ -17,18 +17,18 @@
#include "stdosl.h"
shader node_convert_from_normal(
- normal Normal = normal(0.0, 0.0, 0.0),
- output string String = "",
- output float Val = 0.0,
- output int ValInt = 0,
- output vector Vector = vector(0.0, 0.0, 0.0),
- output color Color = 0.0,
- output point Point = point(0.0, 0.0, 0.0))
+ 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))
{
- Val = (Normal[0] + Normal[1] + Normal[2]) * (1.0 / 3.0);
- ValInt = (int)((Normal[0] + Normal[1] + Normal[2]) * (1.0 / 3.0));
- Vector = vector(Normal[0], Normal[1], Normal[2]);
- Color = color(Normal[0], Normal[1], Normal[2]);
- Point = point(Normal[0], Normal[1], 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 e5913b7a1e4..9e4930296bb 100644
--- a/intern/cycles/kernel/shaders/node_convert_from_point.osl
+++ b/intern/cycles/kernel/shaders/node_convert_from_point.osl
@@ -17,18 +17,18 @@
#include "stdosl.h"
shader node_convert_from_point(
- point Point = point(0.0, 0.0, 0.0),
- output string String = "",
- output float Val = 0.0,
- output int ValInt = 0,
- output vector Vector = vector(0.0, 0.0, 0.0),
- output color Color = 0.0,
- output normal Normal = normal(0.0, 0.0, 0.0))
+ 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))
{
- Val = (Point[0] + Point[1] + Point[2]) * (1.0 / 3.0);
- ValInt = (int)((Normal[0] + Normal[1] + Normal[2]) * (1.0 / 3.0));
- Vector = vector(Point[0], Point[1], Point[2]);
- Color = color(Point[0], Point[1], Point[2]);
- Normal = normal(Point[0], Point[1], 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 0466734277b..cbc6653eada 100644
--- a/intern/cycles/kernel/shaders/node_convert_from_string.osl
+++ b/intern/cycles/kernel/shaders/node_convert_from_string.osl
@@ -17,13 +17,13 @@
#include "stdosl.h"
shader node_convert_from_string(
- string String = "",
- output color Color = color(0.0, 0.0, 0.0),
- output float Val = 0.0,
- output int ValInt = 0,
- output vector Vector = vector(0.0, 0.0, 0.0),
- output point Point = point(0.0, 0.0, 0.0),
- output normal Normal = normal(0.0, 0.0, 0.0))
+ 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 79c5cb04550..8bdca469b90 100644
--- a/intern/cycles/kernel/shaders/node_convert_from_vector.osl
+++ b/intern/cycles/kernel/shaders/node_convert_from_vector.osl
@@ -17,18 +17,18 @@
#include "stdosl.h"
shader node_convert_from_vector(
- vector Vector = vector(0.0, 0.0, 0.0),
- output string String = "",
- output float Val = 0.0,
- output int ValInt = 0,
- output color Color = color(0.0, 0.0, 0.0),
- output point Point = point(0.0, 0.0, 0.0),
- output normal Normal = normal(0.0, 0.0, 0.0))
+ 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))
{
- Val = (Vector[0] + Vector[1] + Vector[2]) * (1.0 / 3.0);
- ValInt = (int)((Normal[0] + Normal[1] + Normal[2]) * (1.0 / 3.0));
- Color = color(Vector[0], Vector[1], Vector[2]);
- Point = point(Vector[0], Vector[1], Vector[2]);
- Normal = normal(Vector[0], Vector[1], 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_environment_texture.osl b/intern/cycles/kernel/shaders/node_environment_texture.osl
index 3a0b782c98e..0a7f602226d 100644
--- a/intern/cycles/kernel/shaders/node_environment_texture.osl
+++ b/intern/cycles/kernel/shaders/node_environment_texture.osl
@@ -44,7 +44,7 @@ shader node_environment_texture(
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 projection = "equirectangular",
string interpolation = "linear",
string color_space = "sRGB",
int is_float = 1,
@@ -59,7 +59,7 @@ shader node_environment_texture(
p = normalize(p);
- if (projection == "Equirectangular")
+ if (projection == "equirectangular")
p = environment_texture_direction_to_equirectangular(p);
else
p = environment_texture_direction_to_mirrorball(p);
diff --git a/intern/cycles/kernel/shaders/node_glass_bsdf.osl b/intern/cycles/kernel/shaders/node_glass_bsdf.osl
index 68bc107cc5e..a9723a8300a 100644
--- a/intern/cycles/kernel/shaders/node_glass_bsdf.osl
+++ b/intern/cycles/kernel/shaders/node_glass_bsdf.osl
@@ -19,7 +19,7 @@
shader node_glass_bsdf(
color Color = 0.8,
- string distribution = "Sharp",
+ string distribution = "sharp",
float Roughness = 0.2,
float IOR = 1.45,
normal Normal = N,
@@ -30,11 +30,13 @@ shader node_glass_bsdf(
float cosi = dot(I, Normal);
float Fr = fresnel_dielectric_cos(cosi, eta);
- if (distribution == "Sharp")
+ if (distribution == "sharp")
BSDF = Color * (Fr * reflection(Normal) + (1.0 - Fr) * refraction(Normal, eta));
- else if (distribution == "Beckmann")
+ 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 d3250b32d0b..f4ea7e7dc6a 100644
--- a/intern/cycles/kernel/shaders/node_glossy_bsdf.osl
+++ b/intern/cycles/kernel/shaders/node_glossy_bsdf.osl
@@ -24,12 +24,14 @@ shader node_glossy_bsdf(
normal Normal = N,
output closure color BSDF = 0)
{
- if (distribution == "Sharp")
+ if (distribution == "sharp")
BSDF = Color * reflection(Normal);
- else if (distribution == "Beckmann")
+ 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 52b49688ab3..f458937a18f 100644
--- a/intern/cycles/kernel/shaders/node_gradient_texture.osl
+++ b/intern/cycles/kernel/shaders/node_gradient_texture.osl
@@ -29,31 +29,31 @@ float gradient(point p, string type)
float result = 0.0;
- if (type == "Linear") {
+ if (type == "linear") {
result = x;
}
- else if (type == "Quadratic") {
+ else if (type == "quadratic") {
float r = max(x, 0.0);
result = r * r;
}
- else if (type == "Easing") {
+ 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") {
+ else if (type == "diagonal") {
result = (x + y) * 0.5;
}
- else if (type == "Radial") {
+ 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")
+ if (type == "quadratic_sphere")
result = r * r;
- else if (type == "Spherical")
+ else if (type == "spherical")
result = r;
}
@@ -63,7 +63,7 @@ float gradient(point p, string type)
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",
+ string type = "linear",
point Vector = P,
output float Fac = 0.0,
output color Color = 0.0)
@@ -73,7 +73,7 @@ shader node_gradient_texture(
if (use_mapping)
p = transform(mapping, p);
- Fac = gradient(p, Type);
+ 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 54d4cb67c3b..ef8f2fae894 100644
--- a/intern/cycles/kernel/shaders/node_hair_bsdf.osl
+++ b/intern/cycles/kernel/shaders/node_hair_bsdf.osl
@@ -20,38 +20,39 @@
shader node_hair_bsdf(
color Color = 0.8,
- string component = "Reflection",
+ string component = "reflection",
float Offset = 0.0,
float RoughnessU = 0.1,
float RoughnessV = 1.0,
- normal Normal = Ng,
+ normal Tangent = normal(0, 0, 0),
output closure color BSDF = 0)
{
- float IsStrand;
float roughnessh = clamp(RoughnessU, 0.001, 1.0);
float roughnessv = clamp(RoughnessV, 0.001, 1.0);
- getattribute("geom:is_curve", IsStrand);
+ float offset = -Offset;
- if (!IsStrand) {
- if (backfacing()) {
- BSDF = transparent();
- }
- else {
- if (component == "Reflection")
- BSDF = Color * hair_reflection(Normal, roughnessh, roughnessv, normalize(dPdv), 0.0);
- else
- BSDF = Color * hair_transmission(Normal, roughnessh, roughnessv, normalize(dPdv), 0.0);
- }
+ 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 (backfacing() && IsCurve) {
+ BSDF = transparent();
}
else {
- if (backfacing()) {
- BSDF = transparent();
- }
- else {
- if (component == "Reflection")
- BSDF = Color * hair_reflection(Normal, roughnessh, roughnessv, dPdu, -Offset);
- else
- BSDF = Color * hair_transmission(Normal, roughnessh, roughnessv, dPdu, -Offset);
- }
+ 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_image_texture.osl b/intern/cycles/kernel/shaders/node_image_texture.osl
index d3a347b70db..7cd2922dd4f 100644
--- a/intern/cycles/kernel/shaders/node_image_texture.osl
+++ b/intern/cycles/kernel/shaders/node_image_texture.osl
@@ -62,9 +62,9 @@ color image_texture_lookup(string filename,
int use_alpha,
int is_float,
string interpolation,
- string wrap)
+ string extension)
{
- color rgb = (color)texture(filename, u, 1.0 - v, "wrap", wrap, "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);
@@ -86,9 +86,9 @@ shader node_image_texture(
point Vector = P,
string filename = "",
string color_space = "sRGB",
- string projection = "Flat",
+ string projection = "flat",
string interpolation = "smartcubic",
- string wrap = "periodic",
+ string extension = "periodic",
float projection_blend = 0.0,
int is_float = 1,
int use_alpha = 1,
@@ -100,7 +100,7 @@ shader node_image_texture(
if (use_mapping)
p = transform(mapping, p);
- if (projection == "Flat") {
+ if (projection == "flat") {
Color = image_texture_lookup(filename,
color_space,
p[0], p[1],
@@ -108,9 +108,9 @@ shader node_image_texture(
use_alpha,
is_float,
interpolation,
- wrap);
+ extension);
}
- else if (projection == "Box") {
+ else if (projection == "box") {
/* object space normal */
vector Nob = transform("world", "object", N);
@@ -184,7 +184,7 @@ shader node_image_texture(
use_alpha,
is_float,
interpolation,
- wrap);
+ extension);
Alpha += weight[0] * tmp_alpha;
}
if (weight[1] > 0.0) {
@@ -195,7 +195,7 @@ shader node_image_texture(
use_alpha,
is_float,
interpolation,
- wrap);
+ extension);
Alpha += weight[1] * tmp_alpha;
}
if (weight[2] > 0.0) {
@@ -206,11 +206,11 @@ shader node_image_texture(
use_alpha,
is_float,
interpolation,
- wrap);
+ extension);
Alpha += weight[2] * tmp_alpha;
}
}
- else if (projection == "Sphere") {
+ else if (projection == "sphere") {
point projected = map_to_sphere(texco_remap_square(p));
Color = image_texture_lookup(filename,
color_space,
@@ -219,9 +219,9 @@ shader node_image_texture(
use_alpha,
is_float,
interpolation,
- wrap);
+ extension);
}
- else if (projection == "Tube") {
+ else if (projection == "tube") {
point projected = map_to_tube(texco_remap_square(p));
Color = image_texture_lookup(filename,
color_space,
@@ -230,6 +230,6 @@ shader node_image_texture(
use_alpha,
is_float,
interpolation,
- wrap);
+ extension);
}
}
diff --git a/intern/cycles/kernel/shaders/node_magic_texture.osl b/intern/cycles/kernel/shaders/node_magic_texture.osl
index 55992e3494c..8d6af391e04 100644
--- a/intern/cycles/kernel/shaders/node_magic_texture.osl
+++ b/intern/cycles/kernel/shaders/node_magic_texture.osl
@@ -93,7 +93,7 @@ color magic(point p, int n, float distortion)
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,
+ int depth = 2,
float Distortion = 5.0,
float Scale = 5.0,
point Vector = P,
@@ -105,7 +105,7 @@ shader node_magic_texture(
if (use_mapping)
p = transform(mapping, p);
- Color = magic(p * Scale, Depth, Distortion);
+ 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_math.osl b/intern/cycles/kernel/shaders/node_math.osl
index 7eef97fd7e8..f309ef7c6f3 100644
--- a/intern/cycles/kernel/shaders/node_math.osl
+++ b/intern/cycles/kernel/shaders/node_math.osl
@@ -49,54 +49,54 @@ float safe_log(float a, float b)
}
shader node_math(
- string type = "Add",
- int Clamp = 0,
+ 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 */
- if (type == "Add")
+ if (type == "add")
Value = Value1 + Value2;
- else if (type == "Subtract")
+ else if (type == "subtract")
Value = Value1 - Value2;
- else if (type == "Multiply")
+ else if (type == "multiply")
Value = Value1 * Value2;
- else if (type == "Divide")
+ else if (type == "divide")
Value = safe_divide(Value1, Value2);
- else if (type == "Sine")
+ else if (type == "sine")
Value = sin(Value1);
- else if (type == "Cosine")
+ else if (type == "cosine")
Value = cos(Value1);
- else if (type == "Tangent")
+ else if (type == "tangent")
Value = tan(Value1);
- else if (type == "Arcsine")
+ else if (type == "arcsine")
Value = asin(Value1);
- else if (type == "Arccosine")
+ else if (type == "arccosine")
Value = acos(Value1);
- else if (type == "Arctangent")
+ else if (type == "arctangent")
Value = atan(Value1);
- else if (type == "Power")
+ else if (type == "power")
Value = pow(Value1, Value2);
- else if (type == "Logarithm")
+ else if (type == "logarithm")
Value = safe_log(Value1, Value2);
- else if (type == "Minimum")
+ else if (type == "minimum")
Value = min(Value1, Value2);
- else if (type == "Maximum")
+ else if (type == "maximum")
Value = max(Value1, Value2);
- else if (type == "Round")
+ else if (type == "round")
Value = floor(Value1 + 0.5);
- else if (type == "Less Than")
+ else if (type == "less_than")
Value = Value1 < Value2;
- else if (type == "Greater Than")
+ else if (type == "greater_than")
Value = Value1 > Value2;
- else if (type == "Modulo")
+ else if (type == "modulo")
Value = safe_modulo(Value1, Value2);
- else if (type == "Absolute")
+ else if (type == "absolute")
Value = fabs(Value1);
- if (Clamp)
+ 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 9ef58e4cbba..0862c34b6e1 100644
--- a/intern/cycles/kernel/shaders/node_mix.osl
+++ b/intern/cycles/kernel/shaders/node_mix.osl
@@ -277,8 +277,8 @@ color node_mix_clamp(color col)
}
shader node_mix(
- string type = "Mix",
- int Clamp = 0,
+ string type = "mix",
+ int use_clamp = 0,
float Fac = 0.5,
color Color1 = 0.0,
color Color2 = 0.0,
@@ -286,44 +286,44 @@ shader node_mix(
{
float t = clamp(Fac, 0.0, 1.0);
- if (type == "Mix")
+ if (type == "mix")
Color = node_mix_blend(t, Color1, Color2);
- if (type == "Add")
+ if (type == "add")
Color = node_mix_add(t, Color1, Color2);
- if (type == "Multiply")
+ if (type == "multiply")
Color = node_mix_mul(t, Color1, Color2);
- if (type == "Screen")
+ if (type == "screen")
Color = node_mix_screen(t, Color1, Color2);
- if (type == "Overlay")
+ if (type == "overlay")
Color = node_mix_overlay(t, Color1, Color2);
- if (type == "Subtract")
+ if (type == "subtract")
Color = node_mix_sub(t, Color1, Color2);
- if (type == "Divide")
+ if (type == "divide")
Color = node_mix_div(t, Color1, Color2);
- if (type == "Difference")
+ if (type == "difference")
Color = node_mix_diff(t, Color1, Color2);
- if (type == "Darken")
+ if (type == "darken")
Color = node_mix_dark(t, Color1, Color2);
- if (type == "Lighten")
+ if (type == "lighten")
Color = node_mix_light(t, Color1, Color2);
- if (type == "Dodge")
+ if (type == "dodge")
Color = node_mix_dodge(t, Color1, Color2);
- if (type == "Burn")
+ if (type == "burn")
Color = node_mix_burn(t, Color1, Color2);
- if (type == "Hue")
+ if (type == "hue")
Color = node_mix_hue(t, Color1, Color2);
- if (type == "Saturation")
+ if (type == "saturation")
Color = node_mix_sat(t, Color1, Color2);
- if (type == "Value")
+ if (type == "value")
Color = node_mix_val (t, Color1, Color2);
- if (type == "Color")
+ if (type == "color")
Color = node_mix_color(t, Color1, Color2);
- if (type == "Soft Light")
+ if (type == "soft_light")
Color = node_mix_soft(t, Color1, Color2);
- if (type == "Linear Light")
+ if (type == "linear_light")
Color = node_mix_linear(t, Color1, Color2);
- if (Clamp)
+ if (use_clamp)
Color = node_mix_clamp(Color);
}
diff --git a/intern/cycles/kernel/shaders/node_musgrave_texture.osl b/intern/cycles/kernel/shaders/node_musgrave_texture.osl
index 4f95dec910a..91f4fba5898 100644
--- a/intern/cycles/kernel/shaders/node_musgrave_texture.osl
+++ b/intern/cycles/kernel/shaders/node_musgrave_texture.osl
@@ -187,7 +187,7 @@ float noise_musgrave_ridged_multi_fractal(point p, float H, float lacunarity,
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",
+ string type = "fBM",
float Dimension = 2.0,
float Lacunarity = 1.0,
float Detail = 2.0,
@@ -210,15 +210,15 @@ shader node_musgrave_texture(
p = p * Scale;
- if (Type == "Multifractal")
+ if (type == "multifractal")
Fac = intensity * noise_musgrave_multi_fractal(p, dimension, lacunarity, octaves);
- else if (Type == "fBM")
+ else if (type == "fBM")
Fac = intensity * noise_musgrave_fBm(p, dimension, lacunarity, octaves);
- else if (Type == "Hybrid Multifractal")
+ else if (type == "hybrid_multifractal")
Fac = intensity * noise_musgrave_hybrid_multi_fractal(p, dimension, lacunarity, octaves, Offset, Gain);
- else if (Type == "Ridged Multifractal")
+ else if (type == "ridged_multifractal")
Fac = intensity * noise_musgrave_ridged_multi_fractal(p, dimension, lacunarity, octaves, Offset, Gain);
- else if (Type == "Hetero Terrain")
+ 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_normal.osl b/intern/cycles/kernel/shaders/node_normal.osl
index 2d04978fc72..7307971eddd 100644
--- a/intern/cycles/kernel/shaders/node_normal.osl
+++ b/intern/cycles/kernel/shaders/node_normal.osl
@@ -17,12 +17,12 @@
#include "stdosl.h"
shader node_normal(
- normal Direction = normal(0.0, 0.0, 0.0),
+ 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);
+ 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 01be566fb20..f95e9fcfe3c 100644
--- a/intern/cycles/kernel/shaders/node_normal_map.osl
+++ b/intern/cycles/kernel/shaders/node_normal_map.osl
@@ -20,14 +20,14 @@ shader node_normal_map(
normal NormalIn = N,
float Strength = 1.0,
color Color = color(0.5, 0.5, 1.0),
- string space = "Tangent",
+ 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);
- if (space == "Tangent") {
+ if (space == "tangent") {
vector tangent;
vector ninterp;
float tangent_sign;
@@ -53,20 +53,20 @@ shader node_normal_map(
Normal = normal(0, 0, 0);
}
}
- else if (space == "Object") {
+ else if (space == "object") {
Normal = normalize(transform("object", "world", vector(mcolor)));
}
- else if (space == "World") {
+ else if (space == "world") {
Normal = normalize(vector(mcolor));
}
- else if (space == "Blender Object") {
+ 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") {
+ else if (space == "blender_world") {
/* strange blender convention */
mcolor[1] = -mcolor[1];
mcolor[2] = -mcolor[2];
diff --git a/intern/cycles/kernel/shaders/node_ramp_util.h b/intern/cycles/kernel/shaders/node_ramp_util.h
new file mode 100644
index 00000000000..917fb65c6df
--- /dev/null
+++ b/intern/cycles/kernel/shaders/node_ramp_util.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2011-2013 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* NOTE: svm_ramp.h, svm_ramp_util.h and node_ramp_util.h must stay consistent */
+
+color rgb_ramp_lookup(color ramp[], float at, int interpolate, int extrapolate)
+{
+ 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);
+ }
+
+ 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;
+
+ color result = ramp[i];
+
+ if (interpolate && t > 0.0)
+ result = (1.0 - t) * result + t * ramp[i + 1];
+
+ return result;
+}
+
+float rgb_ramp_lookup(float ramp[], float at, int interpolate, int extrapolate)
+{
+ 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);
+ }
+
+ 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;
+
+ float result = ramp[i];
+
+ if (interpolate && t > 0.0)
+ result = (1.0 - t) * result + t * ramp[i + 1];
+
+ return result;
+}
diff --git a/intern/cycles/kernel/shaders/node_refraction_bsdf.osl b/intern/cycles/kernel/shaders/node_refraction_bsdf.osl
index d458ca730a4..828becf1818 100644
--- a/intern/cycles/kernel/shaders/node_refraction_bsdf.osl
+++ b/intern/cycles/kernel/shaders/node_refraction_bsdf.osl
@@ -18,7 +18,7 @@
shader node_refraction_bsdf(
color Color = 0.8,
- string distribution = "Sharp",
+ string distribution = "sharp",
float Roughness = 0.2,
float IOR = 1.45,
normal Normal = N,
@@ -27,9 +27,9 @@ shader node_refraction_bsdf(
float f = max(IOR, 1e-5);
float eta = backfacing() ? 1.0 / f : f;
- if (distribution == "Sharp")
+ if (distribution == "sharp")
BSDF = Color * refraction(Normal, eta);
- else if (distribution == "Beckmann")
+ 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 8e208e8a8f7..c8e7e4f175b 100644
--- a/intern/cycles/kernel/shaders/node_rgb_curves.osl
+++ b/intern/cycles/kernel/shaders/node_rgb_curves.osl
@@ -14,43 +14,7 @@
* limitations under the License.
*/
-#include "stdosl.h"
-#include "oslutil.h"
-
-float ramp_lookup(color ramp[], float at, int component)
-{
- int table_size = arraylength(ramp);
-
- if (at < 0.0 || at > 1.0) {
- float t0, dy;
- if (at < 0.0) {
- t0 = ramp[0][component];
- dy = t0 - ramp[1][component];
- at = -at;
- }
- else {
- t0 = ramp[table_size - 1][component];
- dy = t0 - ramp[table_size - 2][component];
- at = at - 1.0;
- }
- return t0 + dy * at * (table_size - 1);
- }
-
- float 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;
-
- float result = ramp[i][component];
-
- if (t > 0.0)
- result = (1.0 - t) * result + t * ramp[i + 1][component];
-
- return result;
-}
+#include "node_ramp_util.h"
shader node_rgb_curves(
color ramp[] = {0.0},
@@ -63,9 +27,13 @@ shader node_rgb_curves(
{
color c = (ColorIn - color(min_x, min_x, min_x)) / (max_x - min_x);
- ColorOut[0] = ramp_lookup(ramp, c[0], 0);
- ColorOut[1] = ramp_lookup(ramp, c[1], 1);
- ColorOut[2] = ramp_lookup(ramp, c[2], 2);
+ 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);
+
+ ColorOut[0] = r[0];
+ ColorOut[1] = g[1];
+ ColorOut[2] = b[2];
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 2ab6b6778b7..24b8728b999 100644
--- a/intern/cycles/kernel/shaders/node_rgb_ramp.osl
+++ b/intern/cycles/kernel/shaders/node_rgb_ramp.osl
@@ -14,33 +14,18 @@
* limitations under the License.
*/
-#include "stdosl.h"
-#include "oslutil.h"
+#include "node_ramp_util.h"
shader node_rgb_ramp(
color ramp_color[] = {0.0},
float ramp_alpha[] = {0.0},
- int ramp_interpolate = 1,
+ int interpolate = 1,
float Fac = 0.0,
output color Color = 0.0,
output float Alpha = 1.0)
{
- int table_size = arraylength(ramp_color);
- float f = clamp(Fac, 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;
-
- Color = ramp_color[i];
- Alpha = ramp_alpha[i];
-
- if (ramp_interpolate && t > 0.0) {
- Color = (1.0 - t) * Color + t * ramp_color[i + 1];
- Alpha = (1.0 - t) * Alpha + t * ramp_alpha[i + 1];
- }
+ 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
new file mode 100644
index 00000000000..903dfcdc881
--- /dev/null
+++ b/intern/cycles/kernel/shaders/node_rgb_to_bw.osl
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2011-2013 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "stdosl.h"
+
+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;
+}
+
diff --git a/intern/cycles/kernel/shaders/node_sky_texture.osl b/intern/cycles/kernel/shaders/node_sky_texture.osl
index 05eed23bea8..a6c187d15f2 100644
--- a/intern/cycles/kernel/shaders/node_sky_texture.osl
+++ b/intern/cycles/kernel/shaders/node_sky_texture.osl
@@ -111,7 +111,7 @@ 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 sky_model = "Hosek / Wilkie",
+ string type = "hosek_wilkie",
float theta = 0.0,
float phi = 0.0,
color radiance = color(0.0, 0.0, 0.0),
@@ -125,7 +125,7 @@ shader node_sky_texture(
if (use_mapping)
p = transform(mapping, p);
- if (sky_model == "Hosek / Wilkie")
+ 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 a67333c5d4e..5ba8f34021d 100644
--- a/intern/cycles/kernel/shaders/node_subsurface_scattering.osl
+++ b/intern/cycles/kernel/shaders/node_subsurface_scattering.osl
@@ -22,13 +22,13 @@ shader node_subsurface_scattering(
vector Radius = vector(0.1, 0.1, 0.1),
float TextureBlur = 0.0,
float Sharpness = 0.0,
- string Falloff = "Cubic",
+ string falloff = "cubic",
normal Normal = N,
output closure color BSSRDF = 0)
{
- if (Falloff == "Gaussian")
+ if (falloff == "gaussian")
BSSRDF = Color * bssrdf_gaussian(Normal, Scale * Radius, TextureBlur);
- else if (Falloff == "Cubic")
+ else if (falloff == "cubic")
BSSRDF = Color * bssrdf_cubic(Normal, Scale * Radius, TextureBlur, Sharpness);
else
BSSRDF = Color * bssrdf_burley(Normal, Scale * Radius, TextureBlur, Color);
diff --git a/intern/cycles/kernel/shaders/node_tangent.osl b/intern/cycles/kernel/shaders/node_tangent.osl
index 53a47396f9f..c527070a2c8 100644
--- a/intern/cycles/kernel/shaders/node_tangent.osl
+++ b/intern/cycles/kernel/shaders/node_tangent.osl
@@ -19,24 +19,24 @@
shader node_tangent(
normal NormalIn = N,
string attr_name = "geom:tangent",
- string direction_type = "Radial",
- string axis = "Z",
+ string direction_type = "radial",
+ string axis = "z",
output normal Tangent = normalize(dPdu))
{
vector T;
- if (direction_type == "UV Map") {
+ if (direction_type == "uv_map") {
getattribute(attr_name, T);
}
- else if (direction_type == "Radial") {
+ else if (direction_type == "radial") {
point generated;
if (!getattribute("geom:generated", generated))
generated = P;
- if (axis == "X")
+ if (axis == "x")
T = vector(0.0, -(generated[2] - 0.5), (generated[1] - 0.5));
- else if (axis == "Y")
+ 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);
diff --git a/intern/cycles/kernel/shaders/node_toon_bsdf.osl b/intern/cycles/kernel/shaders/node_toon_bsdf.osl
index 75c5d06f847..ae68a463e46 100644
--- a/intern/cycles/kernel/shaders/node_toon_bsdf.osl
+++ b/intern/cycles/kernel/shaders/node_toon_bsdf.osl
@@ -18,15 +18,15 @@
shader node_toon_bsdf(
color Color = 0.8,
- string component = "Diffuse",
+ string component = "diffuse",
float Size = 0.5,
float Smooth = 0.0,
normal Normal = N,
output closure color BSDF = 0)
{
- if (component == "Diffuse")
+ if (component == "diffuse")
BSDF = Color * diffuse_toon(Normal, Size, Smooth);
- else if (component == "Glossy")
+ else if (component == "glossy")
BSDF = Color * glossy_toon(Normal, Size, Smooth);
}
diff --git a/intern/cycles/kernel/shaders/node_uv_map.osl b/intern/cycles/kernel/shaders/node_uv_map.osl
index 77e2e8d12d7..b46b2e73457 100644
--- a/intern/cycles/kernel/shaders/node_uv_map.osl
+++ b/intern/cycles/kernel/shaders/node_uv_map.osl
@@ -18,7 +18,7 @@
shader node_uv_map(
int from_dupli = 0,
- string name = "",
+ string attribute = "",
string bump_offset = "center",
output point UV = point(0.0, 0.0, 0.0))
{
@@ -26,10 +26,10 @@ shader node_uv_map(
getattribute("geom:dupli_uv", UV);
}
else {
- if (name == "")
+ if (attribute == "")
getattribute("geom:uv", UV);
else
- getattribute(name, UV);
+ getattribute(attribute, UV);
}
if (bump_offset == "dx") {
diff --git a/intern/cycles/kernel/shaders/node_vector_curves.osl b/intern/cycles/kernel/shaders/node_vector_curves.osl
index cff4efe1d98..d92fa11d439 100644
--- a/intern/cycles/kernel/shaders/node_vector_curves.osl
+++ b/intern/cycles/kernel/shaders/node_vector_curves.osl
@@ -14,43 +14,7 @@
* limitations under the License.
*/
-#include "stdosl.h"
-#include "oslutil.h"
-
-float ramp_lookup(color ramp[], float at, int component)
-{
- int table_size = arraylength(ramp);
-
- if (at < 0.0 || at > 1.0) {
- float t0, dy;
- if (at < 0.0) {
- t0 = ramp[0][component];
- dy = t0 - ramp[1][component];
- at = -at;
- }
- else {
- t0 = ramp[table_size - 1][component];
- dy = t0 - ramp[table_size - 2][component];
- at = at - 1.0;
- }
- return t0 + dy * at * (table_size - 1);
- }
-
- float 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;
-
- float result = ramp[i][component];
-
- if (t > 0.0)
- result = (1.0 - t) * result + t * ramp[i + 1][component];
-
- return result;
-}
+#include "node_ramp_util.h"
shader node_vector_curves(
color ramp[] = {0.0},
@@ -63,9 +27,13 @@ shader node_vector_curves(
{
vector c = (VectorIn - vector(min_x, min_x, min_x)) / (max_x - min_x);
- VectorOut[0] = ramp_lookup(ramp, c[0], 0);
- VectorOut[1] = ramp_lookup(ramp, c[1], 1);
- VectorOut[2] = ramp_lookup(ramp, c[2], 2);
+ 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 = mix(VectorIn, VectorOut, Fac);
}
diff --git a/intern/cycles/kernel/shaders/node_vector_math.osl b/intern/cycles/kernel/shaders/node_vector_math.osl
index f83412dc0f7..a7e3637402e 100644
--- a/intern/cycles/kernel/shaders/node_vector_math.osl
+++ b/intern/cycles/kernel/shaders/node_vector_math.osl
@@ -17,33 +17,33 @@
#include "stdosl.h"
shader node_vector_math(
- string type = "Add",
+ 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") {
+ if (type == "add") {
Vector = Vector1 + Vector2;
Value = (abs(Vector[0]) + abs(Vector[1]) + abs(Vector[2])) / 3.0;
}
- else if (type == "Subtract") {
+ else if (type == "subtract") {
Vector = Vector1 - Vector2;
Value = (abs(Vector[0]) + abs(Vector[1]) + abs(Vector[2])) / 3.0;
}
- else if (type == "Average") {
+ else if (type == "average") {
Value = length(Vector1 + Vector2);
Vector = normalize(Vector1 + Vector2);
}
- else if (type == "Dot Product") {
+ else if (type == "dot_product") {
Value = dot(Vector1, Vector2);
}
- else if (type == "Cross Product") {
+ else if (type == "cross_product") {
vector c = cross(Vector1, Vector2);
Value = length(c);
Vector = normalize(c);
}
- else if (type == "Normalize") {
+ 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 8ebaa31ab25..afb95b340d1 100644
--- a/intern/cycles/kernel/shaders/node_vector_transform.osl
+++ b/intern/cycles/kernel/shaders/node_vector_transform.osl
@@ -17,18 +17,18 @@
#include "stdosl.h"
shader node_vector_transform(
- string type = "Vector",
+ 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") {
+ if (type == "vector" || type == "normal") {
VectorOut = transform(convert_from, convert_to, VectorIn);
- if (type == "Normal")
+ if (type == "normal")
VectorOut = normalize(VectorOut);
}
- else if (type == "Point") {
+ else if (type == "point") {
point Point = (point)VectorIn;
VectorOut = transform(convert_from, convert_to, Point);
}
diff --git a/intern/cycles/kernel/shaders/node_voronoi_texture.osl b/intern/cycles/kernel/shaders/node_voronoi_texture.osl
index 29e143ae207..0c3b95ae4d0 100644
--- a/intern/cycles/kernel/shaders/node_voronoi_texture.osl
+++ b/intern/cycles/kernel/shaders/node_voronoi_texture.osl
@@ -22,7 +22,7 @@
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 coloring = "intensity",
float Scale = 5.0,
point Vector = P,
output float Fac = 0.0,
@@ -40,7 +40,7 @@ shader node_voronoi_texture(
voronoi(p * Scale, 1.0, da, pa);
/* Colored output */
- if (Coloring == "Intensity") {
+ if (coloring == "intensity") {
Fac = fabs(da[0]);
Color = color(Fac);
}
diff --git a/intern/cycles/kernel/shaders/node_wave_texture.osl b/intern/cycles/kernel/shaders/node_wave_texture.osl
index 59f61d3b46a..71bc9324705 100644
--- a/intern/cycles/kernel/shaders/node_wave_texture.osl
+++ b/intern/cycles/kernel/shaders/node_wave_texture.osl
@@ -23,10 +23,10 @@ float wave(point p, string type, string profile, float detail, float distortion,
{
float n = 0.0;
- if (type == "Bands") {
+ if (type == "bands") {
n = (p[0] + p[1] + p[2]) * 10.0;
}
- else if (type == "Rings") {
+ else if (type == "rings") {
n = length(p) * 20.0;
}
@@ -34,7 +34,7 @@ float wave(point p, string type, string profile, float detail, float distortion,
n = n + (distortion * noise_turbulence(p * dscale, detail, 0));
}
- if (profile == "Sine") {
+ if (profile == "sine") {
return 0.5 + 0.5 * sin(n);
}
else {
@@ -48,8 +48,8 @@ float wave(point p, string type, string profile, float detail, float distortion,
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",
+ string type = "bands",
+ string profile = "sine",
float Scale = 5.0,
float Distortion = 0.0,
float Detail = 2.0,
@@ -63,7 +63,7 @@ shader node_wave_texture(
if (use_mapping)
p = transform(mapping, p);
- Fac = wave(p * Scale, Type, Profile, Detail, Distortion, DetailScale);
+ Fac = wave(p * Scale, type, profile, Detail, Distortion, DetailScale);
Color = Fac;
}
diff --git a/intern/cycles/kernel/shaders/stdosl.h b/intern/cycles/kernel/shaders/stdosl.h
index ba88f0f4a79..fc0b94bfdce 100644
--- a/intern/cycles/kernel/shaders/stdosl.h
+++ b/intern/cycles/kernel/shaders/stdosl.h
@@ -527,6 +527,9 @@ closure color transparent() BUILTIN;
closure color microfacet_ggx(normal N, float ag) BUILTIN;
closure color microfacet_ggx_aniso(normal N, vector T, float ax, float ay) BUILTIN;
closure color microfacet_ggx_refraction(normal N, float ag, float eta) BUILTIN;
+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_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;
diff --git a/intern/cycles/kernel/split/kernel_shader_eval.h b/intern/cycles/kernel/split/kernel_shader_eval.h
index e816a818915..cef64bf5f36 100644
--- a/intern/cycles/kernel/split/kernel_shader_eval.h
+++ b/intern/cycles/kernel/split/kernel_shader_eval.h
@@ -65,6 +65,6 @@ ccl_device void kernel_shader_eval(
isect,
&ray);
float rbsdf = path_state_rng_1D_for_decision(kg, rng, state, PRNG_BSDF);
- shader_eval_surface(kg, sd, state, rbsdf, state->flag, SHADER_CONTEXT_MAIN);
+ shader_eval_surface(kg, sd, rng, state, rbsdf, state->flag, SHADER_CONTEXT_MAIN);
}
}
diff --git a/intern/cycles/kernel/split/kernel_split_common.h b/intern/cycles/kernel/split/kernel_split_common.h
index e1c7e2cea99..88d6dab04d0 100644
--- a/intern/cycles/kernel/split/kernel_split_common.h
+++ b/intern/cycles/kernel/split/kernel_split_common.h
@@ -31,6 +31,7 @@
#include "kernel_camera.h"
#include "geom/geom.h"
+#include "bvh/bvh.h"
#include "kernel_accumulate.h"
#include "kernel_shader.h"
diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h
index 543e31bcb35..502994e71f1 100644
--- a/intern/cycles/kernel/svm/svm.h
+++ b/intern/cycles/kernel/svm/svm.h
@@ -142,6 +142,7 @@ CCL_NAMESPACE_END
#include "svm_noise.h"
#include "svm_texture.h"
+#include "svm_color_util.h"
#include "svm_math_util.h"
#include "svm_attribute.h"
@@ -404,10 +405,8 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ccl_a
#if NODES_GROUP(NODE_GROUP_LEVEL_3)
case NODE_RGB_CURVES:
- svm_node_rgb_curves(kg, sd, stack, node, &offset);
- break;
case NODE_VECTOR_CURVES:
- svm_node_vector_curves(kg, sd, stack, node, &offset);
+ svm_node_curves(kg, sd, stack, node, &offset);
break;
case NODE_TANGENT:
svm_node_tangent(kg, sd, stack, node);
diff --git a/intern/cycles/kernel/svm/svm_attribute.h b/intern/cycles/kernel/svm/svm_attribute.h
index 63bbb27d873..6c557684099 100644
--- a/intern/cycles/kernel/svm/svm_attribute.h
+++ b/intern/cycles/kernel/svm/svm_attribute.h
@@ -28,9 +28,7 @@ ccl_device void svm_node_attr_init(KernelGlobals *kg, ShaderData *sd,
/* find attribute by unique id */
uint id = node.y;
uint attr_offset = ccl_fetch(sd, object)*kernel_data.bvh.attributes_map_stride;
-#ifdef __HAIR__
- attr_offset = (ccl_fetch(sd, type) & PRIMITIVE_ALL_CURVE)? attr_offset + ATTR_PRIM_CURVE: attr_offset;
-#endif
+ attr_offset += attribute_primitive_type(kg, sd);
uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
while(attr_map.x != id) {
diff --git a/intern/cycles/kernel/svm/svm_brightness.h b/intern/cycles/kernel/svm/svm_brightness.h
index e4d545a00ae..d71b0ee0b61 100644
--- a/intern/cycles/kernel/svm/svm_brightness.h
+++ b/intern/cycles/kernel/svm/svm_brightness.h
@@ -25,12 +25,7 @@ ccl_device void svm_node_brightness(ShaderData *sd, float *stack, uint in_color,
float brightness = stack_load_float(stack, bright_offset);
float contrast = stack_load_float(stack, contrast_offset);
- 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 = svm_brightness_contrast(color, brightness, contrast);
if(stack_valid(out_color))
stack_store_float3(stack, out_color, color);
diff --git a/intern/cycles/kernel/svm/svm_closure.h b/intern/cycles/kernel/svm/svm_closure.h
index 6161bc5d914..2f886308a64 100644
--- a/intern/cycles/kernel/svm/svm_closure.h
+++ b/intern/cycles/kernel/svm/svm_closure.h
@@ -18,104 +18,44 @@ CCL_NAMESPACE_BEGIN
/* Closure Nodes */
-ccl_device void svm_node_glass_setup(ShaderData *sd, ShaderClosure *sc, 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) {
- sc->data0 = eta;
- sc->data1 = 0.0f;
- sc->data2 = 0.0f;
- ccl_fetch(sd, flag) |= bsdf_refraction_setup(sc);
+ bsdf->alpha_y = 0.0f;
+ bsdf->alpha_x = 0.0f;
+ bsdf->ior = eta;
+ ccl_fetch(sd, flag) |= bsdf_refraction_setup(bsdf);
}
else {
- sc->data0 = 0.0f;
- sc->data1 = 0.0f;
- sc->data2 = 0.0f;
- ccl_fetch(sd, flag) |= bsdf_reflection_setup(sc);
+ bsdf->alpha_y = 0.0f;
+ bsdf->alpha_x = 0.0f;
+ bsdf->ior = 0.0f;
+ ccl_fetch(sd, flag) |= bsdf_reflection_setup(bsdf);
}
}
else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID) {
- sc->data0 = roughness;
- sc->data1 = roughness;
- sc->data2 = eta;
+ bsdf->alpha_x = roughness;
+ bsdf->alpha_y = roughness;
+ bsdf->ior = eta;
if(refract)
- ccl_fetch(sd, flag) |= bsdf_microfacet_beckmann_refraction_setup(sc);
+ ccl_fetch(sd, flag) |= bsdf_microfacet_beckmann_refraction_setup(bsdf);
else
- ccl_fetch(sd, flag) |= bsdf_microfacet_beckmann_setup(sc);
+ ccl_fetch(sd, flag) |= bsdf_microfacet_beckmann_setup(bsdf);
}
else {
- sc->data0 = roughness;
- sc->data1 = roughness;
- sc->data2 = eta;
+ bsdf->alpha_x = roughness;
+ bsdf->alpha_y = roughness;
+ bsdf->ior = eta;
if(refract)
- ccl_fetch(sd, flag) |= bsdf_microfacet_ggx_refraction_setup(sc);
+ ccl_fetch(sd, flag) |= bsdf_microfacet_ggx_refraction_setup(bsdf);
else
- ccl_fetch(sd, flag) |= bsdf_microfacet_ggx_setup(sc);
+ ccl_fetch(sd, flag) |= bsdf_microfacet_ggx_setup(bsdf);
}
}
-ccl_device_inline ShaderClosure *svm_node_closure_get_non_bsdf(ShaderData *sd, ClosureType type, float mix_weight)
-{
- ShaderClosure *sc = ccl_fetch_array(sd, closure, ccl_fetch(sd, num_closure));
-
- if(ccl_fetch(sd, num_closure) < MAX_CLOSURE) {
- sc->weight *= mix_weight;
- sc->type = type;
- sc->data0 = 0.0f;
- sc->data1 = 0.0f;
- sc->data2 = 0.0f;
-#ifdef __OSL__
- sc->prim = NULL;
-#endif
- ccl_fetch(sd, num_closure)++;
- return sc;
- }
-
- return NULL;
-}
-
-ccl_device_inline ShaderClosure *svm_node_closure_get_bsdf(ShaderData *sd, float mix_weight)
-{
- ShaderClosure *sc = ccl_fetch_array(sd, closure, ccl_fetch(sd, num_closure));
-
- float3 weight = sc->weight * mix_weight;
- float sample_weight = fabsf(average(weight));
-
- if(sample_weight > CLOSURE_WEIGHT_CUTOFF && ccl_fetch(sd, num_closure) < MAX_CLOSURE) {
- sc->weight = weight;
- sc->sample_weight = sample_weight;
- ccl_fetch(sd, num_closure)++;
-#ifdef __OSL__
- sc->prim = NULL;
-#endif
- return sc;
- }
-
- return NULL;
-}
-
-ccl_device_inline ShaderClosure *svm_node_closure_get_absorption(ShaderData *sd, float mix_weight)
-{
- ShaderClosure *sc = ccl_fetch_array(sd, closure, ccl_fetch(sd, num_closure));
-
- float3 weight = (make_float3(1.0f, 1.0f, 1.0f) - sc->weight) * mix_weight;
- float sample_weight = fabsf(average(weight));
-
- if(sample_weight > CLOSURE_WEIGHT_CUTOFF && ccl_fetch(sd, num_closure) < MAX_CLOSURE) {
- sc->weight = weight;
- sc->sample_weight = sample_weight;
- ccl_fetch(sd, num_closure)++;
-#ifdef __OSL__
- sc->prim = NULL;
-#endif
- return sc;
- }
-
- return NULL;
-}
-
ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int path_flag, int *offset)
{
uint type, param1_offset, param2_offset;
@@ -136,17 +76,13 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
float param2 = (stack_valid(param2_offset))? stack_load_float(stack, param2_offset): __uint_as_float(node.w);
switch(type) {
-#ifndef __SPLIT_KERNEL__
-# define sc_next(sc) sc++
-#else
-# define sc_next(sc) sc = ccl_fetch_array(sd, closure, ccl_fetch(sd, num_closure))
-#endif
case CLOSURE_BSDF_DISNEY_ID: {
uint specular_offset, roughness_offset, specularTint_offset, anisotropic_offset, sheen_offset,
sheenTint_offset, clearcoat_offset, clearcoatGloss_offset, eta_offset, transparency_offset, refr_roughness_offset;
uint tmp0;
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, &specularTint_offset, &anisotropic_offset);
decode_node_uchar4(data_node.w, &sheen_offset, &sheenTint_offset, &clearcoat_offset, &clearcoatGloss_offset);
decode_node_uchar4(data_node2.x, &eta_offset, &transparency_offset, &refr_roughness_offset, &tmp0);
@@ -167,7 +103,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
refr_roughness = 1.0f - (1.0f - roughness) * (1.0f - refr_roughness);
float eta = fmaxf(stack_load_float(stack, eta_offset), 1e-5f);
- eta = (ccl_fetch(sd, flag) & SD_BACKFACING) ? 1.0f / eta : eta;
+ float ior = (ccl_fetch(sd, flag) & SD_BACKFACING) ? 1.0f / eta : eta;
// calculate fresnel for refraction
float cosNO = dot(N, ccl_fetch(sd, I));
@@ -193,8 +129,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
float3 subsurfaceColor = 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));
- ShaderClosure *sc = ccl_fetch_array(sd, closure, ccl_fetch(sd, num_closure));
- float3 weight = sc->weight * mix_weight;
+ float3 weight = ccl_fetch(sd, svm_closure_weight) * mix_weight;
#ifdef __SUBSURFACE__
float3 albedo = subsurfaceColor; //baseColor;
@@ -207,7 +142,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
if (path_flag & PATH_RAY_DIFFUSE_ANCESTOR)
subsurface = 0.0f;
- if (subsurf_sample_weight > CLOSURE_WEIGHT_CUTOFF && ccl_fetch(sd, num_closure) + 2 < MAX_CLOSURE) {
+ if (subsurf_sample_weight > CLOSURE_WEIGHT_CUTOFF) {
/* radius * scale */
float3 radius = make_float3(1.0f, 1.0f, 1.0f) * subsurface;
/* sharpness */
@@ -216,317 +151,251 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
float texture_blur = 0.0f;
/* create one closure per color channel */
- if (fabsf(subsurf_weight.x) > 0.0f) {
- sc->weight = make_float3(subsurf_weight.x, 0.0f, 0.0f);
- sc->sample_weight = subsurf_sample_weight;
- sc->data0 = radius.x;
- sc->data1 = texture_blur;
- sc->data2 = albedo.x;
- sc->data3 = roughness;
- sc->T.x = sharpness;
- sc->color0 = baseColor;
-# ifdef __OSL__
- sc->prim = NULL;
-# endif
- sc->N = N;
- ccl_fetch(sd, flag) |= bssrdf_setup(sc, (ClosureType)CLOSURE_BSSRDF_DISNEY_ID);
-
- ccl_fetch(sd, num_closure)++;
- sc_next(sc);
+ Bssrdf *bssrdf = bssrdf_alloc(sd, make_float3(subsurf_weight.x, 0.0f, 0.0f));
+ if (bssrdf) {
+ bssrdf->sample_weight = subsurf_sample_weight;
+ bssrdf->radius = radius.x;
+ bssrdf->texture_blur = texture_blur;
+ bssrdf->albedo = albedo.x;
+ bssrdf->sharpness = sharpness;
+ bssrdf->N = N;
+ bssrdf->baseColor = baseColor;
+ bssrdf->roughness = roughness;
+ ccl_fetch(sd, flag) |= bssrdf_setup(bssrdf, (ClosureType)CLOSURE_BSSRDF_DISNEY_ID);
}
- if (fabsf(subsurf_weight.y) > 0.0f) {
- sc->weight = make_float3(0.0f, subsurf_weight.y, 0.0f);
- sc->sample_weight = subsurf_sample_weight;
- sc->data0 = radius.y;
- sc->data1 = texture_blur;
- sc->data2 = albedo.y;
- sc->data3 = roughness;
- sc->T.x = sharpness;
- sc->color0 = baseColor;
-# ifdef __OSL__
- sc->prim = NULL;
-# endif
- sc->N = N;
- ccl_fetch(sd, flag) |= bssrdf_setup(sc, (ClosureType)CLOSURE_BSSRDF_DISNEY_ID);
-
- ccl_fetch(sd, num_closure)++;
- sc_next(sc);
+ bssrdf = bssrdf_alloc(sd, make_float3(0.0f, subsurf_weight.y, 0.0f));
+ if (bssrdf) {
+ bssrdf->sample_weight = subsurf_sample_weight;
+ bssrdf->radius = radius.y;
+ bssrdf->texture_blur = texture_blur;
+ bssrdf->albedo = albedo.y;
+ bssrdf->sharpness = sharpness;
+ bssrdf->N = N;
+ bssrdf->baseColor = baseColor;
+ bssrdf->roughness = roughness;
+ ccl_fetch(sd, flag) |= bssrdf_setup(bssrdf, (ClosureType)CLOSURE_BSSRDF_DISNEY_ID);
}
- if (fabsf(subsurf_weight.z) > 0.0f) {
- sc->weight = make_float3(0.0f, 0.0f, subsurf_weight.z);
- sc->sample_weight = subsurf_sample_weight;
- sc->data0 = radius.z;
- sc->data1 = texture_blur;
- sc->data2 = albedo.z;
- sc->data3 = roughness;
- sc->T.x = sharpness;
- sc->color0 = baseColor;
-# ifdef __OSL__
- sc->prim = NULL;
-# endif
- sc->N = N;
- ccl_fetch(sd, flag) |= bssrdf_setup(sc, (ClosureType)CLOSURE_BSSRDF_DISNEY_ID);
-
- ccl_fetch(sd, num_closure)++;
- sc_next(sc);
+ bssrdf = bssrdf_alloc(sd, make_float3(0.0f, 0.0f, subsurf_weight.z));
+ if (bssrdf) {
+ bssrdf->sample_weight = subsurf_sample_weight;
+ bssrdf->radius = radius.z;
+ bssrdf->texture_blur = texture_blur;
+ bssrdf->albedo = albedo.z;
+ bssrdf->sharpness = sharpness;
+ bssrdf->N = N;
+ bssrdf->baseColor = baseColor;
+ bssrdf->roughness = roughness;
+ ccl_fetch(sd, flag) |= bssrdf_setup(bssrdf, (ClosureType)CLOSURE_BSSRDF_DISNEY_ID);
}
}
#else
/* diffuse */
if (diffuse_weight > 0.0f) {
- if (ccl_fetch(sd, num_closure) < MAX_CLOSURE) {
- float3 diff_weight = weight * diffuse_weight;
- float diff_sample_weight = fabsf(average(diff_weight));
-
- if (diff_sample_weight > CLOSURE_WEIGHT_CUTOFF) {
- sc->weight = diff_weight;
- sc->sample_weight = diff_sample_weight;
- ccl_fetch(sd, num_closure)++;
-#ifdef __OSL__
- sc->prim = NULL;
-#endif
+ float3 diff_weight = weight * diffuse_weight;
+ float diff_sample_weight = fabsf(average(diff_weight));
- sc->N = N;
+ DisneyDiffuseBsdf *bsdf = (DisneyDiffuseBsdf*)bsdf_alloc(sd, sizeof(DisneyDiffuseBsdf), diff_weight);
- sc->color0 = baseColor;
- sc->data0 = roughness;
+ if (bsdf) {
+ bsdf->N = N;
+ bsdf->baseColor = baseColor;
+ bsdf->roughness = roughness;
- ccl_fetch(sd, flag) |= bsdf_disney_diffuse_setup(sc);
- sc_next(sc);
- }
+ /* setup bsdf */
+ ccl_fetch(sd, flag) |= bsdf_disney_diffuse_setup(bsdf);
}
}
#endif
/* sheen */
if (diffuse_weight > 0.0f && sheen != 0.0f) {
- if (ccl_fetch(sd, num_closure) < MAX_CLOSURE) {
- float3 sheen_weight = weight * diffuse_weight;
- float sheen_sample_weight = fabsf(average(sheen_weight));
-
- if (sheen_sample_weight > CLOSURE_WEIGHT_CUTOFF) {
- sc->weight = sheen_weight;
- sc->sample_weight = sheen_sample_weight;
- ccl_fetch(sd, num_closure)++;
-#ifdef __OSL__
- sc->prim = NULL;
-#endif
+ float3 sheen_weight = weight * diffuse_weight;
+ float sheen_sample_weight = fabsf(average(sheen_weight));
- sc->N = N;
+ DisneySheenBsdf *bsdf = (DisneySheenBsdf*)bsdf_alloc(sd, sizeof(DisneySheenBsdf), weight);
- sc->color0 = baseColor;
- sc->data0 = sheen;
- sc->data1 = sheenTint;
+ if (bsdf) {
+ bsdf->N = N;
+ bsdf->baseColor = baseColor;
+ bsdf->sheen = sheen;
+ bsdf->sheenTint = sheenTint;
- ccl_fetch(sd, flag) |= bsdf_disney_sheen_setup(sc);
- sc_next(sc);
- }
- }
+ /* setup bsdf */
+ ccl_fetch(sd, flag) |= bsdf_disney_sheen_setup(bsdf);
+ }
}
/* specular reflection */
- if (specular != 0.0f || metallic != 0.0f) {
- if (ccl_fetch(sd, num_closure) < MAX_CLOSURE) {
- float3 spec_weight = weight * specular_weight;
- float spec_sample_weight = fabsf(average(spec_weight));
-
- if (spec_sample_weight > CLOSURE_WEIGHT_CUTOFF) {
- sc->weight = spec_weight;
- sc->sample_weight = spec_sample_weight;
- ccl_fetch(sd, num_closure)++;
-#ifdef __OSL__
- sc->prim = NULL;
+#ifdef __CAUSTICS_TRICKS__
+ if (kernel_data.integrator.caustics_reflective || (path_flag & PATH_RAY_DIFFUSE) == 0) {
#endif
+ if (specular != 0.0f || metallic != 0.0f) {
+ float3 spec_weight = weight * specular_weight;
- sc->N = N;
- sc->T = stack_load_float3(stack, data_node.y);
+ MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), spec_weight);
+ MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
- sc->color0 = baseColor;
- sc->data0 = metallic;
- sc->data1 = specular; // (1.0f - transparency) * specular + transparency * specular * 12.5f/* equals division by 0.08f */;
- sc->data2 = specularTint;
- sc->data3 = roughness;
- sc->data4 = anisotropic;
+ if (bsdf && extra) {
+ bsdf->N = N;
+ bsdf->ior = 0.0f;
+ bsdf->T = T;
+ bsdf->extra = extra;
- ccl_fetch(sd, flag) |= bsdf_disney_specular_setup(sc);
- sc_next(sc);
- }
- }
- }
+ float aspect = safe_sqrtf(1.0f - anisotropic * 0.9f);
+ float r2 = roughness * roughness;
- /* BSDF */
- if (specular_weight < 1.0f) {
- if (ccl_fetch(sd, num_closure) + 1 < MAX_CLOSURE) {
-#ifdef __CAUSTICS_TRICKS__
- if (!kernel_data.integrator.caustics_reflective &&
- !kernel_data.integrator.caustics_refractive && (path_flag & PATH_RAY_DIFFUSE))
- {
- break;
- }
-#endif
+ bsdf->alpha_x = fmaxf(0.001f, r2 / aspect);
+ bsdf->alpha_y = fmaxf(0.001f, r2 * aspect);
- /* reflection */
- float3 spec_refl_weight = weight * (1.0f - specular_weight) * fresnel;
- float spec_refl_sample_weight = fabsf(average(spec_refl_weight));
+ float m_cdlum = 0.3f * baseColor.x + 0.6f * baseColor.y + 0.1f * baseColor.z; // luminance approx.
+ float3 m_ctint = m_cdlum > 0.0f ? baseColor / 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 - specularTint) + m_ctint * specularTint;
- if (spec_refl_sample_weight > CLOSURE_WEIGHT_CUTOFF) {
- sc->weight = spec_refl_weight;
- sc->sample_weight = spec_refl_sample_weight;
- ccl_fetch(sd, num_closure)++;
-#ifdef __OSL__
- sc->prim = NULL;
-#endif
+ bsdf->extra->cspec0 = (specular * 0.08f * tmp_col) * (1.0f - metallic) + baseColor * metallic;
+ bsdf->extra->color = baseColor;
-#ifdef __CAUSTICS_TRICKS__
- if (kernel_data.integrator.caustics_reflective || (path_flag & PATH_RAY_DIFFUSE) == 0)
+ /* setup bsdf */
+#ifdef __DISNEY_SPECULAR_MULTI_GGX__
+ ccl_fetch(sd, flag) |= bsdf_microfacet_multi_ggx_aniso_setup(bsdf, true);
+#else
+ ccl_fetch(sd, flag) |= bsdf_microfacet_ggx_aniso_setup(bsdf, true);
#endif
- {
- sc->N = N;
- sc->T = stack_load_float3(stack, data_node.y);
-
- sc->color0 = baseColor;
- sc->data0 = 0.0f;
- sc->data1 = 12.5f; // == (1.0f / 0.08f)
- sc->data2 = specularTint;
- sc->data3 = roughness;
- sc->data4 = 0.0f;
-
- ccl_fetch(sd, flag) |= bsdf_disney_specular_setup(sc);
- sc_next(sc);
- }
}
+ }
+#ifdef __CAUSTICS_TRICKS__
+ }
+#endif
+ /* BSDF */
#ifdef __CAUSTICS_TRICKS__
- if (!kernel_data.integrator.caustics_refractive && (path_flag & PATH_RAY_DIFFUSE))
- break;
+ if (kernel_data.integrator.caustics_reflective || kernel_data.integrator.caustics_refractive || (path_flag & PATH_RAY_DIFFUSE) == 0) {
#endif
+ if (specular_weight < 1.0f) {
+ float3 glass_weight = baseColor * weight * (1.0f - specular_weight);
- /* refraction */
- float3 spec_refr_weight = baseColor * weight * (1.0f - specular_weight) * (1.0f - fresnel);
- float spec_refr_sample_weight = fabsf(average(spec_refr_weight));
+ MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), glass_weight);
+ MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
- if (spec_refr_sample_weight > CLOSURE_WEIGHT_CUTOFF) {
- sc->weight = spec_refr_weight;
- sc->sample_weight = spec_refr_sample_weight;
- ccl_fetch(sd, num_closure)++;
-#ifdef __OSL__
- sc->prim = NULL;
-#endif
+ if (bsdf && extra) {
+ bsdf->N = N;
+ bsdf->extra = extra;
+ bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
- sc->N = N;
+ bsdf->alpha_x = refr_roughness * refr_roughness;
+ bsdf->alpha_y = refr_roughness * refr_roughness;
+ bsdf->ior = ior;
- sc->data0 = refr_roughness * refr_roughness;
- sc->data1 = refr_roughness * refr_roughness;
- sc->data2 = eta;
+ bsdf->extra->color = baseColor;
- ccl_fetch(sd, flag) |= bsdf_microfacet_ggx_refraction_setup(sc);
- sc_next(sc);
+ /* setup bsdf */
+ ccl_fetch(sd, flag) |= bsdf_microfacet_multi_ggx_glass_setup(bsdf);
}
}
+#ifdef __CAUSTICS_TRICKS__
}
+#endif
/* clearcoat */
- if (clearcoat > 0.0f) {
- if (ccl_fetch(sd, num_closure) < MAX_CLOSURE) {
+#ifdef __CAUSTICS_TRICKS__
+ if (kernel_data.integrator.caustics_reflective || (path_flag & PATH_RAY_DIFFUSE) == 0) {
+#endif
+ if (clearcoat > 0.0f) {
float3 clearcoat_weight = weight;
float clearcoat_sample_weight = fabsf(average(clearcoat_weight));
- if (clearcoat_sample_weight > CLOSURE_WEIGHT_CUTOFF) {
- sc->weight = clearcoat_weight;
- sc->sample_weight = clearcoat_sample_weight;
- ccl_fetch(sd, num_closure)++;
-#ifdef __OSL__
- sc->prim = NULL;
-#endif
-
- sc->N = CN;
+ DisneyClearcoatBsdf *bsdf = (DisneyClearcoatBsdf*)bsdf_alloc(sd, sizeof(DisneyClearcoatBsdf), clearcoat_weight);
- sc->data0 = clearcoat;
- sc->data1 = clearcoatGloss;
+ if (bsdf) {
+ bsdf->N = CN;
+ bsdf->clearcoat = clearcoat;
+ bsdf->clearcoatGloss = clearcoatGloss;
- ccl_fetch(sd, flag) |= bsdf_disney_clearcoat_setup(sc);
- sc_next(sc);
+ /* setup bsdf */
+ ccl_fetch(sd, flag) |= bsdf_disney_clearcoat_setup(bsdf);
}
}
+#ifdef __CAUSTICS_TRICKS__
}
+#endif
break;
}
-#undef sc_next
case CLOSURE_BSDF_DIFFUSE_ID: {
- ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight);
+ float3 weight = ccl_fetch(sd, svm_closure_weight) * mix_weight;
+ OrenNayarBsdf *bsdf = (OrenNayarBsdf*)bsdf_alloc(sd, sizeof(OrenNayarBsdf), weight);
- if(sc) {
- sc->N = N;
+ if(bsdf) {
+ bsdf->N = N;
float roughness = param1;
if(roughness == 0.0f) {
- sc->data0 = 0.0f;
- sc->data1 = 0.0f;
- sc->data2 = 0.0f;
- ccl_fetch(sd, flag) |= bsdf_diffuse_setup(sc);
+ ccl_fetch(sd, flag) |= bsdf_diffuse_setup((DiffuseBsdf*)bsdf);
}
else {
- sc->data0 = roughness;
- sc->data1 = 0.0f;
- sc->data2 = 0.0f;
- ccl_fetch(sd, flag) |= bsdf_oren_nayar_setup(sc);
+ bsdf->roughness = roughness;
+ ccl_fetch(sd, flag) |= bsdf_oren_nayar_setup(bsdf);
}
}
break;
}
case CLOSURE_BSDF_TRANSLUCENT_ID: {
- ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight);
+ float3 weight = ccl_fetch(sd, svm_closure_weight) * mix_weight;
+ DiffuseBsdf *bsdf = (DiffuseBsdf*)bsdf_alloc(sd, sizeof(DiffuseBsdf), weight);
- if(sc) {
- sc->data0 = 0.0f;
- sc->data1 = 0.0f;
- sc->data2 = 0.0f;
- sc->N = N;
- ccl_fetch(sd, flag) |= bsdf_translucent_setup(sc);
+ if(bsdf) {
+ bsdf->N = N;
+ ccl_fetch(sd, flag) |= bsdf_translucent_setup(bsdf);
}
break;
}
case CLOSURE_BSDF_TRANSPARENT_ID: {
- ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight);
+ float3 weight = ccl_fetch(sd, svm_closure_weight) * mix_weight;
+ ShaderClosure *bsdf = bsdf_alloc(sd, sizeof(ShaderClosure), weight);
- if(sc) {
- sc->data0 = 0.0f;
- sc->data1 = 0.0f;
- sc->data2 = 0.0f;
- sc->N = N;
- ccl_fetch(sd, flag) |= bsdf_transparent_setup(sc);
+ if(bsdf) {
+ ccl_fetch(sd, flag) |= bsdf_transparent_setup(bsdf);
}
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_ASHIKHMIN_SHIRLEY_ID:
+ case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID: {
#ifdef __CAUSTICS_TRICKS__
if(!kernel_data.integrator.caustics_reflective && (path_flag & PATH_RAY_DIFFUSE))
break;
#endif
- ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight);
+ float3 weight = ccl_fetch(sd, svm_closure_weight) * mix_weight;
+ MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), weight);
- if(sc) {
- sc->N = N;
- sc->data0 = param1;
- sc->data1 = param1;
- sc->data2 = 0.0f;
+ if(bsdf) {
+ bsdf->N = N;
+ bsdf->alpha_x = param1;
+ bsdf->alpha_y = param1;
+ bsdf->ior = 0.0f;
+ bsdf->extra = NULL;
/* setup bsdf */
if(type == CLOSURE_BSDF_REFLECTION_ID)
- ccl_fetch(sd, flag) |= bsdf_reflection_setup(sc);
+ ccl_fetch(sd, flag) |= bsdf_reflection_setup(bsdf);
else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_ID)
- ccl_fetch(sd, flag) |= bsdf_microfacet_beckmann_setup(sc);
+ ccl_fetch(sd, flag) |= bsdf_microfacet_beckmann_setup(bsdf);
else if(type == CLOSURE_BSDF_MICROFACET_GGX_ID)
- ccl_fetch(sd, flag) |= bsdf_microfacet_ggx_setup(sc);
+ ccl_fetch(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);
+ ccl_fetch(sd, flag) |= bsdf_microfacet_multi_ggx_setup(bsdf);
+ }
+ }
else
- ccl_fetch(sd, flag) |= bsdf_ashikhmin_shirley_setup(sc);
+ ccl_fetch(sd, flag) |= bsdf_ashikhmin_shirley_setup(bsdf);
}
break;
@@ -538,31 +407,33 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
if(!kernel_data.integrator.caustics_refractive && (path_flag & PATH_RAY_DIFFUSE))
break;
#endif
- ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight);
+ float3 weight = ccl_fetch(sd, svm_closure_weight) * mix_weight;
+ MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), weight);
- if(sc) {
- sc->N = N;
+ if(bsdf) {
+ bsdf->N = N;
+ bsdf->extra = NULL;
float eta = fmaxf(param2, 1e-5f);
eta = (ccl_fetch(sd, flag) & SD_BACKFACING)? 1.0f/eta: eta;
/* setup bsdf */
if(type == CLOSURE_BSDF_REFRACTION_ID) {
- sc->data0 = eta;
- sc->data1 = 0.0f;
- sc->data2 = 0.0f;
+ bsdf->alpha_x = 0.0f;
+ bsdf->alpha_y = 0.0f;
+ bsdf->ior = eta;
- ccl_fetch(sd, flag) |= bsdf_refraction_setup(sc);
+ ccl_fetch(sd, flag) |= bsdf_refraction_setup(bsdf);
}
else {
- sc->data0 = param1;
- sc->data1 = param1;
- sc->data2 = eta;
+ bsdf->alpha_x = param1;
+ bsdf->alpha_y = param1;
+ bsdf->ior = eta;
if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID)
- ccl_fetch(sd, flag) |= bsdf_microfacet_beckmann_refraction_setup(sc);
+ ccl_fetch(sd, flag) |= bsdf_microfacet_beckmann_refraction_setup(bsdf);
else
- ccl_fetch(sd, flag) |= bsdf_microfacet_ggx_refraction_setup(sc);
+ ccl_fetch(sd, flag) |= bsdf_microfacet_ggx_refraction_setup(bsdf);
}
}
@@ -578,7 +449,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
break;
}
#endif
- int num_closure = ccl_fetch(sd, num_closure);
+ float3 weight = ccl_fetch(sd, svm_closure_weight) * mix_weight;
/* index of refraction */
float eta = fmaxf(param2, 1e-5f);
@@ -590,164 +461,193 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
float roughness = param1;
/* reflection */
- ShaderClosure *sc = ccl_fetch_array(sd, closure, num_closure);
- float3 weight = sc->weight;
- float sample_weight = sc->sample_weight;
-
- sc = svm_node_closure_get_bsdf(sd, mix_weight*fresnel);
#ifdef __CAUSTICS_TRICKS__
if(kernel_data.integrator.caustics_reflective || (path_flag & PATH_RAY_DIFFUSE) == 0)
#endif
{
- if(sc) {
- sc->N = N;
- svm_node_glass_setup(sd, sc, type, eta, roughness, false);
+ MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), weight*fresnel);
+
+ if(bsdf) {
+ bsdf->N = N;
+ 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))
+ 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->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 = ccl_fetch(sd, svm_closure_weight) * mix_weight;
+ MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), weight);
+ MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
- /* refraction */
- if(num_closure + 1 < MAX_CLOSURE) {
- sc = ccl_fetch_array(sd, closure, num_closure + 1);
- sc->weight = weight;
- sc->sample_weight = sample_weight;
+ if(bsdf && extra) {
+ bsdf->N = N;
+ bsdf->extra = extra;
+ bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
- sc = svm_node_closure_get_bsdf(sd, mix_weight*(1.0f - fresnel));
+ bsdf->alpha_x = param1;
+ bsdf->alpha_y = param1;
+ float eta = fmaxf(param2, 1e-5f);
+ bsdf->ior = (ccl_fetch(sd, flag) & SD_BACKFACING)? 1.0f/eta: eta;
- if(sc) {
- sc->N = N;
- svm_node_glass_setup(sd, sc, type, eta, roughness, true);
- }
+ kernel_assert(stack_valid(data_node.z));
+ bsdf->extra->color = stack_load_float3(stack, data_node.z);
+
+ /* setup bsdf */
+ ccl_fetch(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
- ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight);
-
- if(sc) {
- sc->N = N;
+ float3 weight = ccl_fetch(sd, svm_closure_weight) * mix_weight;
+ MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), weight);
- sc->T = stack_load_float3(stack, data_node.y);
+ 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)
- sc->T = rotate_around_axis(sc->T, sc->N, rotation * M_2PI_F);
+ bsdf->T = rotate_around_axis(bsdf->T, bsdf->N, rotation * M_2PI_F);
/* compute roughness */
float roughness = param1;
float anisotropy = clamp(param2, -0.99f, 0.99f);
if(anisotropy < 0.0f) {
- sc->data0 = roughness/(1.0f + anisotropy);
- sc->data1 = roughness*(1.0f + anisotropy);
+ bsdf->alpha_x = roughness/(1.0f + anisotropy);
+ bsdf->alpha_y = roughness*(1.0f + anisotropy);
}
else {
- sc->data0 = roughness*(1.0f - anisotropy);
- sc->data1 = roughness/(1.0f - anisotropy);
+ bsdf->alpha_x = roughness*(1.0f - anisotropy);
+ bsdf->alpha_y = roughness/(1.0f - anisotropy);
}
- sc->data2 = 0.0f;
+ bsdf->ior = 0.0f;
- if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID)
- ccl_fetch(sd, flag) |= bsdf_microfacet_beckmann_aniso_setup(sc);
- else if(type == CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID)
- ccl_fetch(sd, flag) |= bsdf_microfacet_ggx_aniso_setup(sc);
+ if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID) {
+ ccl_fetch(sd, flag) |= bsdf_microfacet_beckmann_aniso_setup(bsdf);
+ }
+ else if(type == CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID) {
+ ccl_fetch(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);
+ ccl_fetch(sd, flag) |= bsdf_microfacet_multi_ggx_aniso_setup(bsdf);
+ }
+ }
else
- ccl_fetch(sd, flag) |= bsdf_ashikhmin_shirley_aniso_setup(sc);
+ ccl_fetch(sd, flag) |= bsdf_ashikhmin_shirley_aniso_setup(bsdf);
}
break;
}
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: {
- ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight);
+ float3 weight = ccl_fetch(sd, svm_closure_weight) * mix_weight;
+ VelvetBsdf *bsdf = (VelvetBsdf*)bsdf_alloc(sd, sizeof(VelvetBsdf), weight);
- if(sc) {
- sc->N = N;
+ if(bsdf) {
+ bsdf->N = N;
- /* sigma */
- sc->data0 = saturate(param1);
- sc->data1 = 0.0f;
- sc->data2 = 0.0f;
- ccl_fetch(sd, flag) |= bsdf_ashikhmin_velvet_setup(sc);
+ bsdf->sigma = saturate(param1);
+ ccl_fetch(sd, flag) |= bsdf_ashikhmin_velvet_setup(bsdf);
}
break;
}
- case CLOSURE_BSDF_DIFFUSE_TOON_ID:
- case CLOSURE_BSDF_GLOSSY_TOON_ID: {
- ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight);
-
- if(sc) {
- /* Normal, Size and Smooth */
- sc->N = N;
- sc->data0 = param1;
- sc->data1 = param2;
- sc->data2 = 0.0f;
+ case CLOSURE_BSDF_GLOSSY_TOON_ID:
+#ifdef __CAUSTICS_TRICKS__
+ if(!kernel_data.integrator.caustics_reflective && (path_flag & PATH_RAY_DIFFUSE))
+ break;
+#endif
+ case CLOSURE_BSDF_DIFFUSE_TOON_ID: {
+ float3 weight = ccl_fetch(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)
- ccl_fetch(sd, flag) |= bsdf_diffuse_toon_setup(sc);
+ ccl_fetch(sd, flag) |= bsdf_diffuse_toon_setup(bsdf);
else
- ccl_fetch(sd, flag) |= bsdf_glossy_toon_setup(sc);
+ ccl_fetch(sd, flag) |= bsdf_glossy_toon_setup(bsdf);
}
break;
}
#ifdef __HAIR__
case CLOSURE_BSDF_HAIR_REFLECTION_ID:
case CLOSURE_BSDF_HAIR_TRANSMISSION_ID: {
+ float3 weight = ccl_fetch(sd, svm_closure_weight) * mix_weight;
if(ccl_fetch(sd, flag) & SD_BACKFACING && ccl_fetch(sd, type) & PRIMITIVE_ALL_CURVE) {
- ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight);
+ ShaderClosure *bsdf = bsdf_alloc(sd, sizeof(ShaderClosure), weight);
- if(sc) {
+ if(bsdf) {
/* 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 */
- sc->weight = make_float3(1.0f, 1.0f, 1.0f);
- sc->N = N;
- sc->data0 = 0.0f;
- sc->data1 = 0.0f;
- sc->data2 = 0.0f;
- ccl_fetch(sd, flag) |= bsdf_transparent_setup(sc);
+ bsdf->weight = make_float3(1.0f, 1.0f, 1.0f);
+ ccl_fetch(sd, flag) |= bsdf_transparent_setup(bsdf);
}
}
else {
- ShaderClosure *sc = ccl_fetch_array(sd, closure, ccl_fetch(sd, num_closure));
- sc = svm_node_closure_get_bsdf(sd, mix_weight);
+ HairBsdf *bsdf = (HairBsdf*)bsdf_alloc(sd, sizeof(HairBsdf), weight);
- if(sc) {
- sc->N = N;
- sc->data0 = param1;
- sc->data1 = param2;
- sc->data2 = -stack_load_float(stack, data_node.z);
+ if(bsdf) {
+ bsdf->roughness1 = param1;
+ bsdf->roughness2 = param2;
+ bsdf->offset = -stack_load_float(stack, data_node.z);
if(stack_valid(data_node.y)) {
- sc->T = normalize(stack_load_float3(stack, data_node.y));
+ bsdf->T = normalize(stack_load_float3(stack, data_node.y));
}
else if(!(ccl_fetch(sd, type) & PRIMITIVE_ALL_CURVE)) {
- sc->T = normalize(ccl_fetch(sd, dPdv));
- sc->data2 = 0.0f;
+ bsdf->T = normalize(ccl_fetch(sd, dPdv));
+ bsdf->offset = 0.0f;
}
else
- sc->T = normalize(ccl_fetch(sd, dPdu));
+ bsdf->T = normalize(ccl_fetch(sd, dPdu));
if(type == CLOSURE_BSDF_HAIR_REFLECTION_ID) {
- ccl_fetch(sd, flag) |= bsdf_hair_reflection_setup(sc);
+ ccl_fetch(sd, flag) |= bsdf_hair_reflection_setup(bsdf);
}
else {
- ccl_fetch(sd, flag) |= bsdf_hair_transmission_setup(sc);
+ ccl_fetch(sd, flag) |= bsdf_hair_transmission_setup(bsdf);
}
}
}
@@ -757,17 +657,11 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
#endif
#ifdef __SUBSURFACE__
-# ifndef __SPLIT_KERNEL__
-# define sc_next(sc) sc++
-# else
-# define sc_next(sc) sc = ccl_fetch_array(sd, closure, ccl_fetch(sd, num_closure))
-# endif
case CLOSURE_BSSRDF_CUBIC_ID:
case CLOSURE_BSSRDF_GAUSSIAN_ID:
case CLOSURE_BSSRDF_BURLEY_ID: {
- ShaderClosure *sc = ccl_fetch_array(sd, closure, ccl_fetch(sd, num_closure));
- float3 albedo = sc->weight;
- float3 weight = sc->weight * mix_weight;
+ float3 albedo = ccl_fetch(sd, svm_closure_weight);
+ float3 weight = ccl_fetch(sd, svm_closure_weight) * mix_weight;
float sample_weight = fabsf(average(weight));
/* disable in case of diffuse ancestor, can't see it well then and
@@ -776,7 +670,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
if(path_flag & PATH_RAY_DIFFUSE_ANCESTOR)
param1 = 0.0f;
- if(sample_weight > CLOSURE_WEIGHT_CUTOFF && ccl_fetch(sd, num_closure)+2 < MAX_CLOSURE) {
+ if(sample_weight > CLOSURE_WEIGHT_CUTOFF) {
/* radius * scale */
float3 radius = stack_load_float3(stack, data_node.z)*param1;
/* sharpness */
@@ -785,61 +679,42 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
float texture_blur = param2;
/* create one closure per color channel */
- if(fabsf(weight.x) > 0.0f) {
- sc->weight = make_float3(weight.x, 0.0f, 0.0f);
- sc->sample_weight = sample_weight;
- sc->data0 = radius.x;
- sc->data1 = texture_blur;
- sc->data2 = albedo.x;
- sc->T.x = sharpness;
-# ifdef __OSL__
- sc->prim = NULL;
-# endif
- sc->N = N;
- ccl_fetch(sd, flag) |= bssrdf_setup(sc, (ClosureType)type);
-
- ccl_fetch(sd, num_closure)++;
- sc_next(sc);
+ Bssrdf *bssrdf = bssrdf_alloc(sd, make_float3(weight.x, 0.0f, 0.0f));
+ if(bssrdf) {
+ bssrdf->sample_weight = sample_weight;
+ bssrdf->radius = radius.x;
+ bssrdf->texture_blur = texture_blur;
+ bssrdf->albedo = albedo.x;
+ bssrdf->sharpness = sharpness;
+ bssrdf->N = N;
+ ccl_fetch(sd, flag) |= bssrdf_setup(bssrdf, (ClosureType)type);
}
- if(fabsf(weight.y) > 0.0f) {
- sc->weight = make_float3(0.0f, weight.y, 0.0f);
- sc->sample_weight = sample_weight;
- sc->data0 = radius.y;
- sc->data1 = texture_blur;
- sc->data2 = albedo.y;
- sc->T.x = sharpness;
-# ifdef __OSL__
- sc->prim = NULL;
-# endif
- sc->N = N;
- ccl_fetch(sd, flag) |= bssrdf_setup(sc, (ClosureType)type);
-
- ccl_fetch(sd, num_closure)++;
- sc_next(sc);
+ bssrdf = bssrdf_alloc(sd, make_float3(0.0f, weight.y, 0.0f));
+ if(bssrdf) {
+ bssrdf->sample_weight = sample_weight;
+ bssrdf->radius = radius.y;
+ bssrdf->texture_blur = texture_blur;
+ bssrdf->albedo = albedo.y;
+ bssrdf->sharpness = sharpness;
+ bssrdf->N = N;
+ ccl_fetch(sd, flag) |= bssrdf_setup(bssrdf, (ClosureType)type);
}
- if(fabsf(weight.z) > 0.0f) {
- sc->weight = make_float3(0.0f, 0.0f, weight.z);
- sc->sample_weight = sample_weight;
- sc->data0 = radius.z;
- sc->data1 = texture_blur;
- sc->data2 = albedo.z;
- sc->T.x = sharpness;
-# ifdef __OSL__
- sc->prim = NULL;
-# endif
- sc->N = N;
- ccl_fetch(sd, flag) |= bssrdf_setup(sc, (ClosureType)type);
-
- ccl_fetch(sd, num_closure)++;
- sc_next(sc);
+ bssrdf = bssrdf_alloc(sd, make_float3(0.0f, 0.0f, weight.z));
+ if(bssrdf) {
+ bssrdf->sample_weight = sample_weight;
+ bssrdf->radius = radius.z;
+ bssrdf->texture_blur = texture_blur;
+ bssrdf->albedo = albedo.z;
+ bssrdf->sharpness = sharpness;
+ bssrdf->N = N;
+ ccl_fetch(sd, flag) |= bssrdf_setup(bssrdf, (ClosureType)type);
}
}
break;
}
-# undef sc_next
#endif
default:
break;
@@ -864,7 +739,8 @@ ccl_device void svm_node_closure_volume(KernelGlobals *kg, ShaderData *sd, float
switch(type) {
case CLOSURE_VOLUME_ABSORPTION_ID: {
- ShaderClosure *sc = svm_node_closure_get_absorption(sd, mix_weight * density);
+ float3 weight = (make_float3(1.0f, 1.0f, 1.0f) - ccl_fetch(sd, svm_closure_weight)) * mix_weight * density;
+ ShaderClosure *sc = closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_NONE_ID, weight);
if(sc) {
ccl_fetch(sd, flag) |= volume_absorption_setup(sc);
@@ -872,13 +748,12 @@ ccl_device void svm_node_closure_volume(KernelGlobals *kg, ShaderData *sd, float
break;
}
case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID: {
- ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight * density);
+ float3 weight = ccl_fetch(sd, svm_closure_weight) * mix_weight * density;
+ HenyeyGreensteinVolume *volume = (HenyeyGreensteinVolume*)bsdf_alloc(sd, sizeof(HenyeyGreensteinVolume), weight);
- if(sc) {
- sc->data0 = param2; /* g */
- sc->data1 = 0.0f;
- sc->data2 = 0.0f;
- ccl_fetch(sd, flag) |= volume_henyey_greenstein_setup(sc);
+ if(volume) {
+ volume->g = param2; /* g */
+ ccl_fetch(sd, flag) |= volume_henyey_greenstein_setup(volume);
}
break;
}
@@ -898,10 +773,10 @@ ccl_device void svm_node_closure_emission(ShaderData *sd, float *stack, uint4 no
if(mix_weight == 0.0f)
return;
- svm_node_closure_get_non_bsdf(sd, CLOSURE_EMISSION_ID, mix_weight);
+ closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_EMISSION_ID, ccl_fetch(sd, svm_closure_weight) * mix_weight);
}
else
- svm_node_closure_get_non_bsdf(sd, CLOSURE_EMISSION_ID, 1.0f);
+ closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_EMISSION_ID, ccl_fetch(sd, svm_closure_weight));
ccl_fetch(sd, flag) |= SD_EMISSION;
}
@@ -916,10 +791,10 @@ ccl_device void svm_node_closure_background(ShaderData *sd, float *stack, uint4
if(mix_weight == 0.0f)
return;
- svm_node_closure_get_non_bsdf(sd, CLOSURE_BACKGROUND_ID, mix_weight);
+ closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_BACKGROUND_ID, ccl_fetch(sd, svm_closure_weight) * mix_weight);
}
else
- svm_node_closure_get_non_bsdf(sd, CLOSURE_BACKGROUND_ID, 1.0f);
+ closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_BACKGROUND_ID, ccl_fetch(sd, svm_closure_weight));
}
ccl_device void svm_node_closure_holdout(ShaderData *sd, float *stack, uint4 node)
@@ -932,10 +807,10 @@ ccl_device void svm_node_closure_holdout(ShaderData *sd, float *stack, uint4 nod
if(mix_weight == 0.0f)
return;
- svm_node_closure_get_non_bsdf(sd, CLOSURE_HOLDOUT_ID, mix_weight);
+ closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_HOLDOUT_ID, ccl_fetch(sd, svm_closure_weight) * mix_weight);
}
else
- svm_node_closure_get_non_bsdf(sd, CLOSURE_HOLDOUT_ID, 1.0f);
+ closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_HOLDOUT_ID, ccl_fetch(sd, svm_closure_weight));
ccl_fetch(sd, flag) |= SD_HOLDOUT;
}
@@ -950,10 +825,10 @@ ccl_device void svm_node_closure_ambient_occlusion(ShaderData *sd, float *stack,
if(mix_weight == 0.0f)
return;
- svm_node_closure_get_non_bsdf(sd, CLOSURE_AMBIENT_OCCLUSION_ID, mix_weight);
+ closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_AMBIENT_OCCLUSION_ID, ccl_fetch(sd, svm_closure_weight) * mix_weight);
}
else
- svm_node_closure_get_non_bsdf(sd, CLOSURE_AMBIENT_OCCLUSION_ID, 1.0f);
+ closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_AMBIENT_OCCLUSION_ID, ccl_fetch(sd, svm_closure_weight));
ccl_fetch(sd, flag) |= SD_AO;
}
@@ -962,10 +837,7 @@ ccl_device void svm_node_closure_ambient_occlusion(ShaderData *sd, float *stack,
ccl_device_inline void svm_node_closure_store_weight(ShaderData *sd, float3 weight)
{
- if(ccl_fetch(sd, num_closure) < MAX_CLOSURE) {
- ShaderClosure *sc = ccl_fetch_array(sd, closure, ccl_fetch(sd, num_closure));
- sc->weight = weight;
- }
+ ccl_fetch(sd, svm_closure_weight) = weight;
}
ccl_device void svm_node_closure_set_weight(ShaderData *sd, uint r, uint g, uint b)
diff --git a/intern/cycles/kernel/svm/svm_color_util.h b/intern/cycles/kernel/svm/svm_color_util.h
new file mode 100644
index 00000000000..258cdeb630e
--- /dev/null
+++ b/intern/cycles/kernel/svm/svm_color_util.h
@@ -0,0 +1,306 @@
+/*
+ * Copyright 2011-2013 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+CCL_NAMESPACE_BEGIN
+
+ccl_device float3 svm_mix_blend(float t, float3 col1, float3 col2)
+{
+ return interp(col1, col2, t);
+}
+
+ccl_device float3 svm_mix_add(float t, float3 col1, float3 col2)
+{
+ return interp(col1, col1 + col2, t);
+}
+
+ccl_device float3 svm_mix_mul(float t, float3 col1, float3 col2)
+{
+ 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);
+
+ 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;
+
+ 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.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);
+
+ return outcol;
+}
+
+ccl_device float3 svm_mix_sub(float t, float3 col1, float3 col2)
+{
+ return interp(col1, col1 - col2, t);
+}
+
+ccl_device float3 svm_mix_div(float t, float3 col1, float3 col2)
+{
+ float tm = 1.0f - t;
+
+ 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;
+
+ return outcol;
+}
+
+ccl_device float3 svm_mix_diff(float t, float3 col1, float3 col2)
+{
+ 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);
+}
+
+ccl_device float3 svm_mix_light(float t, float3 col1, float3 col2)
+{
+ 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;
+}
+
+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;
+}
+
+ccl_device float3 svm_mix_hue(float t, float3 col1, float3 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;
+ float3 tmp = hsv_to_rgb(hsv);
+
+ outcol = interp(outcol, tmp, t);
+ }
+
+ return outcol;
+}
+
+ccl_device float3 svm_mix_sat(float t, float3 col1, float3 col2)
+{
+ float tm = 1.0f - t;
+
+ float3 outcol = col1;
+
+ float3 hsv = rgb_to_hsv(outcol);
+
+ if(hsv.y != 0.0f) {
+ float3 hsv2 = rgb_to_hsv(col2);
+
+ hsv.y = tm*hsv.y + t*hsv2.y;
+ outcol = hsv_to_rgb(hsv);
+ }
+
+ return outcol;
+}
+
+ccl_device float3 svm_mix_val(float t, float3 col1, float3 col2)
+{
+ float tm = 1.0f - t;
+
+ float3 hsv = rgb_to_hsv(col1);
+ float3 hsv2 = rgb_to_hsv(col2);
+
+ hsv.z = tm*hsv.z + t*hsv2.z;
+
+ 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);
+
+ 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);
+ }
+
+ return outcol;
+}
+
+ccl_device float3 svm_mix_soft(float t, float3 col1, float3 col2)
+{
+ float tm = 1.0f - t;
+
+ 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);
+}
+
+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));
+}
+
+ccl_device float3 svm_mix_clamp(float3 col)
+{
+ float3 outcol = col;
+
+ outcol.x = saturate(col.x);
+ outcol.y = saturate(col.y);
+ outcol.z = saturate(col.z);
+
+ 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);
+}
+
+ccl_device_inline float3 svm_brightness_contrast(float3 color, float brightness, float contrast)
+{
+ 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);
+
+ return color;
+}
+
+CCL_NAMESPACE_END
+
diff --git a/intern/cycles/kernel/svm/svm_image.h b/intern/cycles/kernel/svm/svm_image.h
index 92d2b36bbb1..b6b90dfff81 100644
--- a/intern/cycles/kernel/svm/svm_image.h
+++ b/intern/cycles/kernel/svm/svm_image.h
@@ -18,15 +18,15 @@ CCL_NAMESPACE_BEGIN
/* Float4 textures on various devices. */
#if defined(__KERNEL_CPU__)
-# define TEX_NUM_FLOAT4_IMAGES TEX_NUM_FLOAT4_IMAGES_CPU
+# define TEX_NUM_FLOAT4_IMAGES TEX_NUM_FLOAT4_CPU
#elif defined(__KERNEL_CUDA__)
# if __CUDA_ARCH__ < 300
-# define TEX_NUM_FLOAT4_IMAGES TEX_NUM_FLOAT4_IMAGES_CUDA
+# define TEX_NUM_FLOAT4_IMAGES TEX_NUM_FLOAT4_CUDA
# else
-# define TEX_NUM_FLOAT4_IMAGES TEX_NUM_FLOAT4_IMAGES_CUDA_KEPLER
+# define TEX_NUM_FLOAT4_IMAGES TEX_NUM_FLOAT4_CUDA_KEPLER
# endif
#else
-# define TEX_NUM_FLOAT4_IMAGES TEX_NUM_FLOAT4_IMAGES_OPENCL
+# define TEX_NUM_FLOAT4_IMAGES TEX_NUM_FLOAT4_OPENCL
#endif
#ifdef __KERNEL_OPENCL__
@@ -72,8 +72,16 @@ ccl_device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y,
uint width = info.x;
uint height = info.y;
uint offset = info.z;
- uint periodic = (info.w & 0x1);
- uint interpolation = info.w >> 1;
+
+ /* Image Options */
+ uint interpolation = (info.w & (1 << 0)) ? INTERPOLATION_CLOSEST : INTERPOLATION_LINEAR;
+ uint extension;
+ if(info.w & (1 << 1))
+ extension = EXTENSION_REPEAT;
+ else if(info.w & (1 << 2))
+ extension = EXTENSION_EXTEND;
+ else
+ extension = EXTENSION_CLIP;
float4 r;
int ix, iy, nix, niy;
@@ -81,22 +89,26 @@ ccl_device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y,
svm_image_texture_frac(x*width, &ix);
svm_image_texture_frac(y*height, &iy);
- if(periodic) {
+ if(extension == EXTENSION_REPEAT) {
ix = svm_image_texture_wrap_periodic(ix, width);
iy = svm_image_texture_wrap_periodic(iy, height);
}
- else {
+ else if(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);
+ }
+ else { /* EXTENSION_EXTEND */
ix = svm_image_texture_wrap_clamp(ix, width);
iy = svm_image_texture_wrap_clamp(iy, height);
-
}
+
r = svm_image_texture_read(kg, id, offset + ix + iy*width);
}
- else { /* We default to linear interpolation if it is not closest */
- float tx = svm_image_texture_frac(x*width, &ix);
- float ty = svm_image_texture_frac(y*height, &iy);
+ else { /* INTERPOLATION_LINEAR */
+ float tx = svm_image_texture_frac(x*width - 0.5f, &ix);
+ float ty = svm_image_texture_frac(y*height - 0.5f, &iy);
- if(periodic) {
+ if(extension == EXTENSION_REPEAT) {
ix = svm_image_texture_wrap_periodic(ix, width);
iy = svm_image_texture_wrap_periodic(iy, height);
@@ -104,14 +116,17 @@ ccl_device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y,
niy = svm_image_texture_wrap_periodic(iy+1, height);
}
else {
- ix = svm_image_texture_wrap_clamp(ix, width);
- iy = svm_image_texture_wrap_clamp(iy, height);
-
+ if(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);
+ }
+ }
nix = svm_image_texture_wrap_clamp(ix+1, width);
niy = svm_image_texture_wrap_clamp(iy+1, height);
+ ix = svm_image_texture_wrap_clamp(ix, width);
+ iy = svm_image_texture_wrap_clamp(iy, height);
}
-
r = (1.0f - ty)*(1.0f - tx)*svm_image_texture_read(kg, id, offset + ix + iy*width);
r += (1.0f - ty)*tx*svm_image_texture_read(kg, id, offset + nix + iy*width);
r += ty*(1.0f - tx)*svm_image_texture_read(kg, id, offset + ix + niy*width);
@@ -256,9 +271,6 @@ ccl_device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y,
case 87: r = kernel_tex_image_interp(__tex_image_byte4_087, x, y); break;
case 88: r = kernel_tex_image_interp(__tex_image_byte4_088, x, y); break;
case 89: r = kernel_tex_image_interp(__tex_image_byte4_089, x, y); break;
- case 90: r = kernel_tex_image_interp(__tex_image_byte4_090, x, y); break;
- case 91: r = kernel_tex_image_interp(__tex_image_byte4_091, x, y); break;
- case 92: r = kernel_tex_image_interp(__tex_image_byte4_092, x, y); break;
default:
kernel_assert(0);
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
diff --git a/intern/cycles/kernel/svm/svm_mix.h b/intern/cycles/kernel/svm/svm_mix.h
index 7cbda111d81..022a68d1928 100644
--- a/intern/cycles/kernel/svm/svm_mix.h
+++ b/intern/cycles/kernel/svm/svm_mix.h
@@ -16,280 +16,6 @@
CCL_NAMESPACE_BEGIN
-ccl_device float3 svm_mix_blend(float t, float3 col1, float3 col2)
-{
- return interp(col1, col2, t);
-}
-
-ccl_device float3 svm_mix_add(float t, float3 col1, float3 col2)
-{
- return interp(col1, col1 + col2, t);
-}
-
-ccl_device float3 svm_mix_mul(float t, float3 col1, float3 col2)
-{
- 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);
-
- 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;
-
- 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.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);
-
- return outcol;
-}
-
-ccl_device float3 svm_mix_sub(float t, float3 col1, float3 col2)
-{
- return interp(col1, col1 - col2, t);
-}
-
-ccl_device float3 svm_mix_div(float t, float3 col1, float3 col2)
-{
- float tm = 1.0f - t;
-
- 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;
-
- return outcol;
-}
-
-ccl_device float3 svm_mix_diff(float t, float3 col1, float3 col2)
-{
- 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);
-}
-
-ccl_device float3 svm_mix_light(float t, float3 col1, float3 col2)
-{
- 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;
-}
-
-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;
-}
-
-ccl_device float3 svm_mix_hue(float t, float3 col1, float3 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;
- float3 tmp = hsv_to_rgb(hsv);
-
- outcol = interp(outcol, tmp, t);
- }
-
- return outcol;
-}
-
-ccl_device float3 svm_mix_sat(float t, float3 col1, float3 col2)
-{
- float tm = 1.0f - t;
-
- float3 outcol = col1;
-
- float3 hsv = rgb_to_hsv(outcol);
-
- if(hsv.y != 0.0f) {
- float3 hsv2 = rgb_to_hsv(col2);
-
- hsv.y = tm*hsv.y + t*hsv2.y;
- outcol = hsv_to_rgb(hsv);
- }
-
- return outcol;
-}
-
-ccl_device float3 svm_mix_val(float t, float3 col1, float3 col2)
-{
- float tm = 1.0f - t;
-
- float3 hsv = rgb_to_hsv(col1);
- float3 hsv2 = rgb_to_hsv(col2);
-
- hsv.z = tm*hsv.z + t*hsv2.z;
-
- 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);
-
- 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);
- }
-
- return outcol;
-}
-
-ccl_device float3 svm_mix_soft(float t, float3 col1, float3 col2)
-{
- float tm = 1.0f - t;
-
- 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);
-}
-
-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));
-}
-
-ccl_device float3 svm_mix_clamp(float3 col)
-{
- float3 outcol = col;
-
- outcol.x = saturate(col.x);
- outcol.y = saturate(col.y);
- outcol.z = saturate(col.z);
-
- 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);
-}
-
/* Node */
ccl_device void svm_node_mix(KernelGlobals *kg, ShaderData *sd, float *stack, uint fac_offset, uint c1_offset, uint c2_offset, int *offset)
diff --git a/intern/cycles/kernel/svm/svm_ramp.h b/intern/cycles/kernel/svm/svm_ramp.h
index 59dec409a70..f959d90f309 100644
--- a/intern/cycles/kernel/svm/svm_ramp.h
+++ b/intern/cycles/kernel/svm/svm_ramp.h
@@ -19,6 +19,8 @@
CCL_NAMESPACE_BEGIN
+/* NOTE: svm_ramp.h, svm_ramp_util.h and node_ramp_util.h must stay consistent */
+
ccl_device float4 rgb_ramp_lookup(KernelGlobals *kg,
int offset,
float f,
@@ -75,36 +77,7 @@ ccl_device void svm_node_rgb_ramp(KernelGlobals *kg, ShaderData *sd, float *stac
*offset += table_size;
}
-ccl_device void svm_node_rgb_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 table_size = read_node(kg, offset).x;
-
- 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;
- color = (color - make_float3(min_x, min_x, min_x)) / range_x;
-
- float r = rgb_ramp_lookup(kg, *offset, color.x, true, true, table_size).x;
- float g = rgb_ramp_lookup(kg, *offset, color.y, true, true, table_size).y;
- float b = rgb_ramp_lookup(kg, *offset, color.z, true, true, table_size).z;
-
- color = (1.0f - fac)*color + fac*make_float3(r, g, b);
- stack_store_float3(stack, out_offset, color);
-
- *offset += table_size;
-}
-
-ccl_device void svm_node_vector_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,
@@ -121,11 +94,11 @@ ccl_device void svm_node_vector_curves(KernelGlobals *kg, ShaderData *sd, float
const float min_x = __int_as_float(node.z),
max_x = __int_as_float(node.w);
const float range_x = max_x - min_x;
- color = (color - make_float3(min_x, min_x, min_x)) / range_x;
+ const float3 relpos = (color - make_float3(min_x, min_x, min_x)) / range_x;
- float r = rgb_ramp_lookup(kg, *offset, color.x, true, true, table_size).x;
- float g = rgb_ramp_lookup(kg, *offset, color.y, true, true, table_size).y;
- float b = rgb_ramp_lookup(kg, *offset, color.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);
diff --git a/intern/cycles/kernel/svm/svm_ramp_util.h b/intern/cycles/kernel/svm/svm_ramp_util.h
new file mode 100644
index 00000000000..495d98cf250
--- /dev/null
+++ b/intern/cycles/kernel/svm/svm_ramp_util.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2011-2013 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __SVM_RAMP_UTIL_H__
+#define __SVM_RAMP_UTIL_H__
+
+CCL_NAMESPACE_BEGIN
+
+/* NOTE: svm_ramp.h, svm_ramp_util.h and node_ramp_util.h must stay consistent */
+
+ccl_device 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;
+}
+
+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;
+}
+
+CCL_NAMESPACE_END
+
+#endif /* __SVM_RAMP_UTIL_H__ */
+
diff --git a/intern/cycles/kernel/svm/svm_tex_coord.h b/intern/cycles/kernel/svm/svm_tex_coord.h
index 27fed89fdf7..276b6f26f5e 100644
--- a/intern/cycles/kernel/svm/svm_tex_coord.h
+++ b/intern/cycles/kernel/svm/svm_tex_coord.h
@@ -312,7 +312,7 @@ ccl_device void svm_node_normal_map(KernelGlobals *kg, ShaderData *sd, float *st
/* apply normal map */
float3 B = sign * cross(normal, tangent);
- N = normalize(color.x * tangent + color.y * B + color.z * normal);
+ N = safe_normalize(color.x * tangent + color.y * B + color.z * normal);
/* transform to world space */
object_normal_transform(kg, sd, &N);
@@ -330,14 +330,18 @@ ccl_device void svm_node_normal_map(KernelGlobals *kg, ShaderData *sd, float *st
if(space == NODE_NORMAL_MAP_OBJECT || space == NODE_NORMAL_MAP_BLENDER_OBJECT)
object_normal_transform(kg, sd, &N);
else
- N = normalize(N);
+ N = safe_normalize(N);
}
float strength = stack_load_float(stack, strength_offset);
if(strength != 1.0f) {
strength = max(strength, 0.0f);
- N = normalize(ccl_fetch(sd, N) + (N - ccl_fetch(sd, N))*strength);
+ N = safe_normalize(ccl_fetch(sd, N) + (N - ccl_fetch(sd, N))*strength);
+ }
+
+ if(is_zero(N)) {
+ N = ccl_fetch(sd, N);
}
stack_store_float3(stack, normal_offset, N);
diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h
index f69b4cc5c8e..91d444098f7 100644
--- a/intern/cycles/kernel/svm/svm_types.h
+++ b/intern/cycles/kernel/svm/svm_types.h
@@ -343,6 +343,11 @@ typedef enum NodeNormalMapSpace {
NODE_NORMAL_MAP_BLENDER_WORLD,
} NodeNormalMapSpace;
+typedef enum NodeImageColorSpace {
+ NODE_COLOR_SPACE_NONE = 0,
+ NODE_COLOR_SPACE_COLOR = 1,
+} NodeImageColorSpace;
+
typedef enum NodeImageProjection {
NODE_IMAGE_PROJ_FLAT = 0,
NODE_IMAGE_PROJ_BOX = 1,
@@ -350,6 +355,11 @@ typedef enum NodeImageProjection {
NODE_IMAGE_PROJ_TUBE = 3,
} NodeImageProjection;
+typedef enum NodeEnvironmentProjection {
+ NODE_ENVIRONMENT_EQUIRECTANGULAR = 0,
+ NODE_ENVIRONMENT_MIRROR_BALL = 1,
+} NodeEnvironmentProjection;
+
typedef enum NodeBumpOffset {
NODE_BUMP_OFFSET_CENTER,
NODE_BUMP_OFFSET_DX,
@@ -388,8 +398,10 @@ typedef enum ClosureType {
CLOSURE_BSDF_REFLECTION_ID,
CLOSURE_BSDF_MICROFACET_GGX_ID,
CLOSURE_BSDF_MICROFACET_BECKMANN_ID,
+ CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID,
CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID,
CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID,
+ CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_ID,
CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID,
CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID,
CLOSURE_BSDF_ASHIKHMIN_VELVET_ID,
@@ -407,6 +419,7 @@ typedef enum ClosureType {
CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID,
CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID,
CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID,
+ CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID,
CLOSURE_BSDF_SHARP_GLASS_ID,
CLOSURE_BSDF_HAIR_TRANSMISSION_ID,
@@ -444,6 +457,9 @@ typedef enum ClosureType {
#define CLOSURE_IS_BSDF_TRANSMISSION(type) (type >= CLOSURE_BSDF_TRANSMISSION_ID && type <= CLOSURE_BSDF_HAIR_TRANSMISSION_ID)
#define CLOSURE_IS_BSDF_BSSRDF(type) (type == CLOSURE_BSDF_BSSRDF_ID || type == CLOSURE_BSDF_BSSRDF_DISNEY_ID)
#define CLOSURE_IS_BSDF_ANISOTROPIC(type) (type >= CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID && type <= CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_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_OR_BSSRDF(type) (type <= CLOSURE_BSSRDF_BURLEY_ID)
#define CLOSURE_IS_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)
diff --git a/intern/cycles/render/CMakeLists.txt b/intern/cycles/render/CMakeLists.txt
index b14da3e63d0..8eaa9de3874 100644
--- a/intern/cycles/render/CMakeLists.txt
+++ b/intern/cycles/render/CMakeLists.txt
@@ -22,6 +22,7 @@ set(SRC
bake.cpp
buffers.cpp
camera.cpp
+ constant_fold.cpp
film.cpp
graph.cpp
image.cpp
@@ -29,6 +30,7 @@ set(SRC
light.cpp
mesh.cpp
mesh_displace.cpp
+ mesh_subdivision.cpp
nodes.cpp
object.cpp
osl.cpp
@@ -49,6 +51,7 @@ set(SRC_HEADERS
background.h
buffers.h
camera.h
+ constant_fold.h
film.h
graph.h
image.h
diff --git a/intern/cycles/render/attribute.cpp b/intern/cycles/render/attribute.cpp
index b7de83d89c1..e8ff81fe08e 100644
--- a/intern/cycles/render/attribute.cpp
+++ b/intern/cycles/render/attribute.cpp
@@ -51,13 +51,13 @@ void Attribute::set(ustring name_, TypeDesc type_, AttributeElement element_)
type == TypeDesc::TypeNormal || type == TypeDesc::TypeMatrix);
}
-void Attribute::reserve(int numverts, int numtris, int numsteps, int numcurves, int numkeys, bool resize)
+void Attribute::resize(Mesh *mesh, AttributePrimitive prim, bool reserve_only)
{
- if(resize) {
- buffer.resize(buffer_size(numverts, numtris, numsteps, numcurves, numkeys), 0);
+ if(reserve_only) {
+ buffer.reserve(buffer_size(mesh, prim));
}
else {
- buffer.reserve(buffer_size(numverts, numtris, numsteps, numcurves, numkeys));
+ buffer.resize(buffer_size(mesh, prim), 0);
}
}
@@ -118,6 +118,8 @@ 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 == TypeDesc::TypeMatrix)
@@ -126,10 +128,10 @@ size_t Attribute::data_sizeof() const
return sizeof(float3);
}
-size_t Attribute::element_size(int numverts, int numtris, int numsteps, int numcurves, int numkeys) const
+size_t Attribute::element_size(Mesh *mesh, AttributePrimitive prim) const
{
size_t size;
-
+
switch(element) {
case ATTR_ELEMENT_OBJECT:
case ATTR_ELEMENT_MESH:
@@ -137,38 +139,54 @@ size_t Attribute::element_size(int numverts, int numtris, int numsteps, int numc
size = 1;
break;
case ATTR_ELEMENT_VERTEX:
- size = numverts;
+ size = mesh->verts.size() + mesh->num_ngons;
+ if(prim == ATTR_PRIM_SUBD) {
+ size -= mesh->num_subd_verts;
+ }
break;
case ATTR_ELEMENT_VERTEX_MOTION:
- size = numverts * (numsteps - 1);
+ 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:
- size = numtris;
+ 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:
- size = numtris*3;
+ 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 = numcurves;
+ size = mesh->num_curves();
break;
case ATTR_ELEMENT_CURVE_KEY:
- size = numkeys;
+ size = mesh->curve_keys.size();
break;
case ATTR_ELEMENT_CURVE_KEY_MOTION:
- size = numkeys * (numsteps - 1);
+ size = mesh->curve_keys.size() * (mesh->motion_steps - 1);
break;
default:
size = 0;
break;
}
-
+
return size;
}
-size_t Attribute::buffer_size(int numverts, int numtris, int numsteps, int numcurves, int numkeys) const
+size_t Attribute::buffer_size(Mesh *mesh, AttributePrimitive prim) const
{
- return element_size(numverts, numtris, numsteps, numcurves, numkeys)*data_sizeof();
+ return element_size(mesh, prim)*data_sizeof();
}
bool Attribute::same_storage(TypeDesc a, TypeDesc b)
@@ -188,6 +206,29 @@ bool Attribute::same_storage(TypeDesc a, TypeDesc b)
return false;
}
+void Attribute::zero_data(void* dst)
+{
+ memset(dst, 0, data_sizeof());
+}
+
+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");
+ }
+}
+
const char *Attribute::standard_name(AttributeStandard std)
{
switch(std) {
@@ -257,13 +298,14 @@ AttributeSet::AttributeSet()
{
triangle_mesh = NULL;
curve_mesh = NULL;
+ subd_mesh = NULL;
}
AttributeSet::~AttributeSet()
{
}
-Attribute *AttributeSet::add(ustring name, TypeDesc type, AttributeElement element, bool resize)
+Attribute *AttributeSet::add(ustring name, TypeDesc type, AttributeElement element)
{
Attribute *attr = find(name);
@@ -291,10 +333,12 @@ Attribute *AttributeSet::add(ustring name, TypeDesc type, AttributeElement eleme
/* this is weak .. */
if(triangle_mesh)
- attr->reserve(triangle_mesh->verts.size(), triangle_mesh->triangles.size(), triangle_mesh->motion_steps, 0, 0, resize);
+ attr->resize(triangle_mesh, ATTR_PRIM_TRIANGLE, false);
if(curve_mesh)
- attr->reserve(0, 0, curve_mesh->motion_steps, curve_mesh->curves.size(), curve_mesh->curve_keys.size(), resize);
-
+ attr->resize(curve_mesh, ATTR_PRIM_CURVE, false);
+ if(subd_mesh)
+ attr->resize(subd_mesh, ATTR_PRIM_SUBD, false);
+
return attr;
}
@@ -330,7 +374,7 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name)
if(name == ustring())
name = Attribute::standard_name(std);
- if(triangle_mesh) {
+ if(triangle_mesh || subd_mesh) {
switch(std) {
case ATTR_STD_VERTEX_NORMAL:
attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_VERTEX);
@@ -448,13 +492,15 @@ Attribute *AttributeSet::find(AttributeRequest& req)
return find(req.std);
}
-void AttributeSet::reserve()
+void AttributeSet::resize(bool reserve_only)
{
foreach(Attribute& attr, attributes) {
if(triangle_mesh)
- attr.reserve(triangle_mesh->verts.size(), triangle_mesh->triangles.size(), triangle_mesh->motion_steps, 0, 0, true);
+ attr.resize(triangle_mesh, ATTR_PRIM_TRIANGLE, reserve_only);
if(curve_mesh)
- attr.reserve(0, 0, 0, curve_mesh->curves.size(), curve_mesh->curve_keys.size(), true);
+ attr.resize(curve_mesh, ATTR_PRIM_CURVE, reserve_only);
+ if(subd_mesh)
+ attr.resize(subd_mesh, ATTR_PRIM_SUBD, reserve_only);
}
}
@@ -477,6 +523,10 @@ AttributeRequest::AttributeRequest(ustring name_)
curve_type = TypeDesc::TypeFloat;
curve_element = ATTR_ELEMENT_NONE;
curve_offset = 0;
+
+ subd_type = TypeDesc::TypeFloat;
+ subd_element = ATTR_ELEMENT_NONE;
+ subd_offset = 0;
}
AttributeRequest::AttributeRequest(AttributeStandard std_)
@@ -491,6 +541,10 @@ AttributeRequest::AttributeRequest(AttributeStandard std_)
curve_type = TypeDesc::TypeFloat;
curve_element = ATTR_ELEMENT_NONE;
curve_offset = 0;
+
+ subd_type = TypeDesc::TypeFloat;
+ subd_element = ATTR_ELEMENT_NONE;
+ subd_offset = 0;
}
/* AttributeRequestSet */
diff --git a/intern/cycles/render/attribute.h b/intern/cycles/render/attribute.h
index 01102d22aaa..e51bdf28d66 100644
--- a/intern/cycles/render/attribute.h
+++ b/intern/cycles/render/attribute.h
@@ -58,11 +58,11 @@ public:
Attribute() {}
~Attribute();
void set(ustring name, TypeDesc type, AttributeElement element);
- void reserve(int numverts, int numfaces, int numsteps, int numcurves, int numkeys, bool resize);
+ void resize(Mesh *mesh, AttributePrimitive prim, bool reserve_only);
size_t data_sizeof() const;
- size_t element_size(int numverts, int numfaces, int numsteps, int numcurves, int numkeys) const;
- size_t buffer_size(int numverts, int numfaces, int numsteps, int numcurves, int numkeys) 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; };
float3 *data_float3() { return (float3*)data(); }
@@ -79,6 +79,9 @@ public:
const Transform *data_transform() const { return (const Transform*)data(); }
const VoxelAttribute *data_voxel() const { 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 float3& f);
void add(const uchar4& f);
@@ -99,12 +102,13 @@ class AttributeSet {
public:
Mesh *triangle_mesh;
Mesh *curve_mesh;
+ Mesh *subd_mesh;
list<Attribute> attributes;
AttributeSet();
~AttributeSet();
- Attribute *add(ustring name, TypeDesc type, AttributeElement element, bool resize = true);
+ Attribute *add(ustring name, TypeDesc type, AttributeElement element);
Attribute *find(ustring name) const;
void remove(ustring name);
@@ -114,7 +118,7 @@ public:
Attribute *find(AttributeRequest& req);
- void reserve();
+ void resize(bool reserve_only = false);
void clear();
};
@@ -130,9 +134,9 @@ public:
AttributeStandard std;
/* temporary variables used by MeshManager */
- TypeDesc triangle_type, curve_type;
- AttributeElement triangle_element, curve_element;
- int triangle_offset, curve_offset;
+ TypeDesc triangle_type, curve_type, subd_type;
+ AttributeElement triangle_element, curve_element, subd_element;
+ int triangle_offset, curve_offset, subd_offset;
explicit AttributeRequest(ustring name_);
explicit AttributeRequest(AttributeStandard std);
diff --git a/intern/cycles/render/background.cpp b/intern/cycles/render/background.cpp
index 6f8d1d1d461..8d7d7b847fd 100644
--- a/intern/cycles/render/background.cpp
+++ b/intern/cycles/render/background.cpp
@@ -32,12 +32,12 @@ NODE_DEFINE(Background)
{
NodeType* type = NodeType::add("background", create);
- SOCKET_INT(ao_factor, "AO Factor", 0.0f);
+ 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_INT(visibility, "Visibility", PATH_RAY_ALL_VISIBILITY);
+ SOCKET_UINT(visibility, "Visibility", PATH_RAY_ALL_VISIBILITY);
SOCKET_BOOLEAN(transparent, "Transparent", false);
SOCKET_NODE(shader, "Shader", &Shader::node_type);
@@ -116,6 +116,11 @@ void Background::device_free(Device * /*device*/, DeviceScene * /*dscene*/)
{
}
+bool Background::modified(const Background& background)
+{
+ return !Node::equals(background);
+}
+
void Background::tag_update(Scene *scene)
{
scene->integrator->tag_update(scene);
diff --git a/intern/cycles/render/background.h b/intern/cycles/render/background.h
index 843655b00a1..8029c6a9e80 100644
--- a/intern/cycles/render/background.h
+++ b/intern/cycles/render/background.h
@@ -50,6 +50,7 @@ public:
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);
};
diff --git a/intern/cycles/render/bake.cpp b/intern/cycles/render/bake.cpp
index 5bf5e5113ef..13310a61761 100644
--- a/intern/cycles/render/bake.cpp
+++ b/intern/cycles/render/bake.cpp
@@ -177,7 +177,7 @@ bool BakeManager::bake(Device *device, DeviceScene *dscene, Scene *scene, Progre
device->mem_alloc(d_input, MEM_READ_ONLY);
device->mem_copy_to(d_input);
- device->mem_alloc(d_output, MEM_WRITE_ONLY);
+ device->mem_alloc(d_output, MEM_READ_WRITE);
DeviceTask task(DeviceTask::SHADER);
task.shader_input = d_input.device_pointer;
diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp
index d992cac5312..a6df656d220 100644
--- a/intern/cycles/render/camera.cpp
+++ b/intern/cycles/render/camera.cpp
@@ -30,70 +30,126 @@
CCL_NAMESPACE_BEGIN
static float shutter_curve_eval(float x,
- float shutter_curve[RAMP_TABLE_SIZE])
+ array<float>& shutter_curve)
{
- x *= RAMP_TABLE_SIZE;
+ if (shutter_curve.size() == 0)
+ return 1.0f;
+
+ x *= shutter_curve.size();
int index = (int)x;
float frac = x - index;
- if(index < RAMP_TABLE_SIZE - 1) {
+ if(index < shutter_curve.size() - 1) {
return lerp(shutter_curve[index], shutter_curve[index + 1], frac);
}
else {
- return shutter_curve[RAMP_TABLE_SIZE - 1];
+ 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_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);
+
+ return type;
+}
+
Camera::Camera()
+: Node(node_type)
{
- shuttertime = 1.0f;
- motion_position = MOTION_POSITION_CENTER;
shutter_table_offset = TABLE_OFFSET_INVALID;
- aperturesize = 0.0f;
- focaldistance = 10.0f;
- blades = 0;
- bladesrotation = 0.0f;
-
- matrix = transform_identity();
+ width = 1024;
+ height = 512;
+ resolution = 1;
motion.pre = transform_identity();
motion.post = transform_identity();
use_motion = false;
use_perspective_motion = false;
- aperture_ratio = 1.0f;
-
- type = CAMERA_PERSPECTIVE;
- panorama_type = PANORAMA_EQUIRECTANGULAR;
- fisheye_fov = M_PI_F;
- fisheye_lens = 10.5f;
- latitude_min = -M_PI_2_F;
- latitude_max = M_PI_2_F;
- longitude_min = -M_PI_F;
- longitude_max = M_PI_F;
- fov = M_PI_4_F;
- fov_pre = fov_post = fov;
- stereo_eye = STEREO_NONE;
- interocular_distance = 0.065f;
- convergence_distance = 30.0f * 0.065f;
- use_pole_merge = false;
- pole_merge_angle_from = 60.0f * M_PI_F / 180.0f;
- pole_merge_angle_to = 75.0f * M_PI_F / 180.0f;
-
- sensorwidth = 0.036f;
- sensorheight = 0.024f;
-
- nearclip = 1e-5f;
- farclip = 1e5f;
-
- width = 1024;
- height = 512;
- resolution = 1;
+ shutter_curve.resize(RAMP_TABLE_SIZE);
+ for(int i = 0; i < shutter_curve.size(); ++i) {
+ shutter_curve[i] = 1.0f;
+ }
- viewplane.left = -((float)width/(float)height);
- viewplane.right = (float)width/(float)height;
- viewplane.bottom = -1.0f;
- viewplane.top = 1.0f;
+ compute_auto_viewplane();
screentoworld = transform_identity();
rastertoworld = transform_identity();
@@ -109,16 +165,6 @@ Camera::Camera()
need_device_update = true;
need_flags_update = true;
previous_need_motion = -1;
-
- /* Initialize shutter curve. */
- const int num_shutter_points = sizeof(shutter_curve) / sizeof(*shutter_curve);
- for(int i = 0; i < num_shutter_points; ++i) {
- shutter_curve[i] = 1.0f;
- }
-
- /* Initialize rolling shutter effect. */
- rolling_shutter_type = ROLLING_SHUTTER_NONE;
- rolling_shutter_duration = 0.1f;
}
Camera::~Camera()
@@ -438,38 +484,14 @@ void Camera::device_free(Device * /*device*/,
bool Camera::modified(const Camera& cam)
{
- return !((shuttertime == cam.shuttertime) &&
- (aperturesize == cam.aperturesize) &&
- (blades == cam.blades) &&
- (bladesrotation == cam.bladesrotation) &&
- (focaldistance == cam.focaldistance) &&
- (type == cam.type) &&
- (fov == cam.fov) &&
- (nearclip == cam.nearclip) &&
- (farclip == cam.farclip) &&
- (sensorwidth == cam.sensorwidth) &&
- (sensorheight == cam.sensorheight) &&
- // modified for progressive render
- // (width == cam.width) &&
- // (height == cam.height) &&
- (viewplane == cam.viewplane) &&
- (border == cam.border) &&
- (matrix == cam.matrix) &&
- (aperture_ratio == cam.aperture_ratio) &&
- (panorama_type == cam.panorama_type) &&
- (fisheye_fov == cam.fisheye_fov) &&
- (fisheye_lens == cam.fisheye_lens) &&
- (latitude_min == cam.latitude_min) &&
- (latitude_max == cam.latitude_max) &&
- (longitude_min == cam.longitude_min) &&
- (longitude_max == cam.longitude_max) &&
- (stereo_eye == cam.stereo_eye));
+ return !Node::equals(cam);
}
bool Camera::motion_modified(const Camera& cam)
{
return !((motion == cam.motion) &&
- (use_motion == cam.use_motion));
+ (use_motion == cam.use_motion) &&
+ (use_perspective_motion == cam.use_perspective_motion));
}
void Camera::tag_update()
diff --git a/intern/cycles/render/camera.h b/intern/cycles/render/camera.h
index 57b9960e70b..141ef9cccef 100644
--- a/intern/cycles/render/camera.h
+++ b/intern/cycles/render/camera.h
@@ -19,6 +19,8 @@
#include "kernel_types.h"
+#include "node.h"
+
#include "util_boundbox.h"
#include "util_transform.h"
#include "util_types.h"
@@ -35,8 +37,10 @@ class Scene;
* Renderman, and Blender after remapping.
*/
-class Camera {
+class Camera : public Node {
public:
+ NODE_DECLARE;
+
/* Specifies an offset for the shutter's time interval. */
enum MotionPosition {
/* Shutter opens at the current frame. */
@@ -69,7 +73,7 @@ public:
/* motion blur */
float shuttertime;
MotionPosition motion_position;
- float shutter_curve[RAMP_TABLE_SIZE];
+ array<float> shutter_curve;
size_t shutter_table_offset;
/* ** Rolling shutter effect. ** */
diff --git a/intern/cycles/render/constant_fold.cpp b/intern/cycles/render/constant_fold.cpp
new file mode 100644
index 00000000000..073bafce98d
--- /dev/null
+++ b/intern/cycles/render/constant_fold.cpp
@@ -0,0 +1,354 @@
+/*
+ * Copyright 2011-2013 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "constant_fold.h"
+#include "graph.h"
+
+#include "util_foreach.h"
+#include "util_logging.h"
+
+CCL_NAMESPACE_BEGIN
+
+ConstantFolder::ConstantFolder(ShaderGraph *graph, ShaderNode *node, ShaderOutput *output)
+: graph(graph), node(node), output(output)
+{
+}
+
+bool ConstantFolder::all_inputs_constant() const
+{
+ foreach(ShaderInput *input, node->inputs) {
+ if(input->link) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void ConstantFolder::make_constant(float value) const
+{
+ VLOG(1) << "Replacing " << node->name << " with constant " << value << ".";
+ foreach(ShaderInput *sock, output->links) {
+ sock->set(value);
+ }
+
+ graph->disconnect(output);
+}
+
+void ConstantFolder::make_constant(float3 value) const
+{
+ foreach(ShaderInput *sock, output->links) {
+ sock->set(value);
+ }
+
+ graph->disconnect(output);
+}
+
+void ConstantFolder::make_constant_clamp(float value, bool clamp) const
+{
+ 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);
+ }
+
+ 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);
+ }
+}
+
+void ConstantFolder::bypass(ShaderOutput *new_output) const
+{
+ assert(new_output);
+
+ /* 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);
+
+ foreach(ShaderInput *sock, outputs) {
+ graph->connect(new_output, sock);
+ }
+}
+
+void ConstantFolder::discard() const
+{
+ assert(output->type() == SocketType::CLOSURE);
+ graph->disconnect(output);
+}
+
+void ConstantFolder::bypass_or_discard(ShaderInput *input) const
+{
+ 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;
+ }
+
+ 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;
+}
+
+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;
+}
+
+/* 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;
+ }
+}
+
+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;
+ 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;
+ }
+}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/render/constant_fold.h b/intern/cycles/render/constant_fold.h
new file mode 100644
index 00000000000..2b31c2a5887
--- /dev/null
+++ b/intern/cycles/render/constant_fold.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2011-2013 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __CONSTANT_FOLD_H__
+#define __CONSTANT_FOLD_H__
+
+#include "util_types.h"
+#include "svm_types.h"
+
+CCL_NAMESPACE_BEGIN
+
+class ShaderGraph;
+class ShaderInput;
+class ShaderNode;
+class ShaderOutput;
+
+class ConstantFolder {
+public:
+ ShaderGraph *const graph;
+ ShaderNode *const node;
+ ShaderOutput *const output;
+
+ ConstantFolder(ShaderGraph *graph, ShaderNode *node, ShaderOutput *output);
+
+ 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;
+
+ /* 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;
+
+ /* 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;
+
+ /* 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__ */
+
diff --git a/intern/cycles/render/curves.h b/intern/cycles/render/curves.h
index 3d9b4e1f347..e41967eebf5 100644
--- a/intern/cycles/render/curves.h
+++ b/intern/cycles/render/curves.h
@@ -63,23 +63,23 @@ public:
ParticleCurveData();
~ParticleCurveData();
- vector<int> psys_firstcurve;
- vector<int> psys_curvenum;
- vector<int> psys_shader;
-
- vector<float> psys_rootradius;
- vector<float> psys_tipradius;
- vector<float> psys_shape;
- vector<bool> psys_closetip;
-
- vector<int> curve_firstkey;
- vector<int> curve_keynum;
- vector<float> curve_length;
- vector<float3> curve_uv;
- vector<float3> curve_vcol;
-
- vector<float3> curvekey_co;
- vector<float> curvekey_time;
+ 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<int> curve_firstkey;
+ array<int> curve_keynum;
+ array<float> curve_length;
+ array<float3> curve_uv;
+ array<float3> curve_vcol;
+
+ array<float3> curvekey_co;
+ array<float> curvekey_time;
};
/* HairSystem Manager */
diff --git a/intern/cycles/render/film.cpp b/intern/cycles/render/film.cpp
index 12dce6ad999..e10a938e1eb 100644
--- a/intern/cycles/render/film.cpp
+++ b/intern/cycles/render/film.cpp
@@ -465,7 +465,7 @@ void Film::device_free(Device * /*device*/,
bool Film::modified(const Film& film)
{
- return Node::modified(film) || !Pass::equals(passes, film.passes);
+ return !Node::equals(film) || !Pass::equals(passes, film.passes);
}
void Film::tag_passes_update(Scene *scene, const array<Pass>& passes_)
diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp
index 24e4c9f33d5..3eeb7ffc2bc 100644
--- a/intern/cycles/render/graph.cpp
+++ b/intern/cycles/render/graph.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2011-2013 Blender Foundation
+ * Copyright 2011-2016 Blender Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@
#include "graph.h"
#include "nodes.h"
#include "shader.h"
+#include "constant_fold.h"
#include "util_algorithm.h"
#include "util_debug.h"
@@ -51,73 +52,19 @@ bool check_node_inputs_traversed(const ShaderNode *node,
return true;
}
-bool check_node_inputs_equals(const ShaderNode *node_a,
- const ShaderNode *node_b)
-{
- if(node_a->inputs.size() != node_b->inputs.size()) {
- /* Happens with BSDF closure nodes which are currently sharing the same
- * name for all the BSDF types, making it impossible to filter out
- * incompatible nodes.
- */
- return false;
- }
- for(int i = 0; i < node_a->inputs.size(); ++i) {
- ShaderInput *input_a = node_a->inputs[i],
- *input_b = node_b->inputs[i];
- if(input_a->link == NULL && input_b->link == NULL) {
- /* Unconnected inputs are expected to have the same value. */
- if(input_a->value != input_b->value) {
- 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;
-}
-
} /* namespace */
-/* Input and Output */
-
-ShaderInput::ShaderInput(ShaderNode *parent_, const char *name_, ShaderSocketType type_)
-{
- parent = parent_;
- name = name_;
- type = type_;
- link = NULL;
- value = make_float3(0.0f, 0.0f, 0.0f);
- stack_offset = SVM_STACK_INVALID;
- default_value = NONE;
- usage = USE_ALL;
-}
-
-ShaderOutput::ShaderOutput(ShaderNode *parent_, const char *name_, ShaderSocketType type_)
-{
- parent = parent_;
- name = name_;
- type = type_;
- stack_offset = SVM_STACK_INVALID;
-}
-
/* Node */
-ShaderNode::ShaderNode(const char *name_)
+ShaderNode::ShaderNode(const NodeType *type)
+: Node(type)
{
- name = name_;
+ name = type->name;
id = -1;
bump = SHADER_BUMP_NONE;
special_type = SHADER_SPECIAL_TYPE_NONE;
+
+ create_inputs_outputs(type);
}
ShaderNode::~ShaderNode()
@@ -129,10 +76,23 @@ ShaderNode::~ShaderNode()
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));
+ }
+}
+
ShaderInput *ShaderNode::input(const char *name)
{
foreach(ShaderInput *socket, inputs) {
- if(strcmp(socket->name, name) == 0)
+ if(socket->name() == name)
return socket;
}
@@ -142,56 +102,42 @@ ShaderInput *ShaderNode::input(const char *name)
ShaderOutput *ShaderNode::output(const char *name)
{
foreach(ShaderOutput *socket, outputs)
- if(strcmp(socket->name, name) == 0)
+ if(socket->name() == name)
return socket;
return NULL;
}
-ShaderInput *ShaderNode::add_input(const char *name, ShaderSocketType type, float value, int usage)
+ShaderInput *ShaderNode::input(ustring name)
{
- ShaderInput *input = new ShaderInput(this, name, type);
- input->value.x = value;
- input->usage = usage;
- inputs.push_back(input);
- return input;
-}
+ foreach(ShaderInput *socket, inputs) {
+ if(socket->name() == name)
+ return socket;
+ }
-ShaderInput *ShaderNode::add_input(const char *name, ShaderSocketType type, float3 value, int usage)
-{
- ShaderInput *input = new ShaderInput(this, name, type);
- input->value = value;
- input->usage = usage;
- inputs.push_back(input);
- return input;
+ return NULL;
}
-ShaderInput *ShaderNode::add_input(const char *name, ShaderSocketType type, ShaderInput::DefaultValue value, int usage)
+ShaderOutput *ShaderNode::output(ustring name)
{
- ShaderInput *input = add_input(name, type);
- input->default_value = value;
- input->usage = usage;
- return input;
-}
+ foreach(ShaderOutput *socket, outputs)
+ if(socket->name() == name)
+ return socket;
-ShaderOutput *ShaderNode::add_output(const char *name, ShaderSocketType type)
-{
- ShaderOutput *output = new ShaderOutput(this, name, type);
- outputs.push_back(output);
- return output;
+ return NULL;
}
void ShaderNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
foreach(ShaderInput *input, inputs) {
if(!input->link) {
- if(input->default_value == ShaderInput::TEXTURE_GENERATED) {
+ 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->default_value == ShaderInput::TEXTURE_UV) {
+ else if(input->flags() & SocketType::LINK_TEXTURE_UV) {
if(shader->has_surface)
attributes->add(ATTR_STD_UV);
}
@@ -199,6 +145,49 @@ void ShaderNode::attributes(Shader *shader, AttributeRequestSet *attributes)
}
}
+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;
+}
+
/* Graph */
ShaderGraph::ShaderGraph()
@@ -256,18 +245,18 @@ void ShaderGraph::connect(ShaderOutput *from, ShaderInput *to)
return;
}
- if(from->type != to->type) {
+ if(from->type() != to->type()) {
/* for closures we can't do automatic conversion */
- if(from->type == SHADER_SOCKET_CLOSURE || to->type == SHADER_SOCKET_CLOSURE) {
+ if(from->type() == SocketType::CLOSURE || to->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,
- to->parent->name.c_str(), to->name);
+ 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 = add(new ConvertNode(from->type, to->type, true));
+ ShaderNode *convert = add(new ConvertNode(from->type(), to->type(), true));
connect(from, convert->inputs[0]);
connect(convert->outputs[0], to);
@@ -279,6 +268,17 @@ void ShaderGraph::connect(ShaderOutput *from, ShaderInput *to)
}
}
+void ShaderGraph::disconnect(ShaderOutput *from)
+{
+ assert(!finalized);
+
+ foreach(ShaderInput *sock, from->links) {
+ sock->link = NULL;
+ }
+
+ from->links.clear();
+}
+
void ShaderGraph::disconnect(ShaderInput *to)
{
assert(!finalized);
@@ -374,24 +374,12 @@ void ShaderGraph::copy_nodes(ShaderNodeSet& nodes, ShaderNodeMap& nnodemap)
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();
-
- foreach(ShaderInput *input, node->inputs) {
- ShaderInput *ninput = new ShaderInput(*input);
- nnode->inputs.push_back(ninput);
-
- ninput->parent = nnode;
- ninput->link = NULL;
- }
-
- foreach(ShaderOutput *output, node->outputs) {
- ShaderOutput *noutput = new ShaderOutput(*output);
- nnode->outputs.push_back(noutput);
-
- noutput->parent = nnode;
- noutput->links.clear();
- }
+ nnode->create_inputs_outputs(nnode->type);
}
/* recreate links */
@@ -401,8 +389,8 @@ void ShaderGraph::copy_nodes(ShaderNodeSet& nodes, ShaderNodeMap& nnodemap)
/* 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);
+ ShaderOutput *noutput = nfrom->output(input->link->name());
+ ShaderInput *ninput = nto->input(input->name());
/* connect */
connect(noutput, ninput);
@@ -447,10 +435,10 @@ void ShaderGraph::remove_proxy_nodes()
vector<ShaderInput*> links = tonode->outputs[0]->links;
foreach(ShaderInput *autoin, links) {
- if(autoin->default_value == ShaderInput::NONE)
- all_links_removed = false;
- else
+ if(autoin->flags() & SocketType::DEFAULT_LINK_MASK)
disconnect(autoin);
+ else
+ all_links_removed = false;
}
if(all_links_removed)
@@ -460,8 +448,7 @@ void ShaderGraph::remove_proxy_nodes()
disconnect(to);
/* transfer the default input value to the target socket */
- to->set(input->value);
- to->set(input->value_string);
+ tonode->copy_value(to->socket_type, *proxy, input->socket_type);
}
}
@@ -527,16 +514,8 @@ void ShaderGraph::constant_fold()
}
}
/* Optimize current node. */
- float3 optimized_value = make_float3(0.0f, 0.0f, 0.0f);
- if(node->constant_fold(this, output, &optimized_value)) {
- /* Apply optimized value to connected sockets. */
- vector<ShaderInput*> links(output->links);
- foreach(ShaderInput *input, links) {
- /* Assign value and disconnect the optimizedinput. */
- input->value = optimized_value;
- disconnect(input);
- }
- }
+ ConstantFolder folder(this, node, output);
+ node->constant_fold(folder);
}
}
}
@@ -561,8 +540,8 @@ void ShaderGraph::deduplicate_nodes()
* already deduplicated.
*/
- ShaderNodeSet scheduled;
- map<ustring, ShaderNodeSet> done;
+ ShaderNodeSet scheduled, done;
+ map<ustring, ShaderNodeSet> candidates;
queue<ShaderNode*> traverse_queue;
/* Schedule nodes which doesn't have any dependencies. */
@@ -576,7 +555,7 @@ void ShaderGraph::deduplicate_nodes()
while(!traverse_queue.empty()) {
ShaderNode *node = traverse_queue.front();
traverse_queue.pop();
- done[node->name].insert(node);
+ done.insert(node);
/* Schedule the nodes which were depending on the current node. */
foreach(ShaderOutput *output, node->outputs) {
foreach(ShaderInput *input, output->links) {
@@ -587,35 +566,28 @@ void ShaderGraph::deduplicate_nodes()
continue;
}
/* Schedule node if its inputs are fully done. */
- if(check_node_inputs_traversed(input->parent, done[input->parent->name])) {
+ if(check_node_inputs_traversed(input->parent, done)) {
traverse_queue.push(input->parent);
scheduled.insert(input->parent);
}
}
}
/* Try to merge this node with another one. */
- foreach(ShaderNode *other_node, done[node->name]) {
- if(node == other_node) {
- /* Don't merge with self. */
- continue;
- }
- if(node->name != other_node->name) {
- /* Can only de-duplicate nodes of the same type. */
- continue;
- }
- if(!check_node_inputs_equals(node, other_node)) {
- /* Node inputs are different, can't merge them, */
- continue;
+ 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(!node->equals(other_node)) {
- /* Node settings are different. */
- continue;
- }
- /* TODO(sergey): Consider making it an utility function. */
+ }
+ /* 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], other_node->outputs[i]);
+ relink(node, node->outputs[i], merge_with->outputs[i]);
}
- break;
+ }
+ else {
+ candidates[node->type->name].insert(node);
}
}
}
@@ -706,38 +678,38 @@ void ShaderGraph::default_inputs(bool do_osl)
foreach(ShaderNode *node, nodes) {
foreach(ShaderInput *input, node->inputs) {
- if(!input->link && ((input->usage & ShaderInput::USE_SVM) || do_osl)) {
- if(input->default_value == ShaderInput::TEXTURE_GENERATED) {
+ 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);
}
- else if(input->default_value == ShaderInput::TEXTURE_UV) {
+ else if(input->flags() & SocketType::LINK_TEXTURE_UV) {
if(!texco)
texco = new TextureCoordinateNode();
connect(texco->output("UV"), input);
}
- else if(input->default_value == ShaderInput::INCOMING) {
+ else if(input->flags() & SocketType::LINK_INCOMING) {
if(!geom)
geom = new GeometryNode();
connect(geom->output("Incoming"), input);
}
- else if(input->default_value == ShaderInput::NORMAL) {
+ else if(input->flags() & SocketType::LINK_NORMAL) {
if(!geom)
geom = new GeometryNode();
connect(geom->output("Normal"), input);
}
- else if(input->default_value == ShaderInput::POSITION) {
+ else if(input->flags() & SocketType::LINK_POSITION) {
if(!geom)
geom = new GeometryNode();
connect(geom->output("Position"), input);
}
- else if(input->default_value == ShaderInput::TANGENT) {
+ else if(input->flags() & SocketType::LINK_TANGENT) {
if(!geom)
geom = new GeometryNode();
@@ -785,8 +757,8 @@ void ShaderGraph::refine_bump_nodes()
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);
+ 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"));
@@ -860,9 +832,9 @@ void ShaderGraph::bump_from_displacement()
ShaderNode *bump = add(new BumpNode());
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);
+ 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());
connect(out_center, bump->input("SampleCenter"));
connect(out_dx, bump->input("SampleX"));
@@ -882,7 +854,7 @@ void ShaderGraph::bump_from_displacement()
continue;
}
foreach(ShaderInput *input, node->inputs) {
- if(!input->link && input->default_value == ShaderInput::NORMAL)
+ if(!input->link && (input->flags() & SocketType::LINK_NORMAL))
connect(set_normal->output("Normal"), input);
}
}
@@ -918,14 +890,15 @@ void ShaderGraph::transform_multi_closure(ShaderNode *node, ShaderOutput *weight
if(fin) {
/* mix closure: add node to mix closure weights */
- ShaderNode *mix_node = add(new MixClosureWeightNode());
+ 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
- fac_in->value = fin->value;
+ mix_node->fac = node->get_float(fin->socket_type);
if(weight_out)
connect(weight_out, weight_in);
@@ -952,20 +925,20 @@ void ShaderGraph::transform_multi_closure(ShaderNode *node, ShaderOutput *weight
return;
/* already has a weight connected to it? add weights */
- if(weight_in->link || weight_in->value.x != 0.0f) {
- ShaderNode *math_node = add(new MathNode());
- ShaderInput *value1_in = math_node->input("Value1");
- ShaderInput *value2_in = math_node->input("Value2");
+ 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, value1_in);
+ connect(weight_in->link, math_node->input("Value1"));
else
- value1_in->value = weight_in->value;
+ math_node->value1 = weight_value;
if(weight_out)
- connect(weight_out, value2_in);
+ connect(weight_out, math_node->input("Value2"));
else
- value2_in->value.x = 1.0f;
+ math_node->value2 = 1.0f;
weight_out = math_node->output("Value");
if(weight_in->link)
@@ -976,7 +949,7 @@ void ShaderGraph::transform_multi_closure(ShaderNode *node, ShaderOutput *weight
if(weight_out)
connect(weight_out, weight_in);
else
- weight_in->value.x += 1.0f;
+ node->set(weight_in->socket_type, weight_value + 1.0f);
}
}
@@ -994,6 +967,9 @@ int ShaderGraph::get_num_closures()
else if(CLOSURE_IS_GLASS(closure_type)) {
num_closures += 2;
}
+ else if(CLOSURE_IS_BSDF_MULTISCATTER(closure_type)) {
+ num_closures += 2;
+ }
else {
++num_closures;
}
@@ -1024,7 +1000,7 @@ void ShaderGraph::dump_graph(const char *filename)
if(socket != node->inputs[0]) {
fprintf(fd, "|");
}
- fprintf(fd, "<IN_%p>%s", socket, socket->name);
+ fprintf(fd, "<IN_%p>%s", socket, socket->name().c_str());
}
fprintf(fd, "}|");
}
@@ -1044,7 +1020,7 @@ void ShaderGraph::dump_graph(const char *filename)
if(socket != node->outputs[0]) {
fprintf(fd, "|");
}
- fprintf(fd, "<OUT_%p>%s", socket, socket->name);
+ fprintf(fd, "<OUT_%p>%s", socket, socket->name().c_str());
}
fprintf(fd, "}");
}
@@ -1058,7 +1034,7 @@ void ShaderGraph::dump_graph(const char *filename)
"// CONNECTION: OUT_%p->IN_%p (%s:%s)\n",
output,
input,
- output->name, input->name);
+ output->name().c_str(), input->name().c_str());
fprintf(fd,
"\"%p\":\"OUT_%p\":e -> \"%p\":\"IN_%p\":w [label=\"\"]\n",
output->parent,
diff --git a/intern/cycles/render/graph.h b/intern/cycles/render/graph.h
index bd3f5ca689a..b35be48d8ca 100644
--- a/intern/cycles/render/graph.h
+++ b/intern/cycles/render/graph.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2011-2013 Blender Foundation
+ * Copyright 2011-2016 Blender Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,6 +17,9 @@
#ifndef __GRAPH_H__
#define __GRAPH_H__
+#include "node.h"
+#include "node_type.h"
+
#include "kernel_types.h"
#include "util_list.h"
@@ -38,23 +41,7 @@ class ShaderGraph;
class SVMCompiler;
class OSLCompiler;
class OutputNode;
-
-/* Socket Type
- *
- * Data type for inputs and outputs */
-
-enum ShaderSocketType {
- SHADER_SOCKET_UNDEFINED,
-
- SHADER_SOCKET_FLOAT,
- SHADER_SOCKET_INT,
- SHADER_SOCKET_COLOR,
- SHADER_SOCKET_VECTOR,
- SHADER_SOCKET_POINT,
- SHADER_SOCKET_NORMAL,
- SHADER_SOCKET_CLOSURE,
- SHADER_SOCKET_STRING
-};
+class ConstantFolder;
/* Bump
*
@@ -86,30 +73,6 @@ enum ShaderNodeSpecialType {
SHADER_SPECIAL_TYPE_BUMP,
};
-/* Enum
- *
- * Utility class for enum values. */
-
-class ShaderEnum {
-public:
- 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) { return left.find(x) != left.end(); }
- bool exists(int y) { return right.find(y) != right.end(); }
-
- int operator[](const char *x) { return left[ustring(x)]; }
- int operator[](ustring x) { return left[x]; }
- ustring operator[](int y) { return right[y]; }
-
-protected:
- map<ustring, int> left;
- map<int, ustring> right;
-};
-
/* Input
*
* Input socket for a shader node. May be linked to an output or not. If not
@@ -118,39 +81,21 @@ protected:
class ShaderInput {
public:
- enum DefaultValue {
- TEXTURE_GENERATED,
- TEXTURE_UV,
- INCOMING,
- NORMAL,
- POSITION,
- TANGENT,
- NONE
- };
-
- enum Usage {
- USE_SVM = 1,
- USE_OSL = 2,
- USE_ALL = USE_SVM|USE_OSL
- };
-
- ShaderInput(ShaderNode *parent, const char *name, ShaderSocketType type);
- void set(const float3& v) { value = v; }
- void set(float f) { value = make_float3(f, 0, 0); }
- void set(const ustring v) { value_string = v; }
-
- const char *name;
- ShaderSocketType type;
+ ShaderInput(const SocketType& socket_type_, ShaderNode* parent_)
+ : socket_type(socket_type_), parent(parent_), link(NULL), stack_offset(SVM_STACK_INVALID)
+ {}
- ShaderNode *parent;
- ShaderOutput *link;
+ ustring name() { return socket_type.ui_name; }
+ int flags() { return socket_type.flags; }
+ SocketType::Type type() { return socket_type.type; }
- DefaultValue default_value;
- float3 value;
- ustring value_string;
+ 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 */
- int usage;
};
/* Output
@@ -159,14 +104,16 @@ public:
class ShaderOutput {
public:
- ShaderOutput(ShaderNode *parent, const char *name, ShaderSocketType type);
+ ShaderOutput(const SocketType& socket_type_, ShaderNode* parent_)
+ : socket_type(socket_type_), parent(parent_), stack_offset(SVM_STACK_INVALID)
+ {}
- const char *name;
- ShaderNode *parent;
- ShaderSocketType type;
+ 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 */
};
@@ -175,18 +122,17 @@ public:
* Shader node in graph, with input and output sockets. This is the virtual
* base class for all node types. */
-class ShaderNode {
+class ShaderNode : public Node {
public:
- explicit ShaderNode(const char *name);
+ 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 *add_input(const char *name, ShaderSocketType type, float value=0.0f, int usage=ShaderInput::USE_ALL);
- ShaderInput *add_input(const char *name, ShaderSocketType type, float3 value, int usage=ShaderInput::USE_ALL);
- ShaderInput *add_input(const char *name, ShaderSocketType type, ShaderInput::DefaultValue value, int usage=ShaderInput::USE_ALL);
- ShaderOutput *add_output(const char *name, ShaderSocketType type);
+ ShaderInput *input(ustring name);
+ ShaderOutput *output(ustring name);
virtual ShaderNode *clone() const = 0;
virtual void attributes(Shader *shader, AttributeRequestSet *attributes);
@@ -195,7 +141,7 @@ public:
/* ** Node optimization ** */
/* Check whether the node can be replaced with single constant. */
- virtual bool constant_fold(ShaderGraph * /*graph*/, ShaderOutput * /*socket*/, float3 * /*optimized_value*/) { return false; }
+ 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.
@@ -213,7 +159,6 @@ public:
vector<ShaderInput*> inputs;
vector<ShaderOutput*> outputs;
- ustring name; /* name, not required to be unique */
int id; /* index in graph node array */
ShaderBump bump; /* for bump mapping utility */
@@ -249,23 +194,21 @@ public:
* 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)
- {
- return name == other->name &&
- bump == other->bump;
- }
+ 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); \
#define SHADER_NODE_NO_CLONE_CLASS(type) \
+ NODE_DECLARE; \
type(); \
virtual void compile(SVMCompiler& compiler); \
virtual void compile(OSLCompiler& compiler); \
@@ -307,6 +250,7 @@ public:
OutputNode *output();
void connect(ShaderOutput *from, ShaderInput *to);
+ void disconnect(ShaderOutput *from);
void disconnect(ShaderInput *to);
void relink(ShaderNode *node, ShaderOutput *from, ShaderOutput *to);
diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp
index 6650c98aa38..614620c14af 100644
--- a/intern/cycles/render/image.cpp
+++ b/intern/cycles/render/image.cpp
@@ -36,59 +36,66 @@ ImageManager::ImageManager(const DeviceInfo& info)
osl_texture_system = NULL;
animation_frame = 0;
- /* Set image limits */
+ /* In case of multiple devices used we need to know type of an actual
+ * compute device.
+ *
+ * NOTE: We assume that all the devices are same type, otherwise we'll
+ * be screwed on so many levels..
+ */
+ DeviceType device_type = info.type;
+ if (device_type == DEVICE_MULTI) {
+ device_type = info.multi_devices[0].type;
+ }
- /* CPU */
- if(info.type == DEVICE_CPU) {
- tex_num_images[IMAGE_DATA_TYPE_BYTE4] = TEX_NUM_BYTE4_IMAGES_CPU;
- tex_num_images[IMAGE_DATA_TYPE_FLOAT4] = TEX_NUM_FLOAT4_IMAGES_CPU;
- tex_num_images[IMAGE_DATA_TYPE_FLOAT] = TEX_NUM_FLOAT_IMAGES_CPU;
- tex_num_images[IMAGE_DATA_TYPE_BYTE] = TEX_NUM_BYTE_IMAGES_CPU;
- tex_image_byte4_start = TEX_IMAGE_BYTE4_START_CPU;
- tex_image_float_start = TEX_IMAGE_FLOAT_START_CPU;
- tex_image_byte_start = TEX_IMAGE_BYTE_START_CPU;
+ /* Set image limits */
+#define SET_TEX_IMAGES_LIMITS(ARCH) \
+ { \
+ tex_num_images[IMAGE_DATA_TYPE_FLOAT4] = TEX_NUM_FLOAT4_ ## ARCH; \
+ tex_num_images[IMAGE_DATA_TYPE_BYTE4] = TEX_NUM_BYTE4_ ## ARCH; \
+ tex_num_images[IMAGE_DATA_TYPE_FLOAT] = TEX_NUM_FLOAT_ ## ARCH; \
+ tex_num_images[IMAGE_DATA_TYPE_BYTE] = TEX_NUM_BYTE_ ## ARCH; \
+ tex_num_images[IMAGE_DATA_TYPE_HALF4] = TEX_NUM_HALF4_ ## ARCH; \
+ tex_num_images[IMAGE_DATA_TYPE_HALF] = TEX_NUM_HALF_ ## ARCH; \
+ tex_start_images[IMAGE_DATA_TYPE_FLOAT4] = TEX_START_FLOAT4_ ## ARCH; \
+ tex_start_images[IMAGE_DATA_TYPE_BYTE4] = TEX_START_BYTE4_ ## ARCH; \
+ tex_start_images[IMAGE_DATA_TYPE_FLOAT] = TEX_START_FLOAT_ ## ARCH; \
+ tex_start_images[IMAGE_DATA_TYPE_BYTE] = TEX_START_BYTE_ ## ARCH; \
+ tex_start_images[IMAGE_DATA_TYPE_HALF4] = TEX_START_HALF4_ ## ARCH; \
+ tex_start_images[IMAGE_DATA_TYPE_HALF] = TEX_START_HALF_ ## ARCH; \
}
- /* CUDA (Fermi) */
- else if((info.type == DEVICE_CUDA || info.type == DEVICE_MULTI) && !info.has_bindless_textures) {
- tex_num_images[IMAGE_DATA_TYPE_BYTE4] = TEX_NUM_BYTE4_IMAGES_CUDA;
- tex_num_images[IMAGE_DATA_TYPE_FLOAT4] = TEX_NUM_FLOAT4_IMAGES_CUDA;
- tex_num_images[IMAGE_DATA_TYPE_FLOAT] = TEX_NUM_FLOAT_IMAGES_CUDA;
- tex_num_images[IMAGE_DATA_TYPE_BYTE] = TEX_NUM_BYTE_IMAGES_CUDA;
- tex_image_byte4_start = TEX_IMAGE_BYTE4_START_CUDA;
- tex_image_float_start = TEX_IMAGE_FLOAT_START_CUDA;
- tex_image_byte_start = TEX_IMAGE_BYTE_START_CUDA;
+
+ if(device_type == DEVICE_CPU) {
+ SET_TEX_IMAGES_LIMITS(CPU);
}
- /* CUDA (Kepler and above) */
- else if((info.type == DEVICE_CUDA || info.type == DEVICE_MULTI) && info.has_bindless_textures) {
- tex_num_images[IMAGE_DATA_TYPE_BYTE4] = TEX_NUM_BYTE4_IMAGES_CUDA_KEPLER;
- tex_num_images[IMAGE_DATA_TYPE_FLOAT4] = TEX_NUM_FLOAT4_IMAGES_CUDA_KEPLER;
- tex_num_images[IMAGE_DATA_TYPE_FLOAT] = TEX_NUM_FLOAT_IMAGES_CUDA_KEPLER;
- tex_num_images[IMAGE_DATA_TYPE_BYTE] = TEX_NUM_BYTE_IMAGES_CUDA_KEPLER;
- tex_image_byte4_start = TEX_IMAGE_BYTE4_START_CUDA_KEPLER;
- tex_image_float_start = TEX_IMAGE_FLOAT_START_CUDA_KEPLER;
- tex_image_byte_start = TEX_IMAGE_BYTE_START_CUDA_KEPLER;
+ else if(device_type == DEVICE_CUDA) {
+ if(info.has_bindless_textures) {
+ SET_TEX_IMAGES_LIMITS(CUDA_KEPLER);
+ }
+ else {
+ SET_TEX_IMAGES_LIMITS(CUDA);
+ }
}
- /* OpenCL */
- else if(info.pack_images) {
- tex_num_images[IMAGE_DATA_TYPE_BYTE4] = TEX_NUM_BYTE4_IMAGES_OPENCL;
- tex_num_images[IMAGE_DATA_TYPE_FLOAT4] = TEX_NUM_FLOAT4_IMAGES_OPENCL;
- tex_num_images[IMAGE_DATA_TYPE_FLOAT] = TEX_NUM_FLOAT_IMAGES_OPENCL;
- tex_num_images[IMAGE_DATA_TYPE_BYTE] = TEX_NUM_BYTE_IMAGES_OPENCL;
- tex_image_byte4_start = TEX_IMAGE_BYTE4_START_OPENCL;
- tex_image_float_start = TEX_IMAGE_FLOAT_START_OPENCL;
- tex_image_byte_start = TEX_IMAGE_BYTE_START_OPENCL;
+ else if(device_type == DEVICE_OPENCL) {
+ SET_TEX_IMAGES_LIMITS(OPENCL);
}
- /* Should never happen */
else {
- tex_num_images[IMAGE_DATA_TYPE_BYTE4] = 0;
+ /* Should not happen. */
tex_num_images[IMAGE_DATA_TYPE_FLOAT4] = 0;
+ tex_num_images[IMAGE_DATA_TYPE_BYTE4] = 0;
tex_num_images[IMAGE_DATA_TYPE_FLOAT] = 0;
tex_num_images[IMAGE_DATA_TYPE_BYTE] = 0;
- tex_image_byte4_start = 0;
- tex_image_float_start = 0;
- tex_image_byte_start = 0;
+ tex_num_images[IMAGE_DATA_TYPE_HALF4] = 0;
+ tex_num_images[IMAGE_DATA_TYPE_HALF] = 0;
+ tex_start_images[IMAGE_DATA_TYPE_FLOAT4] = 0;
+ tex_start_images[IMAGE_DATA_TYPE_BYTE4] = 0;
+ tex_start_images[IMAGE_DATA_TYPE_FLOAT] = 0;
+ tex_start_images[IMAGE_DATA_TYPE_BYTE] = 0;
+ tex_start_images[IMAGE_DATA_TYPE_HALF4] = 0;
+ tex_start_images[IMAGE_DATA_TYPE_HALF] = 0;
assert(0);
}
+
+#undef SET_TEX_IMAGES_LIMITS
}
ImageManager::~ImageManager()
@@ -129,7 +136,7 @@ ImageManager::ImageDataType ImageManager::get_image_metadata(const string& filen
void *builtin_data,
bool& is_linear)
{
- bool is_float = false;
+ bool is_float = false, is_half = false;
is_linear = false;
int channels = 4;
@@ -168,6 +175,10 @@ ImageManager::ImageDataType ImageManager::get_image_metadata(const string& filen
}
}
+ /* check if it's half float */
+ if(spec.format == TypeDesc::HALF)
+ is_half = true;
+
channels = spec.nchannels;
/* basic color space detection, not great but better than nothing
@@ -193,7 +204,10 @@ ImageManager::ImageDataType ImageManager::get_image_metadata(const string& filen
delete in;
}
- if(is_float) {
+ if(is_half) {
+ return (channels > 1) ? IMAGE_DATA_TYPE_HALF4 : IMAGE_DATA_TYPE_HALF;
+ }
+ else if(is_float) {
return (channels > 1) ? IMAGE_DATA_TYPE_FLOAT4 : IMAGE_DATA_TYPE_FLOAT;
}
else {
@@ -207,34 +221,20 @@ ImageManager::ImageDataType ImageManager::get_image_metadata(const string& filen
* to device ones and vice versa. */
int ImageManager::type_index_to_flattened_slot(int slot, ImageDataType type)
{
- if(type == IMAGE_DATA_TYPE_BYTE4)
- return slot + tex_image_byte4_start;
- else if(type == IMAGE_DATA_TYPE_FLOAT)
- return slot + tex_image_float_start;
- else if(type == IMAGE_DATA_TYPE_BYTE)
- return slot + tex_image_byte_start;
- else
- return slot;
+ return slot + tex_start_images[type];
}
int ImageManager::flattened_slot_to_type_index(int flat_slot, ImageDataType *type)
{
- if(flat_slot >= tex_image_byte_start) {
- *type = IMAGE_DATA_TYPE_BYTE;
- return flat_slot - tex_image_byte_start;
- }
- else if(flat_slot >= tex_image_float_start) {
- *type = IMAGE_DATA_TYPE_FLOAT;
- return flat_slot - tex_image_float_start;
- }
- else if(flat_slot >= tex_image_byte4_start) {
- *type = IMAGE_DATA_TYPE_BYTE4;
- return flat_slot - tex_image_byte4_start;
- }
- else {
- *type = IMAGE_DATA_TYPE_FLOAT4;
- return flat_slot;
+ for(int i = IMAGE_DATA_NUM_TYPES - 1; i >= 0; i--) {
+ if(flat_slot >= tex_start_images[i]) {
+ *type = (ImageDataType)i;
+ return flat_slot - tex_start_images[i];
+ }
}
+
+ /* Should not happen. */
+ return flat_slot;
}
string ImageManager::name_from_type(int type)
@@ -245,6 +245,10 @@ string ImageManager::name_from_type(int type)
return "float";
else if(type == IMAGE_DATA_TYPE_BYTE)
return "byte";
+ else if(type == IMAGE_DATA_TYPE_HALF4)
+ return "half4";
+ else if(type == IMAGE_DATA_TYPE_HALF)
+ return "half";
else
return "byte4";
}
@@ -280,11 +284,16 @@ int ImageManager::add_image(const string& filename,
if(type == IMAGE_DATA_TYPE_FLOAT || type == IMAGE_DATA_TYPE_FLOAT4)
is_float = true;
- /* No single channel textures on CUDA (Fermi) and OpenCL, use available slots */
- if(type == IMAGE_DATA_TYPE_FLOAT && tex_num_images[type] == 0)
+ /* No single channel and half textures on CUDA (Fermi) and OpenCL, use available slots */
+ if((type == IMAGE_DATA_TYPE_FLOAT ||
+ type == IMAGE_DATA_TYPE_HALF4 ||
+ type == IMAGE_DATA_TYPE_HALF) &&
+ tex_num_images[type] == 0) {
type = IMAGE_DATA_TYPE_FLOAT4;
- if(type == IMAGE_DATA_TYPE_BYTE && tex_num_images[type] == 0)
+ }
+ if(type == IMAGE_DATA_TYPE_BYTE && tex_num_images[type] == 0) {
type = IMAGE_DATA_TYPE_BYTE4;
+ }
/* Fnd existing image. */
for(slot = 0; slot < images[type].size(); slot++) {
@@ -660,6 +669,107 @@ bool ImageManager::file_load_float_image(Image *img, ImageDataType type, device_
return true;
}
+template<typename T>
+bool ImageManager::file_load_half_image(Image *img, ImageDataType type, device_vector<T>& tex_img)
+{
+ ImageInput *in = NULL;
+ int width, height, depth, components;
+
+ if(!file_load_image_generic(img, &in, width, height, depth, components))
+ return false;
+
+ /* read RGBA pixels */
+ half *pixels = (half*)tex_img.resize(width, height, depth);
+ if(pixels == NULL) {
+ return false;
+ }
+
+ if(in) {
+ half *readpixels = pixels;
+ vector<half> tmppixels;
+
+ if(components > 4) {
+ tmppixels.resize(((size_t)width)*height*components);
+ readpixels = &tmppixels[0];
+ }
+
+ if(depth <= 1) {
+ int scanlinesize = width*components*sizeof(half);
+
+ in->read_image(TypeDesc::HALF,
+ (uchar*)readpixels + (height-1)*scanlinesize,
+ AutoStride,
+ -scanlinesize,
+ AutoStride);
+ }
+ else {
+ in->read_image(TypeDesc::HALF, (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();
+ }
+
+ in->close();
+ delete in;
+ }
+#if 0
+ /* TODO(dingto): Support half for ImBuf. */
+ else {
+ builtin_image_float_pixels_cb(img->filename, img->builtin_data, pixels);
+ }
+#endif
+
+ /* Check if we actually have a half4 slot, in case components == 1, but device
+ * doesn't support single channel textures. */
+ if(type == IMAGE_DATA_TYPE_HALF4) {
+ size_t num_pixels = ((size_t)width) * height * depth;
+ 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] = 1.0f;
+ 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] = 1.0f;
+ 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] = 1.0f;
+ }
+ }
+ }
+
+ return true;
+}
+
void ImageManager::device_load_image(Device *device, DeviceScene *dscene, ImageDataType type, int slot, Progress *progress)
{
if(progress->get_cancel())
@@ -759,7 +869,7 @@ void ImageManager::device_load_image(Device *device, DeviceScene *dscene, ImageD
img->extension);
}
}
- else {
+ else if(type == IMAGE_DATA_TYPE_BYTE){
device_vector<uchar>& tex_img = dscene->tex_byte_image[slot];
if(tex_img.device_pointer) {
@@ -782,6 +892,55 @@ void ImageManager::device_load_image(Device *device, DeviceScene *dscene, ImageD
img->extension);
}
}
+ else if(type == IMAGE_DATA_TYPE_HALF4){
+ device_vector<half4>& tex_img = dscene->tex_half4_image[slot];
+
+ if(tex_img.device_pointer) {
+ thread_scoped_lock device_lock(device_mutex);
+ device->tex_free(tex_img);
+ }
+
+ if(!file_load_half_image(img, type, tex_img)) {
+ /* on failure to load, we set a 1x1 pixels pink image */
+ half *pixels = (half*)tex_img.resize(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;
+ }
+
+ if(!pack_images) {
+ thread_scoped_lock device_lock(device_mutex);
+ device->tex_alloc(name.c_str(),
+ tex_img,
+ img->interpolation,
+ img->extension);
+ }
+ }
+ else if(type == IMAGE_DATA_TYPE_HALF){
+ device_vector<half>& tex_img = dscene->tex_half_image[slot];
+
+ if(tex_img.device_pointer) {
+ thread_scoped_lock device_lock(device_mutex);
+ device->tex_free(tex_img);
+ }
+
+ if(!file_load_half_image(img, type, tex_img)) {
+ /* on failure to load, we set a 1x1 pixels pink image */
+ half *pixels = (half*)tex_img.resize(1, 1);
+
+ pixels[0] = TEX_IMAGE_MISSING_R;
+ }
+
+ if(!pack_images) {
+ thread_scoped_lock device_lock(device_mutex);
+ device->tex_alloc(name.c_str(),
+ tex_img,
+ img->interpolation,
+ img->extension);
+ }
+ }
img->need_load = false;
}
@@ -827,7 +986,7 @@ void ImageManager::device_free_image(Device *device, DeviceScene *dscene, ImageD
tex_img.clear();
}
- else {
+ else if(type == IMAGE_DATA_TYPE_BYTE){
device_vector<uchar>& tex_img = dscene->tex_byte_image[slot];
if(tex_img.device_pointer) {
@@ -837,6 +996,26 @@ void ImageManager::device_free_image(Device *device, DeviceScene *dscene, ImageD
tex_img.clear();
}
+ else if(type == IMAGE_DATA_TYPE_HALF4){
+ device_vector<half4>& tex_img = dscene->tex_half4_image[slot];
+
+ if(tex_img.device_pointer) {
+ thread_scoped_lock device_lock(device_mutex);
+ device->tex_free(tex_img);
+ }
+
+ tex_img.clear();
+ }
+ else if(type == IMAGE_DATA_TYPE_HALF){
+ device_vector<half>& tex_img = dscene->tex_half_image[slot];
+
+ if(tex_img.device_pointer) {
+ thread_scoped_lock device_lock(device_mutex);
+ device->tex_free(tex_img);
+ }
+
+ tex_img.clear();
+ }
delete images[type][slot];
images[type][slot] = NULL;
@@ -897,6 +1076,26 @@ void ImageManager::device_update_slot(Device *device,
}
}
+uint8_t ImageManager::pack_image_options(ImageDataType type, size_t slot)
+{
+ uint8_t options = 0;
+
+ /* Image Options are packed into one uint:
+ * bit 0 -> Interpolation
+ * bit 1 + 2 + 3-> Extension */
+ if(images[type][slot]->interpolation == INTERPOLATION_CLOSEST)
+ options |= (1 << 0);
+
+ if(images[type][slot]->extension == EXTENSION_REPEAT)
+ options |= (1 << 1);
+ else if(images[type][slot]->extension == EXTENSION_EXTEND)
+ options |= (1 << 2);
+ else /* EXTENSION_CLIP */
+ options |= (1 << 3);
+
+ return options;
+}
+
void ImageManager::device_pack_images(Device *device,
DeviceScene *dscene,
Progress& /*progess*/)
@@ -928,11 +1127,9 @@ void ImageManager::device_pack_images(Device *device,
device_vector<uchar4>& tex_img = dscene->tex_byte4_image[slot];
- /* The image options are packed
- bit 0 -> periodic
- bit 1 + 2 -> interpolation type */
- uint8_t interpolation = (images[type][slot]->interpolation << 1) + 1;
- info[type_index_to_flattened_slot(slot, type)] = make_uint4(tex_img.data_width, tex_img.data_height, offset, interpolation);
+ uint8_t options = pack_image_options(type, slot);
+
+ info[type_index_to_flattened_slot(slot, type)] = make_uint4(tex_img.data_width, tex_img.data_height, offset, options);
memcpy(pixels_byte+offset, (void*)tex_img.data_pointer, tex_img.memory_size());
offset += tex_img.size();
@@ -960,11 +1157,8 @@ void ImageManager::device_pack_images(Device *device,
/* todo: support 3D textures, only CPU for now */
- /* The image options are packed
- bit 0 -> periodic
- bit 1 + 2 -> interpolation type */
- uint8_t interpolation = (images[type][slot]->interpolation << 1) + 1;
- info[type_index_to_flattened_slot(slot, type)] = make_uint4(tex_img.data_width, tex_img.data_height, offset, interpolation);
+ uint8_t options = pack_image_options(type, slot);
+ info[type_index_to_flattened_slot(slot, type)] = make_uint4(tex_img.data_width, tex_img.data_height, offset, options);
memcpy(pixels_float+offset, (void*)tex_img.data_pointer, tex_img.memory_size());
offset += tex_img.size();
diff --git a/intern/cycles/render/image.h b/intern/cycles/render/image.h
index 2ab16dd8967..07998684b23 100644
--- a/intern/cycles/render/image.h
+++ b/intern/cycles/render/image.h
@@ -41,6 +41,8 @@ public:
IMAGE_DATA_TYPE_BYTE4 = 1,
IMAGE_DATA_TYPE_FLOAT = 2,
IMAGE_DATA_TYPE_BYTE = 3,
+ IMAGE_DATA_TYPE_HALF4 = 4,
+ IMAGE_DATA_TYPE_HALF = 5,
IMAGE_DATA_NUM_TYPES
};
@@ -96,9 +98,8 @@ public:
private:
int tex_num_images[IMAGE_DATA_NUM_TYPES];
- int tex_image_byte4_start;
- int tex_image_float_start;
- int tex_image_byte_start;
+ int tex_start_images[IMAGE_DATA_NUM_TYPES];
+
thread_mutex device_mutex;
int animation_frame;
@@ -114,10 +115,15 @@ private:
template<typename T>
bool file_load_float_image(Image *img, ImageDataType type, device_vector<T>& tex_img);
+ template<typename T>
+ bool file_load_half_image(Image *img, ImageDataType type, device_vector<T>& tex_img);
+
int type_index_to_flattened_slot(int slot, ImageDataType type);
int flattened_slot_to_type_index(int flat_slot, ImageDataType *type);
string name_from_type(int type);
+ uint8_t pack_image_options(ImageDataType type, size_t slot);
+
void device_load_image(Device *device, DeviceScene *dscene, ImageDataType type, int slot, Progress *progess);
void device_free_image(Device *device, DeviceScene *dscene, ImageDataType type, int slot);
diff --git a/intern/cycles/render/integrator.cpp b/intern/cycles/render/integrator.cpp
index 41e2571dc24..63914e57319 100644
--- a/intern/cycles/render/integrator.cpp
+++ b/intern/cycles/render/integrator.cpp
@@ -176,7 +176,7 @@ void Integrator::device_update(Device *device, DeviceScene *dscene, Scene *scene
max_samples = max(max_samples, volume_samples);
}
- max_samples *= (max_bounce + transparent_max_bounce + 3);
+ max_samples *= (max_bounce + transparent_max_bounce + 3 + BSSRDF_MAX_HITS);
int dimensions = PRNG_BASE_NUM + max_samples*PRNG_BOUNCE_NUM;
dimensions = min(dimensions, SOBOL_MAX_DIMENSIONS);
@@ -204,6 +204,11 @@ void Integrator::device_free(Device *device, DeviceScene *dscene)
dscene->sobol_directions.clear();
}
+bool Integrator::modified(const Integrator& integrator)
+{
+ return !Node::equals(integrator);
+}
+
void Integrator::tag_update(Scene *scene)
{
foreach(Shader *shader, scene->shaders) {
diff --git a/intern/cycles/render/integrator.h b/intern/cycles/render/integrator.h
index a5cfb0c7863..39eaaf246d4 100644
--- a/intern/cycles/render/integrator.h
+++ b/intern/cycles/render/integrator.h
@@ -86,6 +86,7 @@ public:
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);
};
diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp
index c20bf6b5e9e..ae6042cef34 100644
--- a/intern/cycles/render/light.cpp
+++ b/intern/cycles/render/light.cpp
@@ -209,6 +209,29 @@ void LightManager::disable_ineffective_light(Device *device, Scene *scene)
}
}
+bool LightManager::object_usable_as_light(Object *object) {
+ Mesh *mesh = object->mesh;
+ /* Skip if we are not visible for BSDFs. */
+ if(!(object->visibility & (PATH_RAY_DIFFUSE|PATH_RAY_GLOSSY|PATH_RAY_TRANSMIT))) {
+ return false;
+ }
+ /* Skip motion blurred deforming meshes, not supported yet. */
+ if(mesh->has_motion_blur()) {
+ 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 *device, DeviceScene *dscene, Scene *scene, Progress& progress)
{
progress.set_status("Updating Lights", "Computing distribution");
@@ -226,39 +249,28 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
}
foreach(Object *object, scene->objects) {
- Mesh *mesh = object->mesh;
- bool have_emission = false;
-
- /* skip if we are not visible for BSDFs */
- if(!(object->visibility & (PATH_RAY_DIFFUSE|PATH_RAY_GLOSSY|PATH_RAY_TRANSMIT)))
- continue;
+ if(progress.get_cancel()) return;
- /* skip motion blurred deforming meshes, not supported yet */
- if(mesh->has_motion_blur())
+ if(!object_usable_as_light(object)) {
continue;
-
- /* skip if we have no emission shaders */
- foreach(Shader *shader, mesh->used_shaders) {
- if(shader->use_mis && shader->has_surface_emission) {
- have_emission = true;
- break;
- }
}
+ /* 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;
- /* count triangles */
- if(have_emission) {
- for(size_t i = 0; i < mesh->triangles.size(); 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++;
+ 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 */
float4 *distribution = dscene->light_distribution.resize(num_distribution + 1);
@@ -269,86 +281,68 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
int j = 0;
foreach(Object *object, scene->objects) {
- Mesh *mesh = object->mesh;
- bool have_emission = false;
+ if(progress.get_cancel()) return;
- /* skip if we are not visible for BSDFs */
- if(!(object->visibility & (PATH_RAY_DIFFUSE|PATH_RAY_GLOSSY|PATH_RAY_TRANSMIT))) {
+ 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;
- /* skip motion blurred deforming meshes, not supported yet */
- if(mesh->has_motion_blur()) {
- j++;
- continue;
- }
+ if(transform_applied)
+ object_id = ~object_id;
- /* skip if we have no emission shaders */
- foreach(Shader *shader, mesh->used_shaders) {
- if(shader->use_mis && shader->has_surface_emission) {
- have_emission = true;
- break;
- }
+ 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;
}
- /* sum area */
- if(have_emission) {
- bool transform_applied = mesh->transform_applied;
- Transform tfm = object->tfm;
- int object_id = j;
- int shader_flag = 0;
-
- if(transform_applied)
- object_id = ~object_id;
-
- 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;
- for(size_t i = 0; i < mesh->triangles.size(); 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].x = totarea;
- distribution[offset].y = __int_as_float(i + mesh->tri_offset);
- distribution[offset].z = __int_as_float(shader_flag);
- distribution[offset].w = __int_as_float(object_id);
- offset++;
-
- Mesh::Triangle t = mesh->triangles[i];
- 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);
+ if(shader->use_mis && shader->has_surface_emission) {
+ distribution[offset].x = totarea;
+ distribution[offset].y = __int_as_float(i + mesh->tri_offset);
+ distribution[offset].z = __int_as_float(shader_flag);
+ distribution[offset].w = __int_as_float(object_id);
+ offset++;
+
+ Mesh::Triangle t = mesh->get_triangle(i);
+ 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);
}
}
- if(progress.get_cancel()) return;
-
j++;
}
@@ -441,9 +435,9 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen
device->tex_alloc("__light_distribution", dscene->light_distribution);
/* Portals */
- if(num_background_lights > 0 && light_index != scene->lights.size()) {
+ if(num_background_lights > 0 && light_index != num_lights) {
kintegrator->portal_offset = light_index;
- kintegrator->num_portals = scene->lights.size() - light_index;
+ kintegrator->num_portals = num_lights - light_index;
kintegrator->portal_pdf = background_mis? 0.5f: 1.0f;
}
else {
@@ -607,10 +601,21 @@ void LightManager::device_update_points(Device *device,
Scene *scene)
{
int num_scene_lights = scene->lights.size();
- if(num_scene_lights == 0)
+ int num_lights = 0;
+
+ foreach(Light *light, scene->lights) {
+ if(light->is_enabled) {
+ num_lights++;
+ }
+ }
+
+ float4 *light_data = dscene->light_data.resize(num_lights*LIGHT_SIZE);
+
+ if(num_lights == 0) {
+ VLOG(1) << "No effective light, ignoring points update.";
return;
+ }
- float4 *light_data = dscene->light_data.resize(num_scene_lights*LIGHT_SIZE);
int light_index = 0;
foreach(Light *light, scene->lights) {
diff --git a/intern/cycles/render/light.h b/intern/cycles/render/light.h
index 2f1df1c9417..745caa96159 100644
--- a/intern/cycles/render/light.h
+++ b/intern/cycles/render/light.h
@@ -28,6 +28,7 @@ CCL_NAMESPACE_BEGIN
class Device;
class DeviceScene;
+class Object;
class Progress;
class Scene;
class Shader;
@@ -108,6 +109,9 @@ protected:
DeviceScene *dscene,
Scene *scene,
Progress& progress);
+
+ /* Check whether light manager can use the object as a light-emissive. */
+ bool object_usable_as_light(Object *object);
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp
index d26404035eb..4cf0a785897 100644
--- a/intern/cycles/render/mesh.cpp
+++ b/intern/cycles/render/mesh.cpp
@@ -35,9 +35,6 @@
#include "util_progress.h"
#include "util_set.h"
-#include "subd_split.h"
-#include "subd_patch.h"
-
CCL_NAMESPACE_BEGIN
/* Triangle */
@@ -51,14 +48,45 @@ void Mesh::Triangle::bounds_grow(const float3 *verts, BoundBox& bounds) const
/* Curve */
-void Mesh::Curve::bounds_grow(const int k, const float4 *curve_keys, 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];
+
+ 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;
+
+ 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]);
+
+ 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
{
float3 P[4];
- P[0] = float4_to_float3(curve_keys[max(first_key + k - 1,first_key)]);
- P[1] = float4_to_float3(curve_keys[first_key + k]);
- P[2] = float4_to_float3(curve_keys[first_key + k + 1]);
- P[3] = float4_to_float3(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]);
float3 lower;
float3 upper;
@@ -67,27 +95,62 @@ void Mesh::Curve::bounds_grow(const int k, const float4 *curve_keys, BoundBox& b
curvebounds(&lower.y, &upper.y, P, 1);
curvebounds(&lower.z, &upper.z, P, 2);
- float mr = max(curve_keys[first_key + k].w, curve_keys[first_key + k + 1].w);
+ float mr = max(curve_radius[first_key + k], curve_radius[first_key + k + 1]);
bounds.grow(lower, mr);
bounds.grow(upper, mr);
}
+/* 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]];
+
+ return safe_normalize(cross(v1 - v0, v2 - v0));
+}
+
+
/* Mesh */
+NODE_DEFINE(Mesh)
+{
+ NodeType* type = NodeType::add("mesh", create);
+
+ 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);
+
+ 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_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;
+}
+
Mesh::Mesh()
+: Node(node_type)
{
need_update = true;
need_update_rebuild = false;
transform_applied = false;
transform_negative_scaled = false;
transform_normal = transform_identity();
- displacement_method = DISPLACE_BUMP;
bounds = BoundBox::empty;
- motion_steps = 3;
- use_motion_blur = false;
-
bvh = NULL;
tri_offset = 0;
@@ -96,11 +159,24 @@ Mesh::Mesh()
curve_offset = 0;
curvekey_offset = 0;
+ patch_offset = 0;
+ face_offset = 0;
+ corner_offset = 0;
+
+ num_subd_verts = 0;
+
attributes.triangle_mesh = this;
curve_attributes.curve_mesh = this;
+ subd_attributes.subd_mesh = this;
+
+ geometry_flags = GEOMETRY_NONE;
has_volume = false;
has_surface_bssrdf = false;
+
+ num_ngons = 0;
+
+ subdivision_type = SUBDIVISION_NONE;
}
Mesh::~Mesh()
@@ -108,21 +184,73 @@ Mesh::~Mesh()
delete bvh;
}
-void Mesh::reserve(int numverts, int numtris, int numcurves, int numcurvekeys)
+void Mesh::resize_mesh(int numverts, int numtris)
{
- /* reserve space to add verts and triangles later */
verts.resize(numverts);
- triangles.resize(numtris);
+ triangles.resize(numtris * 3);
shader.resize(numtris);
smooth.resize(numtris);
- forms_quad.resize(numtris);
+ if(subd_faces.size()) {
+ triangle_patch.resize(numtris);
+ vert_patch_uv.resize(numverts);
+ }
+
+ 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);
+
+ if(subd_faces.size()) {
+ triangle_patch.reserve(numtris);
+ vert_patch_uv.reserve(numverts);
+ }
+
+ 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_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_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_attributes.resize();
+}
- curve_keys.resize(numcurvekeys);
- curves.resize(numcurves);
+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_;
- attributes.reserve();
- curve_attributes.reserve();
+ subd_attributes.resize(true);
}
void Mesh::clear()
@@ -133,13 +261,22 @@ void Mesh::clear()
shader.clear();
smooth.clear();
- forms_quad.clear();
+ triangle_patch.clear();
+ vert_patch_uv.clear();
curve_keys.clear();
- curves.clear();
+ curve_radius.clear();
+ curve_first_key.clear();
+ curve_shader.clear();
+
+ subd_faces.clear();
+ subd_face_corners.clear();
+
+ num_subd_verts = 0;
attributes.clear();
curve_attributes.clear();
+ subd_attributes.clear();
used_shaders.clear();
transform_applied = false;
@@ -151,7 +288,7 @@ void Mesh::clear()
int Mesh::split_vertex(int vertex)
{
/* copy vertex location and vertex attributes */
- verts.push_back(verts[vertex]);
+ add_vertex_slow(verts[vertex]);
foreach(Attribute& attr, attributes.attributes) {
if(attr.element == ATTR_ELEMENT_VERTEX) {
@@ -161,51 +298,77 @@ int Mesh::split_vertex(int vertex)
}
}
+ foreach(Attribute& attr, subd_attributes.attributes) {
+ if(attr.element == ATTR_ELEMENT_VERTEX) {
+ vector<char> tmp(attr.data_sizeof());
+ memcpy(&tmp[0], attr.data() + tmp.size()*vertex, tmp.size());
+ attr.add(&tmp[0]);
+ }
+ }
+
return verts.size() - 1;
}
-void Mesh::set_triangle(int i, int v0, int v1, int v2, int shader_, bool smooth_, bool forms_quad_)
+void Mesh::add_vertex(float3 P)
+{
+ verts.push_back_reserved(P);
+
+ if(subd_faces.size()) {
+ vert_patch_uv.push_back_reserved(make_float2(0.0f, 0.0f));
+ }
+}
+
+void Mesh::add_vertex_slow(float3 P)
{
- Triangle tri;
- tri.v[0] = v0;
- tri.v[1] = v1;
- tri.v[2] = v2;
-
- triangles[i] = tri;
- shader[i] = shader_;
- smooth[i] = smooth_;
- forms_quad[i] = forms_quad_;
+ verts.push_back_slow(P);
+
+ 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_, bool forms_quad_)
+void Mesh::add_triangle(int v0, int v1, int v2, int shader_, bool smooth_)
{
- Triangle tri;
- tri.v[0] = v0;
- tri.v[1] = v1;
- tri.v[2] = v2;
-
- triangles.push_back(tri);
- shader.push_back(shader_);
- smooth.push_back(smooth_);
- forms_quad.push_back(forms_quad_);
+ 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);
+ }
}
void Mesh::add_curve_key(float3 co, float radius)
{
- float4 key = float3_to_float4(co);
- key.w = radius;
+ curve_keys.push_back_reserved(co);
+ curve_radius.push_back_reserved(radius);
+}
- curve_keys.push_back(key);
+void Mesh::add_curve(int first_key, int shader)
+{
+ curve_first_key.push_back_reserved(first_key);
+ curve_shader.push_back_reserved(shader);
}
-void Mesh::add_curve(int first_key, int num_keys, int shader)
+void Mesh::add_subd_face(int* corners, int num_corners, int shader_, bool smooth_)
{
- Curve curve;
- curve.first_key = first_key;
- curve.num_keys = num_keys;
- curve.shader = shader;
+ int start_corner = subd_face_corners.size();
+
+ for(int i = 0; i < num_corners; i++) {
+ subd_face_corners.push_back_reserved(corners[i]);
+ }
- curves.push_back(curve);
+ 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();
+ }
+
+ SubdFace face = {start_corner, num_corners, shader_, smooth_, ptex_offset};
+ subd_faces.push_back_reserved(face);
}
void Mesh::compute_bounds()
@@ -219,7 +382,7 @@ void Mesh::compute_bounds()
bnds.grow(verts[i]);
for(size_t i = 0; i < curve_keys_size; i++)
- bnds.grow(float4_to_float3(curve_keys[i]), curve_keys[i].w);
+ bnds.grow(curve_keys[i], curve_radius[i]);
Attribute *attr = attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
if(use_motion_blur && attr) {
@@ -247,7 +410,7 @@ void Mesh::compute_bounds()
bnds.grow_safe(verts[i]);
for(size_t i = 0; i < curve_keys_size; i++)
- bnds.grow_safe(float4_to_float3(curve_keys[i]), curve_keys[i].w);
+ bnds.grow_safe(curve_keys[i], curve_radius[i]);
if(use_motion_blur && attr) {
size_t steps_size = verts.size() * (motion_steps - 1);
@@ -301,15 +464,14 @@ void Mesh::add_face_normals()
float3 *fN = attr_fN->data_float3();
/* compute face normals */
- size_t triangles_size = triangles.size();
+ size_t triangles_size = num_triangles();
bool flip = transform_negative_scaled;
if(triangles_size) {
float3 *verts_ptr = &verts[0];
- Triangle *triangles_ptr = &triangles[0];
for(size_t i = 0; i < triangles_size; i++) {
- fN[i] = compute_face_normal(triangles_ptr[i], verts_ptr);
+ fN[i] = compute_face_normal(get_triangle(i), verts_ptr);
if(flip)
fN[i] = -fN[i];
@@ -329,7 +491,7 @@ void Mesh::add_vertex_normals()
{
bool flip = transform_negative_scaled;
size_t verts_size = verts.size();
- size_t triangles_size = triangles.size();
+ size_t triangles_size = num_triangles();
/* static vertex normals */
if(!attributes.find(ATTR_STD_VERTEX_NORMAL)) {
@@ -344,11 +506,10 @@ void Mesh::add_vertex_normals()
memset(vN, 0, verts.size()*sizeof(float3));
if(triangles_size) {
- Triangle *triangles_ptr = &triangles[0];
for(size_t i = 0; i < triangles_size; i++)
for(size_t j = 0; j < 3; j++)
- vN[triangles_ptr[i].v[j]] += fN[i];
+ vN[get_triangle(i).v[j]] += fN[i];
}
for(size_t i = 0; i < verts_size; i++) {
@@ -374,12 +535,10 @@ void Mesh::add_vertex_normals()
memset(mN, 0, verts.size()*sizeof(float3));
if(triangles_size) {
- Triangle *triangles_ptr = &triangles[0];
-
for(size_t i = 0; i < triangles_size; i++) {
for(size_t j = 0; j < 3; j++) {
- float3 fN = compute_face_normal(triangles_ptr[i], mP);
- mN[triangles_ptr[i].v[j]] += fN;
+ float3 fN = compute_face_normal(get_triangle(i), mP);
+ mN[get_triangle(i).v[j]] += fN;
}
}
}
@@ -402,8 +561,8 @@ void Mesh::pack_normals(Scene *scene, uint *tri_shader, float4 *vnormal)
uint last_shader = -1;
bool last_smooth = false;
- size_t triangles_size = triangles.size();
- uint *shader_ptr = (shader.size())? &shader[0]: NULL;
+ size_t triangles_size = num_triangles();
+ int *shader_ptr = (shader.size())? &shader[0]: NULL;
bool do_transform = transform_applied;
Transform ntfm = transform_normal;
@@ -433,32 +592,34 @@ void Mesh::pack_normals(Scene *scene, uint *tri_shader, float4 *vnormal)
}
}
-void Mesh::pack_verts(float4 *tri_verts, float4 *tri_vindex, size_t vert_offset)
+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();
- if(verts_size) {
- float3 *verts_ptr = &verts[0];
+ if(verts_size && subd_faces.size()) {
+ float2 *vert_patch_uv_ptr = &vert_patch_uv[0];
for(size_t i = 0; i < verts_size; i++) {
- float3 p = verts_ptr[i];
- tri_verts[i] = make_float4(p.x, p.y, p.z, 0.0f);
+ tri_patch_uv[i] = vert_patch_uv_ptr[i];
}
}
- size_t triangles_size = triangles.size();
+ size_t triangles_size = num_triangles();
if(triangles_size) {
- Triangle *triangles_ptr = &triangles[0];
-
for(size_t i = 0; i < triangles_size; i++) {
- Triangle t = triangles_ptr[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_vindex[i] = make_float4(
- __int_as_float(t.v[0] + vert_offset),
- __int_as_float(t.v[1] + vert_offset),
- __int_as_float(t.v[2] + vert_offset),
- 0);
+ tri_patch[i] = (!subd_faces.size()) ? -1 : (triangle_patch[i]*8 + patch_offset);
}
}
}
@@ -466,27 +627,25 @@ void Mesh::pack_verts(float4 *tri_verts, float4 *tri_vindex, size_t vert_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();
- float4 *keys_ptr = NULL;
/* pack curve keys */
if(curve_keys_size) {
- keys_ptr = &curve_keys[0];
+ float3 *keys_ptr = &curve_keys[0];
+ float *radius_ptr = &curve_radius[0];
for(size_t i = 0; i < curve_keys_size; i++)
- curve_key_co[i] = keys_ptr[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 = curves.size();
+ size_t curve_num = num_curves();
if(curve_num) {
- Curve *curve_ptr = &curves[0];
- int shader_id = 0;
-
for(size_t i = 0; i < curve_num; i++) {
- Curve curve = curve_ptr[i];
- Shader *shader = (curve.shader < used_shaders.size()) ?
- used_shaders[curve.shader] : scene->default_surface;
+ 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, this, false);
curve_data[i] = make_float4(
@@ -498,7 +657,60 @@ void Mesh::pack_curves(Scene *scene, float4 *curve_key_co, float4 *curve_data, s
}
}
-void Mesh::compute_bvh(SceneParams *params, Progress *progress, int n, int total)
+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;
+
+ if(num_faces) {
+ 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(DeviceScene *dscene,
+ SceneParams *params,
+ Progress *progress,
+ int n,
+ int total)
{
if(progress->get_cancel())
return;
@@ -529,6 +741,8 @@ void Mesh::compute_bvh(SceneParams *params, Progress *progress, int n, int total
BVHParams bparams;
bparams.use_spatial_split = params->use_bvh_spatial_split;
bparams.use_qbvh = params->use_qbvh;
+ bparams.use_unaligned_nodes = dscene->data.bvh.have_curves &&
+ params->use_bvh_unaligned_nodes;
delete bvh;
bvh = BVH::create(bparams, objects);
@@ -621,8 +835,9 @@ void MeshManager::update_osl_attributes(Device *device, Scene *scene, vector<Att
osl_attr.value = attr;
osl_attr.offset = 0;
- og->attribute_map[i*ATTR_PRIM_TYPES][attr.name()] = osl_attr;
+ 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 */
@@ -652,11 +867,11 @@ void MeshManager::update_osl_attributes(Device *device, Scene *scene, vector<Att
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][stdname] = osl_attr;
+ 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][req.name] = osl_attr;
+ og->attribute_map[i*ATTR_PRIM_TYPES + ATTR_PRIM_TRIANGLE][req.name] = osl_attr;
}
}
@@ -681,6 +896,28 @@ void MeshManager::update_osl_attributes(Device *device, Scene *scene, vector<Att
og->attribute_map[i*ATTR_PRIM_TYPES + ATTR_PRIM_CURVE][req.name] = osl_attr;
}
}
+
+ if(req.subd_element != ATTR_ELEMENT_NONE) {
+ osl_attr.elem = req.subd_element;
+ osl_attr.offset = req.subd_offset;
+
+ 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
@@ -732,7 +969,7 @@ void MeshManager::update_svm_attributes(Device *device, DeviceScene *dscene, Sce
else
id = scene->shader_manager->get_attribute_id(req.std);
- if(mesh->triangles.size()) {
+ if(mesh->num_triangles()) {
attr_map[index].x = id;
attr_map[index].y = req.triangle_element;
attr_map[index].z = as_uint(req.triangle_offset);
@@ -747,7 +984,7 @@ void MeshManager::update_svm_attributes(Device *device, DeviceScene *dscene, Sce
index++;
- if(mesh->curves.size()) {
+ if(mesh->num_curves()) {
attr_map[index].x = id;
attr_map[index].y = req.curve_element;
attr_map[index].z = as_uint(req.curve_offset);
@@ -761,22 +998,32 @@ void MeshManager::update_svm_attributes(Device *device, DeviceScene *dscene, Sce
}
index++;
- }
- /* terminator */
- attr_map[index].x = ATTR_STD_NONE;
- attr_map[index].y = 0;
- attr_map[index].z = 0;
- attr_map[index].w = 0;
+ if(mesh->subd_faces.size()) {
+ attr_map[index].x = id;
+ attr_map[index].y = req.subd_element;
+ attr_map[index].z = as_uint(req.subd_offset);
- index++;
+ 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
+ attr_map[index].w = NODE_ATTR_FLOAT3;
+ }
- attr_map[index].x = ATTR_STD_NONE;
- attr_map[index].y = 0;
- attr_map[index].z = 0;
- attr_map[index].w = 0;
+ index++;
+ }
+
+ /* terminator */
+ for(int i = 0; i < ATTR_PRIM_TYPES; i++) {
+ attr_map[index].x = ATTR_STD_NONE;
+ attr_map[index].y = 0;
+ attr_map[index].z = 0;
+ attr_map[index].w = 0;
- index++;
+ index++;
+ }
}
/* copy to device */
@@ -786,17 +1033,13 @@ void MeshManager::update_svm_attributes(Device *device, DeviceScene *dscene, Sce
static void update_attribute_element_size(Mesh *mesh,
Attribute *mattr,
+ AttributePrimitive prim,
size_t *attr_float_size,
size_t *attr_float3_size,
size_t *attr_uchar4_size)
{
if(mattr) {
- size_t size = mattr->element_size(
- mesh->verts.size(),
- mesh->triangles.size(),
- mesh->motion_steps,
- mesh->curves.size(),
- mesh->curve_keys.size());
+ size_t size = mattr->element_size(mesh, prim);
if(mattr->element == ATTR_ELEMENT_VOXEL) {
/* pass */
@@ -824,6 +1067,7 @@ static void update_attribute_element_offset(Mesh *mesh,
vector<uchar4>& attr_uchar4,
size_t& attr_uchar4_offset,
Attribute *mattr,
+ AttributePrimitive prim,
TypeDesc& type,
int& offset,
AttributeElement& element)
@@ -834,12 +1078,7 @@ static void update_attribute_element_offset(Mesh *mesh,
type = mattr->type;
/* store attribute data in arrays */
- size_t size = mattr->element_size(
- mesh->verts.size(),
- mesh->triangles.size(),
- mesh->motion_steps,
- mesh->curves.size(),
- mesh->curve_keys.size());
+ size_t size = mattr->element_size(mesh, prim);
if(mattr->element == ATTR_ELEMENT_VOXEL) {
/* store slot in offset value */
@@ -893,10 +1132,18 @@ static void update_attribute_element_offset(Mesh *mesh,
offset -= mesh->vert_offset;
else if(element == ATTR_ELEMENT_VERTEX_MOTION)
offset -= mesh->vert_offset;
- else if(element == ATTR_ELEMENT_FACE)
- offset -= mesh->tri_offset;
- else if(element == ATTR_ELEMENT_CORNER || element == ATTR_ELEMENT_CORNER_BYTE)
- offset -= 3*mesh->tri_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)
@@ -946,23 +1193,23 @@ void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene,
foreach(AttributeRequest& req, attributes.requests) {
Attribute *triangle_mattr = mesh->attributes.find(req);
Attribute *curve_mattr = mesh->curve_attributes.find(req);
-
- /* todo: get rid of this exception, it's only here for giving some
- * working texture coordinate for subdivision as we can't preserve
- * any attributes yet */
- if(!triangle_mattr && req.std == ATTR_STD_GENERATED) {
- triangle_mattr = mesh->attributes.add(ATTR_STD_GENERATED);
- if(mesh->verts.size())
- memcpy(triangle_mattr->data_float3(), &mesh->verts[0], sizeof(float3)*mesh->verts.size());
- }
+ Attribute *subd_mattr = mesh->subd_attributes.find(req);
update_attribute_element_size(mesh,
triangle_mattr,
+ ATTR_PRIM_TRIANGLE,
&attr_float_size,
&attr_float3_size,
&attr_uchar4_size);
update_attribute_element_size(mesh,
curve_mattr,
+ ATTR_PRIM_CURVE,
+ &attr_float_size,
+ &attr_float3_size,
+ &attr_uchar4_size);
+ update_attribute_element_size(mesh,
+ subd_mattr,
+ ATTR_PRIM_SUBD,
&attr_float_size,
&attr_float3_size,
&attr_uchar4_size);
@@ -987,12 +1234,14 @@ void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene,
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,
attr_float, attr_float_offset,
attr_float3, attr_float3_offset,
attr_uchar4, attr_uchar4_offset,
triangle_mattr,
+ ATTR_PRIM_TRIANGLE,
req.triangle_type,
req.triangle_offset,
req.triangle_element);
@@ -1002,10 +1251,21 @@ void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene,
attr_float3, attr_float3_offset,
attr_uchar4, attr_uchar4_offset,
curve_mattr,
+ ATTR_PRIM_CURVE,
req.curve_type,
req.curve_offset,
req.curve_element);
+ update_attribute_element_offset(mesh,
+ attr_float, attr_float_offset,
+ attr_float3, attr_float3_offset,
+ attr_uchar4, attr_uchar4_offset,
+ subd_mattr,
+ ATTR_PRIM_SUBD,
+ req.subd_type,
+ req.subd_offset,
+ req.subd_element);
+
if(progress.get_cancel()) return;
}
}
@@ -1035,15 +1295,18 @@ void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene,
}
}
-void MeshManager::device_update_mesh(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
+void MeshManager::mesh_calc_offset(Scene *scene)
{
- /* count and update offsets */
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;
@@ -1051,26 +1314,97 @@ void MeshManager::device_update_mesh(Device *device, DeviceScene *dscene, Scene
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;
+ }
+ face_size += mesh->subd_faces.size();
+ corner_size += mesh->subd_face_corners.size();
+ }
+}
+
+void MeshManager::device_update_mesh(Device *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->triangles.size();
+ tri_size += mesh->num_triangles();
curve_key_size += mesh->curve_keys.size();
- curve_size += mesh->curves.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;
+ }
}
+ /* 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 {
+ PackedBVH& pack = bvh->pack;
+ for(size_t i = 0; i < pack.prim_index.size(); ++i) {
+ if ((pack.prim_type[i] & PRIMITIVE_ALL_TRIANGLE) != 0) {
+ tri_prim_index[pack.prim_index[i]] = pack.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.resize(tri_size);
float4 *vnormal = dscene->tri_vnormal.resize(vert_size);
- float4 *tri_verts = dscene->tri_verts.resize(vert_size);
- float4 *tri_vindex = dscene->tri_vindex.resize(tri_size);
+ uint4 *tri_vindex = dscene->tri_vindex.resize(tri_size);
+ uint *tri_patch = dscene->tri_patch.resize(tri_size);
+ float2 *tri_patch_uv = dscene->tri_patch_uv.resize(vert_size);
foreach(Mesh *mesh, scene->meshes) {
- mesh->pack_normals(scene, &tri_shader[mesh->tri_offset], &vnormal[mesh->vert_offset]);
- mesh->pack_verts(&tri_verts[mesh->vert_offset], &tri_vindex[mesh->tri_offset], mesh->vert_offset);
-
+ mesh->pack_normals(scene,
+ &tri_shader[mesh->tri_offset],
+ &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;
}
@@ -1079,8 +1413,9 @@ void MeshManager::device_update_mesh(Device *device, DeviceScene *dscene, Scene
device->tex_alloc("__tri_shader", dscene->tri_shader);
device->tex_alloc("__tri_vnormal", dscene->tri_vnormal);
- device->tex_alloc("__tri_verts", dscene->tri_verts);
device->tex_alloc("__tri_vindex", dscene->tri_vindex);
+ device->tex_alloc("__tri_patch", dscene->tri_patch);
+ device->tex_alloc("__tri_patch_uv", dscene->tri_patch_uv);
}
if(curve_size != 0) {
@@ -1097,6 +1432,33 @@ void MeshManager::device_update_mesh(Device *device, DeviceScene *dscene, Scene
device->tex_alloc("__curve_keys", dscene->curve_keys);
device->tex_alloc("__curves", dscene->curves);
}
+
+ if(patch_size != 0) {
+ progress.set_status("Updating Mesh", "Copying Patches to device");
+
+ uint *patch_data = dscene->patches.resize(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(progress.get_cancel()) return;
+ }
+
+ device->tex_alloc("__patches", dscene->patches);
+ }
+
+ if(for_displacement) {
+ float4 *prim_tri_verts = dscene->prim_tri_verts.resize(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]]);
+ }
+ }
+ device->tex_alloc("__prim_tri_verts", dscene->prim_tri_verts);
+ }
}
void MeshManager::device_update_bvh(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
@@ -1111,6 +1473,8 @@ void MeshManager::device_update_bvh(Device *device, DeviceScene *dscene, Scene *
bparams.top_level = true;
bparams.use_qbvh = scene->params.use_qbvh;
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;
delete bvh;
bvh = BVH::create(bparams, scene->objects);
@@ -1135,9 +1499,13 @@ void MeshManager::device_update_bvh(Device *device, DeviceScene *dscene, Scene *
dscene->object_node.reference((uint*)&pack.object_node[0], pack.object_node.size());
device->tex_alloc("__object_node", dscene->object_node);
}
- if(pack.tri_storage.size()) {
- dscene->tri_storage.reference(&pack.tri_storage[0], pack.tri_storage.size());
- device->tex_alloc("__tri_storage", dscene->tri_storage);
+ if(pack.prim_tri_index.size()) {
+ dscene->prim_tri_index.reference((uint*)&pack.prim_tri_index[0], pack.prim_tri_index.size());
+ device->tex_alloc("__prim_tri_index", dscene->prim_tri_index);
+ }
+ if(pack.prim_tri_verts.size()) {
+ dscene->prim_tri_verts.reference((float4*)&pack.prim_tri_verts[0], pack.prim_tri_verts.size());
+ device->tex_alloc("__prim_tri_verts", dscene->prim_tri_verts);
}
if(pack.prim_type.size()) {
dscene->prim_type.reference((uint*)&pack.prim_type[0], pack.prim_type.size());
@@ -1238,7 +1606,7 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen
VLOG(1) << "Total " << scene->meshes.size() << " meshes.";
- /* update normals */
+ /* Update normals. */
foreach(Mesh *mesh, scene->meshes) {
foreach(Shader *shader, mesh->used_shaders) {
if(shader->need_update_attributes)
@@ -1254,17 +1622,17 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen
}
/* Update images needed for true displacement. */
- bool need_displacement_images = false;
+ bool true_displacement_used = false;
bool old_need_object_flags_update = false;
foreach(Mesh *mesh, scene->meshes) {
if(mesh->need_update &&
mesh->displacement_method != Mesh::DISPLACE_BUMP)
{
- need_displacement_images = true;
+ true_displacement_used = true;
break;
}
}
- if(need_displacement_images) {
+ if(true_displacement_used) {
VLOG(1) << "Updating images used for true displacement.";
device_update_displacement_images(device, dscene, scene, progress);
old_need_object_flags_update = scene->object_manager->need_flags_update;
@@ -1275,42 +1643,46 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen
false);
}
- /* device update */
+ /* Device update. */
device_free(device, dscene);
- device_update_mesh(device, dscene, scene, progress);
+ 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 */
+ /* Update displacement. */
bool displacement_done = false;
-
- foreach(Mesh *mesh, scene->meshes)
- if(mesh->need_update && displace(device, dscene, scene, mesh, progress))
+ foreach(Mesh *mesh, scene->meshes) {
+ if(mesh->need_update &&
+ displace(device, dscene, scene, mesh, progress))
+ {
displacement_done = true;
+ }
+ }
- /* todo: properly handle cancel halfway displacement */
+ /* TODO: properly handle cancel halfway displacement */
if(progress.get_cancel()) return;
- /* device re-update after displacement */
+ /* Device re-update after displacement. */
if(displacement_done) {
device_free(device, dscene);
- device_update_mesh(device, dscene, scene, progress);
- if(progress.get_cancel()) return;
-
device_update_attributes(device, dscene, scene, progress);
if(progress.get_cancel()) return;
}
- /* update bvh */
+ /* Update bvh. */
size_t i = 0, num_bvh = 0;
-
- foreach(Mesh *mesh, scene->meshes)
- if(mesh->need_update && mesh->need_build_bvh())
+ foreach(Mesh *mesh, scene->meshes) {
+ if(mesh->need_update && mesh->need_build_bvh()) {
num_bvh++;
+ }
+ }
TaskPool pool;
@@ -1318,6 +1690,7 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen
if(mesh->need_update) {
pool.push(function_bind(&Mesh::compute_bvh,
mesh,
+ dscene,
&scene->params,
&progress,
i,
@@ -1333,8 +1706,9 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen
VLOG(2) << "Objects BVH build pool statistics:\n"
<< summary.full_report();
- foreach(Shader *shader, scene->shaders)
+ foreach(Shader *shader, scene->shaders) {
shader->need_update_attributes = false;
+ }
#ifdef __OBJECT_MOTION__
Scene::MotionType need_motion = scene->need_motion(device->info.advanced_shading);
@@ -1343,18 +1717,23 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen
bool motion_blur = false;
#endif
- /* update obejcts */
+ /* Update objects. */
vector<Object *> volume_objects;
- foreach(Object *object, scene->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(need_displacement_images) {
+ if(true_displacement_used) {
/* Re-tag flags for update, so they're re-evaluated
* for meshes with correct bounding boxes.
*
@@ -1370,7 +1749,8 @@ void MeshManager::device_free(Device *device, DeviceScene *dscene)
device->tex_free(dscene->bvh_nodes);
device->tex_free(dscene->bvh_leaf_nodes);
device->tex_free(dscene->object_node);
- device->tex_free(dscene->tri_storage);
+ device->tex_free(dscene->prim_tri_verts);
+ device->tex_free(dscene->prim_tri_index);
device->tex_free(dscene->prim_type);
device->tex_free(dscene->prim_visibility);
device->tex_free(dscene->prim_index);
@@ -1378,9 +1758,11 @@ void MeshManager::device_free(Device *device, DeviceScene *dscene)
device->tex_free(dscene->tri_shader);
device->tex_free(dscene->tri_vnormal);
device->tex_free(dscene->tri_vindex);
- device->tex_free(dscene->tri_verts);
+ device->tex_free(dscene->tri_patch);
+ device->tex_free(dscene->tri_patch_uv);
device->tex_free(dscene->curves);
device->tex_free(dscene->curve_keys);
+ device->tex_free(dscene->patches);
device->tex_free(dscene->attributes_map);
device->tex_free(dscene->attributes_float);
device->tex_free(dscene->attributes_float3);
@@ -1388,7 +1770,8 @@ void MeshManager::device_free(Device *device, DeviceScene *dscene)
dscene->bvh_nodes.clear();
dscene->object_node.clear();
- dscene->tri_storage.clear();
+ dscene->prim_tri_verts.clear();
+ dscene->prim_tri_index.clear();
dscene->prim_type.clear();
dscene->prim_visibility.clear();
dscene->prim_index.clear();
@@ -1396,9 +1779,11 @@ void MeshManager::device_free(Device *device, DeviceScene *dscene)
dscene->tri_shader.clear();
dscene->tri_vnormal.clear();
dscene->tri_vindex.clear();
- dscene->tri_verts.clear();
+ dscene->tri_patch.clear();
+ dscene->tri_patch_uv.clear();
dscene->curves.clear();
dscene->curve_keys.clear();
+ dscene->patches.clear();
dscene->attributes_map.clear();
dscene->attributes_float.clear();
dscene->attributes_float3.clear();
@@ -1448,74 +1833,5 @@ bool Mesh::need_attribute(Scene * /*scene*/, ustring name)
return false;
}
-void Mesh::tessellate(DiagSplit *split)
-{
- int num_faces = triangles.size();
-
- add_face_normals();
- add_vertex_normals();
-
- Attribute *attr_fN = attributes.find(ATTR_STD_FACE_NORMAL);
- float3 *fN = attr_fN->data_float3();
-
- Attribute *attr_vN = attributes.find(ATTR_STD_VERTEX_NORMAL);
- float3 *vN = attr_vN->data_float3();
-
- for(int f = 0; f < num_faces; f++) {
- if(!forms_quad[f]) {
- /* triangle */
- LinearTrianglePatch patch;
- float3 *hull = patch.hull;
- float3 *normals = patch.normals;
-
- for(int i = 0; i < 3; i++) {
- hull[i] = verts[triangles[f].v[i]];
- }
-
- if(smooth[f]) {
- for(int i = 0; i < 3; i++) {
- normals[i] = vN[triangles[f].v[i]];
- }
- }
- else {
- for(int i = 0; i < 3; i++) {
- normals[i] = fN[f];
- }
- }
-
- split->split_triangle(&patch);
- }
- else {
- /* quad */
- LinearQuadPatch patch;
- float3 *hull = patch.hull;
- float3 *normals = patch.normals;
-
- hull[0] = verts[triangles[f ].v[0]];
- hull[1] = verts[triangles[f ].v[1]];
- hull[3] = verts[triangles[f ].v[2]];
- hull[2] = verts[triangles[f+1].v[2]];
-
- if(smooth[f]) {
- normals[0] = vN[triangles[f ].v[0]];
- normals[1] = vN[triangles[f ].v[1]];
- normals[3] = vN[triangles[f ].v[2]];
- normals[2] = vN[triangles[f+1].v[2]];
- }
- else {
- for(int i = 0; i < 4; i++) {
- normals[i] = fN[f];
- }
- }
-
- split->split_quad(&patch);
-
- // consume second triangle in quad
- f++;
- }
-
- }
-}
-
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/mesh.h b/intern/cycles/render/mesh.h
index 557b664bff3..c9ae9aab888 100644
--- a/intern/cycles/render/mesh.h
+++ b/intern/cycles/render/mesh.h
@@ -18,6 +18,7 @@
#define __MESH_H__
#include "attribute.h"
+#include "node.h"
#include "shader.h"
#include "util_boundbox.h"
@@ -42,8 +43,10 @@ class DiagSplit;
/* Mesh */
-class Mesh {
+class Mesh : public Node {
public:
+ NODE_DECLARE;
+
/* Mesh Triangle */
struct Triangle {
int v[3];
@@ -51,15 +54,60 @@ public:
void bounds_grow(const float3 *verts, BoundBox& bounds) 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;
- uint shader;
int num_segments() { return num_keys - 1; }
- void bounds_grow(const int k, const float4 *curve_keys, BoundBox& bounds) const;
+ void bounds_grow(const int k,
+ const float3 *curve_keys,
+ const float *curve_radius,
+ BoundBox& bounds) const;
+ void bounds_grow(const int k,
+ const float3 *curve_keys,
+ const float *curve_radius,
+ const Transform& aligned_space,
+ BoundBox& bounds) 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; }
};
/* Displacement */
@@ -71,7 +119,13 @@ public:
DISPLACE_NUM_METHODS,
};
- ustring name;
+ enum SubdivisionType {
+ SUBDIVISION_NONE,
+ SUBDIVISION_LINEAR,
+ SUBDIVISION_CATMULL_CLARK,
+ };
+
+ SubdivisionType subdivision_type;
/* Mesh Data */
enum GeometryFlags {
@@ -82,21 +136,31 @@ public:
int geometry_flags; /* used to distinguish meshes with no verts
and meshed for which geometry is not created */
- vector<float3> verts;
- vector<Triangle> triangles;
- vector<uint> shader;
- vector<bool> smooth;
- vector<bool> forms_quad; /* used to tell if triangle is part of a quad patch */
+ 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;
bool has_volume; /* Set in the device_update_flags(). */
bool has_surface_bssrdf; /* Set in the device_update_flags(). */
- vector<float4> curve_keys; /* co + radius */
- vector<Curve> curves;
+ 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;
vector<Shader*> used_shaders;
AttributeSet attributes;
AttributeSet curve_attributes;
+ AttributeSet subd_attributes;
BoundBox bounds;
bool transform_applied;
@@ -119,16 +183,29 @@ public:
size_t curve_offset;
size_t curvekey_offset;
+ size_t patch_offset;
+ size_t face_offset;
+ size_t corner_offset;
+
+ size_t num_subd_verts;
+
/* Functions */
Mesh();
~Mesh();
- void reserve(int numverts, int numfaces, int numcurves, int numcurvekeys);
+ 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();
- void set_triangle(int i, int v0, int v1, int v2, int shader, bool smooth, bool forms_quad = false);
- void add_triangle(int v0, int v1, int v2, int shader, bool smooth, bool forms_quad = 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 num_keys, int shader);
+ void add_curve(int first_key, int shader);
+ void add_subd_face(int* corners, int num_corners, int shader_, bool smooth_);
int split_vertex(int vertex);
void compute_bounds();
@@ -136,9 +213,20 @@ public:
void add_vertex_normals();
void pack_normals(Scene *scene, uint *shader, float4 *vnormal);
- void pack_verts(float4 *tri_verts, float4 *tri_vindex, size_t vert_offset);
+ 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 compute_bvh(SceneParams *params, Progress *progress, int n, int total);
+ void pack_patches(uint *patch_data, uint vert_offset, uint face_offset, uint corner_offset);
+
+ void compute_bvh(DeviceScene *dscene,
+ SceneParams *params,
+ Progress *progress,
+ int n,
+ int total);
bool need_attribute(Scene *scene, AttributeStandard std);
bool need_attribute(Scene *scene, ustring name);
@@ -182,15 +270,41 @@ public:
void update_svm_attributes(Device *device, DeviceScene *dscene, Scene *scene, vector<AttributeRequestSet>& mesh_attributes);
void device_update(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, 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_flags(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
- void device_update_displacement_images(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
+
void device_free(Device *device, DeviceScene *dscene);
void tag_update(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_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_bvh(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress& progress);
+
+ void device_update_displacement_images(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress& progress);
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/mesh_displace.cpp b/intern/cycles/render/mesh_displace.cpp
index d19bf2084d7..95f46ff02a2 100644
--- a/intern/cycles/render/mesh_displace.cpp
+++ b/intern/cycles/render/mesh_displace.cpp
@@ -60,8 +60,9 @@ bool MeshManager::displace(Device *device, DeviceScene *dscene, Scene *scene, Me
uint4 *d_input_data = d_input.resize(num_verts);
size_t d_input_size = 0;
- for(size_t i = 0; i < mesh->triangles.size(); i++) {
- Mesh::Triangle t = mesh->triangles[i];
+ 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;
@@ -146,8 +147,8 @@ bool MeshManager::displace(Device *device, DeviceScene *dscene, Scene *scene, Me
float4 *offset = (float4*)d_output.data_pointer;
Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
- for(size_t i = 0; i < mesh->triangles.size(); i++) {
- Mesh::Triangle t = mesh->triangles[i];
+ 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;
diff --git a/intern/cycles/render/mesh_subdivision.cpp b/intern/cycles/render/mesh_subdivision.cpp
new file mode 100644
index 00000000000..fe8e41e8d35
--- /dev/null
+++ b/intern/cycles/render/mesh_subdivision.cpp
@@ -0,0 +1,224 @@
+/*
+ * Copyright 2011-2016 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mesh.h"
+#include "attribute.h"
+
+#include "subd_split.h"
+#include "subd_patch.h"
+
+#include "util_foreach.h"
+
+CCL_NAMESPACE_BEGIN
+
+void Mesh::tessellate(DiagSplit *split)
+{
+ int num_faces = subd_faces.size();
+
+ 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];
+
+ if(face.is_quad()) {
+ /* quad */
+ LinearQuadPatch patch;
+ float3 *hull = patch.hull;
+ float3 *normals = patch.normals;
+
+ patch.patch_index = face.ptex_offset;
+ patch.shader = face.shader;
+
+ 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]);
+
+ /* 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.
+ */
+ QuadDice::SubPatch subpatch;
+ subpatch.patch = &patch;
+
+ 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(&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(&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(&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(&patch, &subpatch);
+ }
+ else {
+ /* ngon */
+ 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) {
+ 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;
+ }
+ }
+}
+
+CCL_NAMESPACE_END
+
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index f75fef1c13e..cf366367873 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -19,8 +19,11 @@
#include "nodes.h"
#include "scene.h"
#include "svm.h"
+#include "svm_color_util.h"
+#include "svm_ramp_util.h"
#include "svm_math_util.h"
#include "osl.h"
+#include "constant_fold.h"
#include "util_sky_model.h"
#include "util_foreach.h"
@@ -30,64 +33,40 @@ CCL_NAMESPACE_BEGIN
/* Texture Mapping */
-static ShaderEnum texture_mapping_type_init()
-{
- ShaderEnum enm;
-
- enm.insert("Point", TextureMapping::POINT);
- enm.insert("Texture", TextureMapping::TEXTURE);
- enm.insert("Vector", TextureMapping::VECTOR);
- enm.insert("Normal", TextureMapping::NORMAL);
-
- return enm;
-}
-
-static ShaderEnum texture_mapping_mapping_init()
-{
- ShaderEnum enm;
-
- enm.insert("None", TextureMapping::NONE);
- enm.insert("X", TextureMapping::X);
- enm.insert("Y", TextureMapping::Y);
- enm.insert("Z", TextureMapping::Z);
-
- return enm;
-}
-
-static ShaderEnum texture_mapping_projection_init()
-{
- ShaderEnum enm;
-
- enm.insert("Flat", TextureMapping::FLAT);
- enm.insert("Cube", TextureMapping::CUBE);
- enm.insert("Tube", TextureMapping::TUBE);
- enm.insert("Sphere", TextureMapping::SPHERE);
-
- return enm;
-}
-
-ShaderEnum TextureMapping::type_enum = texture_mapping_type_init();
-ShaderEnum TextureMapping::mapping_enum = texture_mapping_mapping_init();
-ShaderEnum TextureMapping::projection_enum = texture_mapping_projection_init();
+#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);
TextureMapping::TextureMapping()
{
- translation = make_float3(0.0f, 0.0f, 0.0f);
- rotation = make_float3(0.0f, 0.0f, 0.0f);
- scale = make_float3(1.0f, 1.0f, 1.0f);
-
- min = make_float3(-FLT_MAX, -FLT_MAX, -FLT_MAX);
- max = make_float3(FLT_MAX, FLT_MAX, FLT_MAX);
-
- use_minmax = false;
-
- x_mapping = X;
- y_mapping = Y;
- z_mapping = Z;
-
- type = TEXTURE;
-
- projection = FLAT;
}
Transform TextureMapping::compute_transform()
@@ -193,7 +172,7 @@ 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(SHADER_SOCKET_VECTOR);
+ int offset_out = compiler.stack_find_offset(SocketType::VECTOR);
compile(compiler, offset_in, offset_out);
@@ -206,7 +185,7 @@ int TextureMapping::compile_begin(SVMCompiler& compiler, ShaderInput *vector_in)
void TextureMapping::compile_end(SVMCompiler& compiler, ShaderInput *vector_in, int vector_offset)
{
if(!skip()) {
- compiler.stack_clear_offset(vector_in->type, vector_offset);
+ compiler.stack_clear_offset(vector_in->type(), vector_offset);
}
}
@@ -222,72 +201,66 @@ void TextureMapping::compile(OSLCompiler &compiler)
/* Image Texture */
-static ShaderEnum color_space_init()
+NODE_DEFINE(ImageTextureNode)
{
- ShaderEnum enm;
+ NodeType* type = NodeType::add("image_texture", create, NodeType::SHADER);
- enm.insert("None", 0);
- enm.insert("Color", 1);
+ TEXTURE_MAPPING_DEFINE(ImageTextureNode);
- return enm;
-}
+ SOCKET_STRING(filename, "Filename", ustring(""));
-static ShaderEnum image_projection_init()
-{
- ShaderEnum enm;
+ 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);
- enm.insert("Flat", NODE_IMAGE_PROJ_FLAT);
- enm.insert("Box", NODE_IMAGE_PROJ_BOX);
- enm.insert("Sphere", NODE_IMAGE_PROJ_SPHERE);
- enm.insert("Tube", NODE_IMAGE_PROJ_TUBE);
+ SOCKET_BOOLEAN(use_alpha, "Use Alpha", true);
- return enm;
-}
+ 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 const char* get_osl_interpolation_parameter(InterpolationType interpolation)
-{
- switch(interpolation) {
- case INTERPOLATION_CLOSEST:
- return "closest";
- case INTERPOLATION_CUBIC:
- return "cubic";
- case INTERPOLATION_SMART:
- return "smart";
- case INTERPOLATION_LINEAR:
- default:
- return "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 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);
-ShaderEnum ImageTextureNode::color_space_enum = color_space_init();
-ShaderEnum ImageTextureNode::projection_enum = image_projection_init();
+ 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");
+
+ return type;
+}
ImageTextureNode::ImageTextureNode()
-: ImageSlotTextureNode("image_texture")
+: ImageSlotTextureNode(node_type)
{
image_manager = NULL;
slot = -1;
is_float = -1;
is_linear = false;
- use_alpha = true;
- filename = "";
builtin_data = NULL;
- color_space = ustring("Color");
- projection = ustring("Flat");
- interpolation = INTERPOLATION_LINEAR;
- extension = EXTENSION_REPEAT;
- projection_blend = 0.0f;
animated = false;
-
- add_input("Vector", SHADER_SOCKET_POINT, ShaderInput::TEXTURE_UV);
- add_output("Color", SHADER_SOCKET_COLOR);
- add_output("Alpha", SHADER_SOCKET_FLOAT);
}
ImageTextureNode::~ImageTextureNode()
{
if(image_manager) {
- image_manager->remove_image(filename,
+ image_manager->remove_image(filename.string(),
builtin_data,
interpolation,
extension);
@@ -328,7 +301,7 @@ void ImageTextureNode::compile(SVMCompiler& compiler)
image_manager = compiler.image_manager;
if(is_float == -1) {
bool is_float_bool;
- slot = image_manager->add_image(filename,
+ slot = image_manager->add_image(filename.string(),
builtin_data,
animated,
0,
@@ -341,10 +314,10 @@ void ImageTextureNode::compile(SVMCompiler& compiler)
}
if(slot != -1) {
- int srgb = (is_linear || color_space != "Color")? 0: 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 != "Box") {
+ if(projection != NODE_IMAGE_PROJ_BOX) {
compiler.add_node(NODE_TEX_IMAGE,
slot,
compiler.encode_uchar4(
@@ -352,7 +325,7 @@ void ImageTextureNode::compile(SVMCompiler& compiler)
compiler.stack_assign_if_linked(color_out),
compiler.stack_assign_if_linked(alpha_out),
srgb),
- projection_enum[projection]);
+ projection);
}
else {
compiler.add_node(NODE_TEX_IMAGE_BOX,
@@ -390,13 +363,13 @@ void ImageTextureNode::compile(OSLCompiler& compiler)
if(is_float == -1) {
if(builtin_data == NULL) {
ImageManager::ImageDataType type;
- type = image_manager->get_image_metadata(filename, NULL, is_linear);
+ type = image_manager->get_image_metadata(filename.string(), NULL, is_linear);
if(type == ImageManager::IMAGE_DATA_TYPE_FLOAT || type == ImageManager::IMAGE_DATA_TYPE_FLOAT4)
is_float = 1;
}
else {
bool is_float_bool;
- slot = image_manager->add_image(filename,
+ slot = image_manager->add_image(filename.string(),
builtin_data,
animated,
0,
@@ -410,7 +383,7 @@ void ImageTextureNode::compile(OSLCompiler& compiler)
}
if(slot == -1) {
- compiler.parameter("filename", filename.c_str());
+ compiler.parameter(this, "filename");
}
else {
/* TODO(sergey): It's not so simple to pass custom attribute
@@ -421,71 +394,72 @@ void ImageTextureNode::compile(OSLCompiler& compiler)
*/
compiler.parameter("filename", string_printf("@%d", slot).c_str());
}
- if(is_linear || color_space != "Color")
- compiler.parameter("color_space", "Linear");
+ if(is_linear || color_space != NODE_COLOR_SPACE_COLOR)
+ compiler.parameter("color_space", "linear");
else
compiler.parameter("color_space", "sRGB");
- compiler.parameter("projection", projection);
- compiler.parameter("projection_blend", projection_blend);
+ 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("interpolation", get_osl_interpolation_parameter(interpolation));
-
- switch(extension) {
- case EXTENSION_EXTEND:
- compiler.parameter("wrap", "clamp");
- break;
- case EXTENSION_CLIP:
- compiler.parameter("wrap", "black");
- break;
- case EXTENSION_REPEAT:
- default:
- compiler.parameter("wrap", "periodic");
- break;
- }
+ compiler.parameter(this, "interpolation");
+ compiler.parameter(this, "extension");
compiler.add(this, "node_image_texture");
}
/* Environment Texture */
-static ShaderEnum env_projection_init()
+NODE_DEFINE(EnvironmentTextureNode)
{
- ShaderEnum enm;
+ NodeType* type = NodeType::add("environment_texture", create, NodeType::SHADER);
- enm.insert("Equirectangular", 0);
- enm.insert("Mirror Ball", 1);
+ TEXTURE_MAPPING_DEFINE(EnvironmentTextureNode);
- return enm;
-}
+ 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);
+
+ 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 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);
-ShaderEnum EnvironmentTextureNode::color_space_enum = color_space_init();
-ShaderEnum EnvironmentTextureNode::projection_enum = env_projection_init();
+ SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_OUT_FLOAT(alpha, "Alpha");
+
+ return type;
+}
EnvironmentTextureNode::EnvironmentTextureNode()
-: ImageSlotTextureNode("environment_texture")
+: ImageSlotTextureNode(node_type)
{
image_manager = NULL;
slot = -1;
is_float = -1;
is_linear = false;
- use_alpha = true;
- filename = "";
builtin_data = NULL;
- color_space = ustring("Color");
- interpolation = INTERPOLATION_LINEAR;
- projection = ustring("Equirectangular");
animated = false;
-
- add_input("Vector", SHADER_SOCKET_VECTOR, ShaderInput::POSITION);
- add_output("Color", SHADER_SOCKET_COLOR);
- add_output("Alpha", SHADER_SOCKET_FLOAT);
}
EnvironmentTextureNode::~EnvironmentTextureNode()
{
if(image_manager) {
- image_manager->remove_image(filename,
+ image_manager->remove_image(filename.string(),
builtin_data,
interpolation,
EXTENSION_REPEAT);
@@ -524,7 +498,7 @@ void EnvironmentTextureNode::compile(SVMCompiler& compiler)
image_manager = compiler.image_manager;
if(slot == -1) {
bool is_float_bool;
- slot = image_manager->add_image(filename,
+ slot = image_manager->add_image(filename.string(),
builtin_data,
animated,
0,
@@ -537,7 +511,7 @@ void EnvironmentTextureNode::compile(SVMCompiler& compiler)
}
if(slot != -1) {
- int srgb = (is_linear || color_space != "Color")? 0: 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,
@@ -547,7 +521,7 @@ void EnvironmentTextureNode::compile(SVMCompiler& compiler)
compiler.stack_assign_if_linked(color_out),
compiler.stack_assign_if_linked(alpha_out),
srgb),
- projection_enum[projection]);
+ projection);
tex_mapping.compile_end(compiler, vector_in, vector_offset);
}
@@ -577,13 +551,13 @@ void EnvironmentTextureNode::compile(OSLCompiler& compiler)
if(is_float == -1) {
if(builtin_data == NULL) {
ImageManager::ImageDataType type;
- type = image_manager->get_image_metadata(filename, NULL, is_linear);
+ type = image_manager->get_image_metadata(filename.string(), NULL, is_linear);
if(type == ImageManager::IMAGE_DATA_TYPE_FLOAT || type == ImageManager::IMAGE_DATA_TYPE_FLOAT4)
is_float = 1;
}
else {
bool is_float_bool;
- slot = image_manager->add_image(filename,
+ slot = image_manager->add_image(filename.string(),
builtin_data,
animated,
0,
@@ -597,19 +571,18 @@ void EnvironmentTextureNode::compile(OSLCompiler& compiler)
}
if(slot == -1) {
- compiler.parameter("filename", filename.c_str());
+ compiler.parameter(this, "filename");
}
else {
compiler.parameter("filename", string_printf("@%d", slot).c_str());
}
- compiler.parameter("projection", projection);
- if(is_linear || color_space != "Color")
- compiler.parameter("color_space", "Linear");
+ 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("interpolation", get_osl_interpolation_parameter(interpolation));
-
+ compiler.parameter(this, "interpolation");
compiler.parameter("is_float", is_float);
compiler.parameter("use_alpha", !alpha_out->links.empty());
compiler.add(this, "node_environment_texture");
@@ -640,10 +613,10 @@ static float sky_perez_function(float lam[6], float theta, float 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
- */
+ * 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;
@@ -738,29 +711,31 @@ static void sky_texture_precompute_new(SunSky *sunsky, float3 dir, float turbidi
arhosekskymodelstate_free(sky_state);
}
-static ShaderEnum sky_type_init()
+NODE_DEFINE(SkyTextureNode)
{
- ShaderEnum enm;
+ NodeType* type = NodeType::add("sky_texture", create, NodeType::SHADER);
- enm.insert("Preetham", NODE_SKY_OLD);
- enm.insert("Hosek / Wilkie", NODE_SKY_NEW);
+ TEXTURE_MAPPING_DEFINE(SkyTextureNode);
- return enm;
-}
+ 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);
-ShaderEnum SkyTextureNode::type_enum = sky_type_init();
+ 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("sky_texture")
+: TextureNode(node_type)
{
- type = ustring("Hosek / Wilkie");
-
- sun_direction = make_float3(0.0f, 0.0f, 1.0f);
- turbidity = 2.2f;
- ground_albedo = 0.3f;
-
- add_input("Vector", SHADER_SOCKET_VECTOR, ShaderInput::POSITION);
- add_output("Color", SHADER_SOCKET_COLOR);
}
void SkyTextureNode::compile(SVMCompiler& compiler)
@@ -769,18 +744,17 @@ void SkyTextureNode::compile(SVMCompiler& compiler)
ShaderOutput *color_out = output("Color");
SunSky sunsky;
- if(type_enum[type] == NODE_SKY_OLD)
+ if(type == NODE_SKY_OLD)
sky_texture_precompute_old(&sunsky, sun_direction, turbidity);
- else if(type_enum[type] == NODE_SKY_NEW)
+ 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);
- int sky_model = type_enum[type];
compiler.stack_assign(color_out);
- compiler.add_node(NODE_TEX_SKY, vector_offset, compiler.stack_assign(color_out), sky_model);
+ 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]));
@@ -798,15 +772,14 @@ void SkyTextureNode::compile(OSLCompiler& compiler)
tex_mapping.compile(compiler);
SunSky sunsky;
-
- if(type_enum[type] == NODE_SKY_OLD)
+ if(type == NODE_SKY_OLD)
sky_texture_precompute_old(&sunsky, sun_direction, turbidity);
- else if(type_enum[type] == NODE_SKY_NEW)
+ else if(type == NODE_SKY_NEW)
sky_texture_precompute_new(&sunsky, sun_direction, turbidity, ground_albedo);
else
assert(false);
- compiler.parameter("sky_model", type);
+ 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));
@@ -818,31 +791,33 @@ void SkyTextureNode::compile(OSLCompiler& compiler)
/* Gradient Texture */
-static ShaderEnum gradient_type_init()
+NODE_DEFINE(GradientTextureNode)
{
- ShaderEnum enm;
+ NodeType* type = NodeType::add("gradient_texture", create, NodeType::SHADER);
- enm.insert("Linear", NODE_BLEND_LINEAR);
- enm.insert("Quadratic", NODE_BLEND_QUADRATIC);
- enm.insert("Easing", NODE_BLEND_EASING);
- enm.insert("Diagonal", NODE_BLEND_DIAGONAL);
- enm.insert("Radial", NODE_BLEND_RADIAL);
- enm.insert("Quadratic Sphere", NODE_BLEND_QUADRATIC_SPHERE);
- enm.insert("Spherical", NODE_BLEND_SPHERICAL);
+ TEXTURE_MAPPING_DEFINE(GradientTextureNode);
- return enm;
-}
+ 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);
-ShaderEnum GradientTextureNode::type_enum = gradient_type_init();
+ SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_OUT_FLOAT(fac, "Fac");
+
+ return type;
+}
GradientTextureNode::GradientTextureNode()
-: TextureNode("gradient_texture")
+: TextureNode(node_type)
{
- type = ustring("Linear");
-
- add_input("Vector", SHADER_SOCKET_POINT, ShaderInput::TEXTURE_GENERATED);
- add_output("Color", SHADER_SOCKET_COLOR);
- add_output("Fac", SHADER_SOCKET_FLOAT);
}
void GradientTextureNode::compile(SVMCompiler& compiler)
@@ -855,7 +830,7 @@ void GradientTextureNode::compile(SVMCompiler& compiler)
compiler.add_node(NODE_TEX_GRADIENT,
compiler.encode_uchar4(
- type_enum[type],
+ type,
vector_offset,
compiler.stack_assign_if_linked(fac_out),
compiler.stack_assign_if_linked(color_out)));
@@ -867,22 +842,32 @@ void GradientTextureNode::compile(OSLCompiler& compiler)
{
tex_mapping.compile(compiler);
- compiler.parameter("Type", type);
+ compiler.parameter(this, "type");
compiler.add(this, "node_gradient_texture");
}
/* Noise Texture */
-NoiseTextureNode::NoiseTextureNode()
-: TextureNode("noise_texture")
+NODE_DEFINE(NoiseTextureNode)
{
- add_input("Vector", SHADER_SOCKET_POINT, ShaderInput::TEXTURE_GENERATED);
- add_input("Scale", SHADER_SOCKET_FLOAT, 1.0f);
- add_input("Detail", SHADER_SOCKET_FLOAT, 2.0f);
- add_input("Distortion", SHADER_SOCKET_FLOAT, 0.0f);
+ NodeType* type = NodeType::add("noise_texture", create, NodeType::SHADER);
+
+ 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_OUT_COLOR(color, "Color");
+ SOCKET_OUT_FLOAT(fac, "Fac");
+
+ return type;
+}
- add_output("Color", SHADER_SOCKET_COLOR);
- add_output("Fac", SHADER_SOCKET_FLOAT);
+NoiseTextureNode::NoiseTextureNode()
+: TextureNode(node_type)
+{
}
void NoiseTextureNode::compile(SVMCompiler& compiler)
@@ -906,9 +891,9 @@ void NoiseTextureNode::compile(SVMCompiler& compiler)
compiler.stack_assign_if_linked(color_out),
compiler.stack_assign_if_linked(fac_out)));
compiler.add_node(
- __float_as_int(scale_in->value.x),
- __float_as_int(detail_in->value.x),
- __float_as_int(distortion_in->value.x));
+ __float_as_int(scale),
+ __float_as_int(detail),
+ __float_as_int(distortion));
tex_mapping.compile_end(compiler, vector_in, vector_offset);
}
@@ -922,28 +907,29 @@ void NoiseTextureNode::compile(OSLCompiler& compiler)
/* Voronoi Texture */
-static ShaderEnum voronoi_coloring_init()
+NODE_DEFINE(VoronoiTextureNode)
{
- ShaderEnum enm;
+ NodeType* type = NodeType::add("voronoi_texture", create, NodeType::SHADER);
- enm.insert("Intensity", NODE_VORONOI_INTENSITY);
- enm.insert("Cells", NODE_VORONOI_CELLS);
+ TEXTURE_MAPPING_DEFINE(VoronoiTextureNode);
- return enm;
-}
+ 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);
-ShaderEnum VoronoiTextureNode::coloring_enum = voronoi_coloring_init();
+ SOCKET_IN_FLOAT(scale, "Scale", 1.0f);
+ SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_GENERATED);
-VoronoiTextureNode::VoronoiTextureNode()
-: TextureNode("voronoi_texture")
-{
- coloring = ustring("Intensity");
+ SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_OUT_FLOAT(fac, "Fac");
- add_input("Scale", SHADER_SOCKET_FLOAT, 1.0f);
- add_input("Vector", SHADER_SOCKET_POINT, ShaderInput::TEXTURE_GENERATED);
+ return type;
+}
- add_output("Color", SHADER_SOCKET_COLOR);
- add_output("Fac", SHADER_SOCKET_FLOAT);
+VoronoiTextureNode::VoronoiTextureNode()
+: TextureNode(node_type)
+{
}
void VoronoiTextureNode::compile(SVMCompiler& compiler)
@@ -956,13 +942,13 @@ void VoronoiTextureNode::compile(SVMCompiler& compiler)
int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
compiler.add_node(NODE_TEX_VORONOI,
- coloring_enum[coloring],
+ coloring,
compiler.encode_uchar4(
compiler.stack_assign_if_linked(scale_in),
vector_offset,
compiler.stack_assign(fac_out),
compiler.stack_assign(color_out)),
- __float_as_int(scale_in->value.x));
+ __float_as_int(scale));
tex_mapping.compile_end(compiler, vector_in, vector_offset);
}
@@ -971,42 +957,43 @@ void VoronoiTextureNode::compile(OSLCompiler& compiler)
{
tex_mapping.compile(compiler);
- compiler.parameter("Coloring", coloring);
+ compiler.parameter(this, "coloring");
compiler.add(this, "node_voronoi_texture");
}
/* Musgrave Texture */
-static ShaderEnum musgrave_type_init()
+NODE_DEFINE(MusgraveTextureNode)
{
- ShaderEnum enm;
+ NodeType* type = NodeType::add("musgrave_texture", create, NodeType::SHADER);
- enm.insert("Multifractal", NODE_MUSGRAVE_MULTIFRACTAL);
- enm.insert("fBM", NODE_MUSGRAVE_FBM);
- enm.insert("Hybrid Multifractal", NODE_MUSGRAVE_HYBRID_MULTIFRACTAL);
- enm.insert("Ridged Multifractal", NODE_MUSGRAVE_RIDGED_MULTIFRACTAL);
- enm.insert("Hetero Terrain", NODE_MUSGRAVE_HETERO_TERRAIN);
+ TEXTURE_MAPPING_DEFINE(MusgraveTextureNode);
- return enm;
-}
+ 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);
-ShaderEnum MusgraveTextureNode::type_enum = musgrave_type_init();
+ 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);
-MusgraveTextureNode::MusgraveTextureNode()
-: TextureNode("musgrave_texture")
-{
- type = ustring("fBM");
+ SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_OUT_FLOAT(fac, "Fac");
- add_input("Scale", SHADER_SOCKET_FLOAT, 1.0f);
- add_input("Detail", SHADER_SOCKET_FLOAT, 2.0f);
- add_input("Vector", SHADER_SOCKET_POINT, ShaderInput::TEXTURE_GENERATED);
- add_input("Dimension", SHADER_SOCKET_FLOAT, 2.0f);
- add_input("Lacunarity", SHADER_SOCKET_FLOAT, 1.0f);
- add_input("Offset", SHADER_SOCKET_FLOAT, 0.0f);
- add_input("Gain", SHADER_SOCKET_FLOAT, 1.0f);
+ return type;
+}
- add_output("Fac", SHADER_SOCKET_FLOAT);
- add_output("Color", SHADER_SOCKET_COLOR);
+MusgraveTextureNode::MusgraveTextureNode()
+: TextureNode(node_type)
+{
}
void MusgraveTextureNode::compile(SVMCompiler& compiler)
@@ -1025,7 +1012,7 @@ void MusgraveTextureNode::compile(SVMCompiler& compiler)
compiler.add_node(NODE_TEX_MUSGRAVE,
compiler.encode_uchar4(
- type_enum[type],
+ type,
vector_offset,
compiler.stack_assign_if_linked(color_out),
compiler.stack_assign_if_linked(fac_out)),
@@ -1037,12 +1024,12 @@ void MusgraveTextureNode::compile(SVMCompiler& compiler)
compiler.encode_uchar4(
compiler.stack_assign_if_linked(gain_in),
compiler.stack_assign_if_linked(scale_in)));
- compiler.add_node(__float_as_int(dimension_in->value.x),
- __float_as_int(lacunarity_in->value.x),
- __float_as_int(detail_in->value.x),
- __float_as_int(offset_in->value.x));
- compiler.add_node(__float_as_int(gain_in->value.x),
- __float_as_int(scale_in->value.x));
+ 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);
}
@@ -1051,50 +1038,43 @@ void MusgraveTextureNode::compile(OSLCompiler& compiler)
{
tex_mapping.compile(compiler);
- compiler.parameter("Type", type);
-
+ compiler.parameter(this, "type");
compiler.add(this, "node_musgrave_texture");
}
/* Wave Texture */
-static ShaderEnum wave_type_init()
+NODE_DEFINE(WaveTextureNode)
{
- ShaderEnum enm;
+ NodeType* type = NodeType::add("wave_texture", create, NodeType::SHADER);
- enm.insert("Bands", NODE_WAVE_BANDS);
- enm.insert("Rings", NODE_WAVE_RINGS);
+ TEXTURE_MAPPING_DEFINE(WaveTextureNode);
- return enm;
-}
+ 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 ShaderEnum wave_profile_init()
-{
- ShaderEnum enm;
+ 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);
- enm.insert("Sine", NODE_WAVE_PROFILE_SIN);
- enm.insert("Saw", NODE_WAVE_PROFILE_SAW);
+ 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);
- return enm;
-}
+ SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_OUT_FLOAT(fac, "Fac");
-ShaderEnum WaveTextureNode::type_enum = wave_type_init();
-ShaderEnum WaveTextureNode::profile_enum = wave_profile_init();
+ return type;
+}
WaveTextureNode::WaveTextureNode()
-: TextureNode("wave_texture")
+: TextureNode(node_type)
{
- type = ustring("Bands");
- profile = ustring("Sine");
-
- add_input("Scale", SHADER_SOCKET_FLOAT, 1.0f);
- add_input("Distortion", SHADER_SOCKET_FLOAT, 0.0f);
- add_input("Detail", SHADER_SOCKET_FLOAT, 2.0f);
- add_input("Detail Scale", SHADER_SOCKET_FLOAT, 1.0f);
- add_input("Vector", SHADER_SOCKET_POINT, ShaderInput::TEXTURE_GENERATED);
-
- add_output("Color", SHADER_SOCKET_COLOR);
- add_output("Fac", SHADER_SOCKET_FLOAT);
}
void WaveTextureNode::compile(SVMCompiler& compiler)
@@ -1111,7 +1091,7 @@ void WaveTextureNode::compile(SVMCompiler& compiler)
compiler.add_node(NODE_TEX_WAVE,
compiler.encode_uchar4(
- type_enum[type],
+ type,
compiler.stack_assign_if_linked(color_out),
compiler.stack_assign_if_linked(fac_out),
compiler.stack_assign_if_linked(dscale_in)),
@@ -1120,13 +1100,13 @@ void WaveTextureNode::compile(SVMCompiler& compiler)
compiler.stack_assign_if_linked(scale_in),
compiler.stack_assign_if_linked(detail_in),
compiler.stack_assign_if_linked(distortion_in)),
- profile_enum[profile]);
+ profile);
compiler.add_node(
- __float_as_int(scale_in->value.x),
- __float_as_int(detail_in->value.x),
- __float_as_int(distortion_in->value.x),
- __float_as_int(dscale_in->value.x));
+ __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);
}
@@ -1135,25 +1115,35 @@ void WaveTextureNode::compile(OSLCompiler& compiler)
{
tex_mapping.compile(compiler);
- compiler.parameter("Type", type);
- compiler.parameter("Profile", profile);
+ compiler.parameter(this, "type");
+ compiler.parameter(this, "profile");
compiler.add(this, "node_wave_texture");
}
/* Magic Texture */
-MagicTextureNode::MagicTextureNode()
-: TextureNode("magic_texture")
+NODE_DEFINE(MagicTextureNode)
{
- depth = 2;
+ NodeType* type = NodeType::add("magic_texture", create, NodeType::SHADER);
+
+ TEXTURE_MAPPING_DEFINE(MagicTextureNode);
+
+ SOCKET_INT(depth, "Depth", 2);
- add_input("Vector", SHADER_SOCKET_POINT, ShaderInput::TEXTURE_GENERATED);
- add_input("Scale", SHADER_SOCKET_FLOAT, 5.0f);
- add_input("Distortion", SHADER_SOCKET_FLOAT, 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);
- add_output("Color", SHADER_SOCKET_COLOR);
- add_output("Fac", SHADER_SOCKET_FLOAT);
+ SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_OUT_FLOAT(fac, "Fac");
+
+ return type;
+}
+
+MagicTextureNode::MagicTextureNode()
+: TextureNode(node_type)
+{
}
void MagicTextureNode::compile(SVMCompiler& compiler)
@@ -1176,8 +1166,8 @@ void MagicTextureNode::compile(SVMCompiler& compiler)
compiler.stack_assign_if_linked(scale_in),
compiler.stack_assign_if_linked(distortion_in)));
compiler.add_node(
- __float_as_int(scale_in->value.x),
- __float_as_int(distortion_in->value.x));
+ __float_as_int(scale),
+ __float_as_int(distortion));
tex_mapping.compile_end(compiler, vector_in, vector_offset);
}
@@ -1186,22 +1176,32 @@ void MagicTextureNode::compile(OSLCompiler& compiler)
{
tex_mapping.compile(compiler);
- compiler.parameter("Depth", depth);
+ compiler.parameter(this, "depth");
compiler.add(this, "node_magic_texture");
}
/* Checker Texture */
-CheckerTextureNode::CheckerTextureNode()
-: TextureNode("checker_texture")
+NODE_DEFINE(CheckerTextureNode)
{
- add_input("Vector", SHADER_SOCKET_POINT, ShaderInput::TEXTURE_GENERATED);
- add_input("Color1", SHADER_SOCKET_COLOR);
- add_input("Color2", SHADER_SOCKET_COLOR);
- add_input("Scale", SHADER_SOCKET_FLOAT, 1.0f);
+ NodeType* type = NodeType::add("checker_texture", create, NodeType::SHADER);
- add_output("Color", SHADER_SOCKET_COLOR);
- add_output("Fac", SHADER_SOCKET_FLOAT);
+ 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_OUT_COLOR(color, "Color");
+ SOCKET_OUT_FLOAT(fac, "Fac");
+
+ return type;
+}
+
+CheckerTextureNode::CheckerTextureNode()
+: TextureNode(node_type)
+{
}
void CheckerTextureNode::compile(SVMCompiler& compiler)
@@ -1225,7 +1225,7 @@ void CheckerTextureNode::compile(SVMCompiler& compiler)
compiler.encode_uchar4(
compiler.stack_assign_if_linked(color_out),
compiler.stack_assign_if_linked(fac_out)),
- __float_as_int(scale_in->value.x));
+ __float_as_int(scale));
tex_mapping.compile_end(compiler, vector_in, vector_offset);
}
@@ -1239,26 +1239,37 @@ void CheckerTextureNode::compile(OSLCompiler& compiler)
/* Brick Texture */
-BrickTextureNode::BrickTextureNode()
-: TextureNode("brick_texture")
+NODE_DEFINE(BrickTextureNode)
{
- offset = 0.5f;
- offset_frequency = 2;
- squash = 1.0f;
- squash_frequency = 2;
-
- add_input("Vector", SHADER_SOCKET_POINT, ShaderInput::TEXTURE_GENERATED);
- add_input("Color1", SHADER_SOCKET_COLOR);
- add_input("Color2", SHADER_SOCKET_COLOR);
- add_input("Mortar", SHADER_SOCKET_COLOR);
- add_input("Scale", SHADER_SOCKET_FLOAT, 5.0f);
- add_input("Mortar Size", SHADER_SOCKET_FLOAT, 0.02f);
- add_input("Bias", SHADER_SOCKET_FLOAT, 0.0f);
- add_input("Brick Width", SHADER_SOCKET_FLOAT, 0.5f);
- add_input("Row Height", SHADER_SOCKET_FLOAT, 0.25f);
+ NodeType* type = NodeType::add("brick_texture", create, NodeType::SHADER);
+
+ 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_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(bias, "Bias", 0.0f);
+ SOCKET_IN_FLOAT(brick_width, "Brick Width", 0.5f);
+ SOCKET_IN_FLOAT(row_height, "Row Height", 0.25f);
- add_output("Color", SHADER_SOCKET_COLOR);
- add_output("Fac", SHADER_SOCKET_FLOAT);
+ SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_OUT_FLOAT(fac, "Fac");
+
+ return type;
+}
+
+BrickTextureNode::BrickTextureNode()
+: TextureNode(node_type)
+{
}
void BrickTextureNode::compile(SVMCompiler& compiler)
@@ -1295,12 +1306,12 @@ void BrickTextureNode::compile(SVMCompiler& compiler)
compiler.stack_assign_if_linked(fac_out)));
compiler.add_node(compiler.encode_uchar4(offset_frequency, squash_frequency),
- __float_as_int(scale_in->value.x),
- __float_as_int(mortar_size_in->value.x),
- __float_as_int(bias_in->value.x));
+ __float_as_int(scale),
+ __float_as_int(mortar_size),
+ __float_as_int(bias));
- compiler.add_node(__float_as_int(brick_width_in->value.x),
- __float_as_int(row_height_in->value.x),
+ compiler.add_node(__float_as_int(brick_width),
+ __float_as_int(row_height),
__float_as_int(offset),
__float_as_int(squash));
@@ -1311,48 +1322,55 @@ void BrickTextureNode::compile(OSLCompiler& compiler)
{
tex_mapping.compile(compiler);
- compiler.parameter("Offset", offset);
- compiler.parameter("OffsetFrequency", offset_frequency);
- compiler.parameter("Squash", squash);
- compiler.parameter("SquashFrequency", squash_frequency);
+ 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 */
-static ShaderEnum point_density_space_init()
+NODE_DEFINE(PointDensityTextureNode)
{
- ShaderEnum enm;
+ NodeType* type = NodeType::add("point_density_texture", create, NodeType::SHADER);
- enm.insert("Object", NODE_TEX_VOXEL_SPACE_OBJECT);
- enm.insert("World", NODE_TEX_VOXEL_SPACE_WORLD);
+ SOCKET_STRING(filename, "Filename", ustring(""));
- return enm;
-}
+ 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);
-ShaderEnum PointDensityTextureNode::space_enum = point_density_space_init();
+ 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_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");
+
+ return type;
+}
PointDensityTextureNode::PointDensityTextureNode()
-: ShaderNode("point_density")
+: ShaderNode(node_type)
{
image_manager = NULL;
slot = -1;
- filename = "";
- space = ustring("Object");
builtin_data = NULL;
- interpolation = INTERPOLATION_LINEAR;
-
- tfm = transform_identity();
-
- add_input("Vector", SHADER_SOCKET_POINT, ShaderInput::POSITION);
- add_output("Density", SHADER_SOCKET_FLOAT);
- add_output("Color", SHADER_SOCKET_COLOR);
}
PointDensityTextureNode::~PointDensityTextureNode()
{
if(image_manager) {
- image_manager->remove_image(filename,
+ image_manager->remove_image(filename.string(),
builtin_data,
interpolation,
EXTENSION_CLIP);
@@ -1390,7 +1408,7 @@ void PointDensityTextureNode::compile(SVMCompiler& compiler)
if(use_density || use_color) {
if(slot == -1) {
bool is_float, is_linear;
- slot = image_manager->add_image(filename, builtin_data,
+ slot = image_manager->add_image(filename.string(), builtin_data,
false, 0,
is_float, is_linear,
interpolation,
@@ -1405,8 +1423,8 @@ void PointDensityTextureNode::compile(SVMCompiler& compiler)
compiler.encode_uchar4(compiler.stack_assign(vector_in),
compiler.stack_assign_if_linked(density_out),
compiler.stack_assign_if_linked(color_out),
- space_enum[space]));
- if(space == "World") {
+ space));
+ if(space == NODE_TEX_VOXEL_SPACE_WORLD) {
compiler.add_node(tfm.x);
compiler.add_node(tfm.y);
compiler.add_node(tfm.z);
@@ -1442,7 +1460,7 @@ void PointDensityTextureNode::compile(OSLCompiler& compiler)
if(use_density || use_color) {
if(slot == -1) {
bool is_float, is_linear;
- slot = image_manager->add_image(filename, builtin_data,
+ slot = image_manager->add_image(filename.string(), builtin_data,
false, 0,
is_float, is_linear,
interpolation,
@@ -1453,37 +1471,34 @@ void PointDensityTextureNode::compile(OSLCompiler& compiler)
if(slot != -1) {
compiler.parameter("filename", string_printf("@%d", slot).c_str());
}
- if(space == "World") {
+ if(space == NODE_TEX_VOXEL_SPACE_WORLD) {
compiler.parameter("mapping", transform_transpose(tfm));
compiler.parameter("use_mapping", 1);
}
- switch(interpolation) {
- case INTERPOLATION_CLOSEST:
- compiler.parameter("interpolation", "closest");
- break;
- case INTERPOLATION_CUBIC:
- compiler.parameter("interpolation", "cubic");
- break;
- case INTERPOLATION_LINEAR:
- default:
- compiler.parameter("interpolation", "linear");
- break;
- }
-
+ compiler.parameter(this, "interpolation");
compiler.add(this, "node_voxel_texture");
}
}
/* Normal */
-NormalNode::NormalNode()
-: ShaderNode("normal")
+NODE_DEFINE(NormalNode)
{
- direction = make_float3(0.0f, 0.0f, 1.0f);
+ NodeType* type = NodeType::add("normal", create, NodeType::SHADER);
+
+ 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));
- add_input("Normal", SHADER_SOCKET_NORMAL);
- add_output("Normal", SHADER_SOCKET_NORMAL);
- add_output("Dot", SHADER_SOCKET_FLOAT);
+ SOCKET_OUT_NORMAL(normal, "Normal");
+ SOCKET_OUT_FLOAT(dot, "Dot");
+
+ return type;
+}
+
+NormalNode::NormalNode()
+: ShaderNode(node_type)
+{
}
void NormalNode::compile(SVMCompiler& compiler)
@@ -1504,17 +1519,27 @@ void NormalNode::compile(SVMCompiler& compiler)
void NormalNode::compile(OSLCompiler& compiler)
{
- compiler.parameter_normal("Direction", direction);
+ compiler.parameter(this, "direction");
compiler.add(this, "node_normal");
}
/* Mapping */
+NODE_DEFINE(MappingNode)
+{
+ NodeType* type = NodeType::add("mapping", create, NodeType::SHADER);
+
+ TEXTURE_MAPPING_DEFINE(MappingNode);
+
+ SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_OUT_POINT(vector, "Vector");
+
+ return type;
+}
+
MappingNode::MappingNode()
-: ShaderNode("mapping")
+: ShaderNode(node_type)
{
- add_input("Vector", SHADER_SOCKET_POINT);
- add_output("Vector", SHADER_SOCKET_POINT);
}
void MappingNode::compile(SVMCompiler& compiler)
@@ -1536,146 +1561,170 @@ void MappingNode::compile(OSLCompiler& compiler)
compiler.add(this, "node_mapping");
}
+/* RGBToBW */
+
+NODE_DEFINE(RGBToBWNode)
+{
+ 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");
+
+ return type;
+}
+
+RGBToBWNode::RGBToBWNode()
+: ShaderNode(node_type)
+{
+}
+
+void RGBToBWNode::constant_fold(const ConstantFolder& folder)
+{
+ if(folder.all_inputs_constant()) {
+ folder.make_constant(linear_rgb_to_gray(color));
+ }
+}
+
+void RGBToBWNode::compile(SVMCompiler& compiler)
+{
+ compiler.add_node(NODE_CONVERT,
+ NODE_CONVERT_CF,
+ compiler.stack_assign(inputs[0]),
+ compiler.stack_assign(outputs[0]));
+}
+
+void RGBToBWNode::compile(OSLCompiler& compiler)
+{
+ compiler.add(this, "node_rgb_to_bw");
+}
+
/* Convert */
-ConvertNode::ConvertNode(ShaderSocketType from_, ShaderSocketType to_, bool autoconvert)
-: ShaderNode("convert")
+const NodeType* ConvertNode::node_types[ConvertNode::MAX_TYPE][ConvertNode::MAX_TYPE];
+bool ConvertNode::initialized = ConvertNode::register_types();
+
+Node* ConvertNode::create(const NodeType *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;
+}
+
+ConvertNode::ConvertNode(SocketType::Type from_, SocketType::Type to_, bool autoconvert)
+: ShaderNode(node_types[from_][to_])
{
from = from_;
to = to_;
- if(autoconvert) {
- if(from == to)
- special_type = SHADER_SPECIAL_TYPE_PROXY;
- else
- special_type = SHADER_SPECIAL_TYPE_AUTOCONVERT;
- }
-
- if(from == SHADER_SOCKET_FLOAT)
- add_input("Val", SHADER_SOCKET_FLOAT);
- else if(from == SHADER_SOCKET_INT)
- add_input("ValInt", SHADER_SOCKET_INT);
- else if(from == SHADER_SOCKET_COLOR)
- add_input("Color", SHADER_SOCKET_COLOR);
- else if(from == SHADER_SOCKET_VECTOR)
- add_input("Vector", SHADER_SOCKET_VECTOR);
- else if(from == SHADER_SOCKET_POINT)
- add_input("Point", SHADER_SOCKET_POINT);
- else if(from == SHADER_SOCKET_NORMAL)
- add_input("Normal", SHADER_SOCKET_NORMAL);
- else if(from == SHADER_SOCKET_STRING)
- add_input("String", SHADER_SOCKET_STRING);
- else if(from == SHADER_SOCKET_CLOSURE)
- add_input("Closure", SHADER_SOCKET_CLOSURE);
- else
- assert(0);
-
- if(to == SHADER_SOCKET_FLOAT)
- add_output("Val", SHADER_SOCKET_FLOAT);
- else if(to == SHADER_SOCKET_INT)
- add_output("ValInt", SHADER_SOCKET_INT);
- else if(to == SHADER_SOCKET_COLOR)
- add_output("Color", SHADER_SOCKET_COLOR);
- else if(to == SHADER_SOCKET_VECTOR)
- add_output("Vector", SHADER_SOCKET_VECTOR);
- else if(to == SHADER_SOCKET_POINT)
- add_output("Point", SHADER_SOCKET_POINT);
- else if(to == SHADER_SOCKET_NORMAL)
- add_output("Normal", SHADER_SOCKET_NORMAL);
- else if(to == SHADER_SOCKET_STRING)
- add_output("String", SHADER_SOCKET_STRING);
- else if(to == SHADER_SOCKET_CLOSURE)
- add_output("Closure", SHADER_SOCKET_CLOSURE);
- else
- assert(0);
+ if(from == to)
+ special_type = SHADER_SPECIAL_TYPE_PROXY;
+ else if(autoconvert)
+ special_type = SHADER_SPECIAL_TYPE_AUTOCONVERT;
}
-bool ConvertNode::constant_fold(ShaderGraph * /*graph*/,
- ShaderOutput * /*socket*/,
- float3 *optimized_value)
+void ConvertNode::constant_fold(const ConstantFolder& folder)
{
- ShaderInput *in = inputs[0];
- float3 value = in->value;
+ /* 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(in->link == NULL) {
- if(from == SHADER_SOCKET_FLOAT) {
- if(to == SHADER_SOCKET_INT)
- /* float to int */
- return false;
- else
- /* float to float3 */
- *optimized_value = make_float3(value.x, value.x, value.x);
- }
- else if(from == SHADER_SOCKET_INT) {
- if(to == SHADER_SOCKET_FLOAT)
- /* int to float */
- return false;
- else
- /* int to vector/point/normal */
- return false;
- }
- else if(to == SHADER_SOCKET_FLOAT) {
- if(from == SHADER_SOCKET_COLOR)
- /* color to float */
- optimized_value->x = linear_rgb_to_gray(value);
- else
- /* vector/point/normal to float */
- optimized_value->x = average(value);
- }
- else if(to == SHADER_SOCKET_INT) {
- if(from == SHADER_SOCKET_COLOR)
- /* color to int */
- return false;
- else
- /* vector/point/normal to int */
- return false;
+ 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 {
- *optimized_value = value;
+ else if(SocketType::is_float3(from)) {
+ if(to == SocketType::FLOAT) {
+ if(from == SocketType::COLOR) {
+ /* color to float */
+ folder.make_constant(linear_rgb_to_gray(value_color));
+ }
+ else {
+ /* vector/point/normal to float */
+ folder.make_constant(average(value_vector));
+ }
+ }
+ else if(SocketType::is_float3(to)) {
+ folder.make_constant(value_color);
+ }
}
-
- return true;
}
-
- return false;
}
void ConvertNode::compile(SVMCompiler& compiler)
{
- /* constant folding should eliminate proxy nodes */
- assert(from != to);
+ /* 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 == SHADER_SOCKET_FLOAT) {
- if(to == SHADER_SOCKET_INT)
+ 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 == SHADER_SOCKET_INT) {
- if(to == SHADER_SOCKET_FLOAT)
+ 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 == SHADER_SOCKET_FLOAT) {
- if(from == SHADER_SOCKET_COLOR)
+ 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 == SHADER_SOCKET_INT) {
- if(from == SHADER_SOCKET_COLOR)
+ 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
@@ -1691,27 +1740,27 @@ void ConvertNode::compile(SVMCompiler& compiler)
else {
/* set 0,0,0 value */
compiler.add_node(NODE_VALUE_V, compiler.stack_assign(out));
- compiler.add_node(NODE_VALUE_V, in->value);
+ compiler.add_node(NODE_VALUE_V, value_color);
}
}
}
void ConvertNode::compile(OSLCompiler& compiler)
{
- /* constant folding should eliminate proxy nodes */
- assert(from != to);
+ /* proxy nodes should have been removed at this point */
+ assert(special_type != SHADER_SPECIAL_TYPE_PROXY);
- if(from == SHADER_SOCKET_FLOAT)
+ if(from == SocketType::FLOAT)
compiler.add(this, "node_convert_from_float");
- else if(from == SHADER_SOCKET_INT)
+ else if(from == SocketType::INT)
compiler.add(this, "node_convert_from_int");
- else if(from == SHADER_SOCKET_COLOR)
+ else if(from == SocketType::COLOR)
compiler.add(this, "node_convert_from_color");
- else if(from == SHADER_SOCKET_VECTOR)
+ else if(from == SocketType::VECTOR)
compiler.add(this, "node_convert_from_vector");
- else if(from == SHADER_SOCKET_POINT)
+ else if(from == SocketType::POINT)
compiler.add(this, "node_convert_from_point");
- else if(from == SHADER_SOCKET_NORMAL)
+ else if(from == SocketType::NORMAL)
compiler.add(this, "node_convert_from_normal");
else
assert(0);
@@ -1719,23 +1768,10 @@ void ConvertNode::compile(OSLCompiler& compiler)
/* BSDF Closure */
-BsdfNode::BsdfNode(bool scattering_)
-: ShaderNode("bsdf"), scattering(scattering_)
+BsdfNode::BsdfNode(const NodeType *node_type)
+: ShaderNode(node_type)
{
special_type = SHADER_SPECIAL_TYPE_CLOSURE;
-
- add_input("Color", SHADER_SOCKET_COLOR, make_float3(0.8f, 0.8f, 0.8f));
- add_input("Normal", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL);
- add_input("SurfaceMixWeight", SHADER_SOCKET_FLOAT, 0.0f, ShaderInput::USE_SVM);
-
- if(scattering) {
- closure = CLOSURE_BSSRDF_CUBIC_ID;
- add_output("BSSRDF", SHADER_SOCKET_CLOSURE);
- }
- else {
- closure = CLOSURE_BSDF_DIFFUSE_ID;
- add_output("BSDF", SHADER_SOCKET_CLOSURE);
- }
}
void BsdfNode::compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *param2, ShaderInput *param3, ShaderInput *param4)
@@ -1747,9 +1783,9 @@ void BsdfNode::compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *
if(color_in->link)
compiler.add_node(NODE_CLOSURE_WEIGHT, compiler.stack_assign(color_in));
else
- compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color_in->value);
+ compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color);
- int normal_offset = compiler.stack_assign_if_linked(normal_in);
+ 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;
@@ -1759,8 +1795,8 @@ void BsdfNode::compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *
(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)? param1->value.x: 0.0f),
- __float_as_int((param2)? param2->value.x: 0.0f));
+ __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);
}
@@ -1777,29 +1813,36 @@ void BsdfNode::compile(OSLCompiler& /*compiler*/)
/* Anisotropic BSDF Closure */
-static ShaderEnum aniso_distribution_init()
+NODE_DEFINE(AnisotropicBsdfNode)
{
- ShaderEnum enm;
+ NodeType* type = NodeType::add("anisotropic_bsdf", create, NodeType::SHADER);
- enm.insert("Beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID);
- enm.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID);
- enm.insert("Ashikhmin-Shirley", CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID);
+ 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);
- return enm;
-}
+ 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_FLOAT(roughness, "Roughness", 0.2f);
+ SOCKET_IN_FLOAT(anisotropy, "Anisotropy", 0.5f);
+ SOCKET_IN_FLOAT(rotation, "Rotation", 0.0f);
-ShaderEnum AnisotropicBsdfNode::distribution_enum = aniso_distribution_init();
+ SOCKET_OUT_CLOSURE(BSDF, "BSDF");
+
+ return type;
+}
AnisotropicBsdfNode::AnisotropicBsdfNode()
+: BsdfNode(node_type)
{
closure = CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID;
- distribution = ustring("GGX");
-
- add_input("Tangent", SHADER_SOCKET_VECTOR, ShaderInput::TANGENT);
-
- add_input("Roughness", SHADER_SOCKET_FLOAT, 0.2f);
- add_input("Anisotropy", SHADER_SOCKET_FLOAT, 0.5f);
- add_input("Rotation", SHADER_SOCKET_FLOAT, 0.0f);
}
void AnisotropicBsdfNode::attributes(Shader *shader, AttributeRequestSet *attributes)
@@ -1816,45 +1859,54 @@ void AnisotropicBsdfNode::attributes(Shader *shader, AttributeRequestSet *attrib
void AnisotropicBsdfNode::compile(SVMCompiler& compiler)
{
- closure = (ClosureType)distribution_enum[distribution];
+ closure = distribution;
- 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)
{
- compiler.parameter("distribution", distribution);
+ compiler.parameter(this, "distribution");
compiler.add(this, "node_anisotropic_bsdf");
}
/* Glossy BSDF Closure */
-static ShaderEnum glossy_distribution_init()
+NODE_DEFINE(GlossyBsdfNode)
{
- ShaderEnum enm;
+ NodeType* type = NodeType::add("glossy_bsdf", create, NodeType::SHADER);
- enm.insert("Sharp", CLOSURE_BSDF_REFLECTION_ID);
- enm.insert("Beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_ID);
- enm.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_ID);
- enm.insert("Ashikhmin-Shirley", CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID);
+ 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);
- return enm;
-}
+ 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.2f);
-ShaderEnum GlossyBsdfNode::distribution_enum = glossy_distribution_init();
+ SOCKET_OUT_CLOSURE(BSDF, "BSDF");
+
+ return type;
+}
GlossyBsdfNode::GlossyBsdfNode()
+: BsdfNode(node_type)
{
closure = CLOSURE_BSDF_MICROFACET_GGX_ID;
- distribution = ustring("GGX");
- distribution_orig = ustring("");
-
- add_input("Roughness", SHADER_SOCKET_FLOAT, 0.2f);
+ distribution_orig = NBUILTIN_CLOSURES;
}
void GlossyBsdfNode::simplify_settings(Scene *scene)
{
- if(distribution_orig == "") {
+ if(distribution_orig == NBUILTIN_CLOSURES) {
distribution_orig = distribution;
}
Integrator *integrator = scene->integrator;
@@ -1863,67 +1915,75 @@ void GlossyBsdfNode::simplify_settings(Scene *scene)
* Note: Keep the epsilon in sync with kernel!
*/
ShaderInput *roughness_input = input("Roughness");
- if(!roughness_input->link && roughness_input->value.x <= 1e-4f) {
- distribution = ustring("Sharp");
+ if(!roughness_input->link && roughness <= 1e-4f) {
+ distribution = CLOSURE_BSDF_REFLECTION_ID;
}
}
else {
/* Rollback to original distribution when filter glossy is used. */
distribution = distribution_orig;
}
- closure = (ClosureType)distribution_enum[distribution];
+ closure = distribution;
}
bool GlossyBsdfNode::has_integrator_dependency()
{
ShaderInput *roughness_input = input("Roughness");
- return !roughness_input->link && roughness_input->value.x <= 1e-4f;
+ return !roughness_input->link && roughness <= 1e-4f;
}
void GlossyBsdfNode::compile(SVMCompiler& compiler)
{
- closure = (ClosureType)distribution_enum[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);
}
void GlossyBsdfNode::compile(OSLCompiler& compiler)
{
- compiler.parameter("distribution", distribution);
+ compiler.parameter(this, "distribution");
compiler.add(this, "node_glossy_bsdf");
}
/* Glass BSDF Closure */
-static ShaderEnum glass_distribution_init()
+NODE_DEFINE(GlassBsdfNode)
{
- ShaderEnum enm;
+ NodeType* type = NodeType::add("glass_bsdf", create, NodeType::SHADER);
- enm.insert("Sharp", CLOSURE_BSDF_SHARP_GLASS_ID);
- enm.insert("Beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID);
- enm.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID);
+ 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);
- return enm;
-}
+ 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");
-ShaderEnum GlassBsdfNode::distribution_enum = glass_distribution_init();
+ return type;
+}
GlassBsdfNode::GlassBsdfNode()
+: BsdfNode(node_type)
{
closure = CLOSURE_BSDF_SHARP_GLASS_ID;
- distribution = ustring("Sharp");
- distribution_orig = ustring("");
-
- add_input("Roughness", SHADER_SOCKET_FLOAT, 0.0f);
- add_input("IOR", SHADER_SOCKET_FLOAT, 0.3f);
+ distribution_orig = NBUILTIN_CLOSURES;
}
void GlassBsdfNode::simplify_settings(Scene *scene)
{
- if(distribution_orig == "") {
+ if(distribution_orig == NBUILTIN_CLOSURES) {
distribution_orig = distribution;
}
Integrator *integrator = scene->integrator;
@@ -1932,67 +1992,75 @@ void GlassBsdfNode::simplify_settings(Scene *scene)
* Note: Keep the epsilon in sync with kernel!
*/
ShaderInput *roughness_input = input("Roughness");
- if(!roughness_input->link && roughness_input->value.x <= 1e-4f) {
- distribution = ustring("Sharp");
+ if(!roughness_input->link && roughness <= 1e-4f) {
+ distribution = CLOSURE_BSDF_SHARP_GLASS_ID;
}
}
else {
/* Rollback to original distribution when filter glossy is used. */
distribution = distribution_orig;
}
- closure = (ClosureType)distribution_enum[distribution];
+ closure = distribution;
}
bool GlassBsdfNode::has_integrator_dependency()
{
ShaderInput *roughness_input = input("Roughness");
- return !roughness_input->link && roughness_input->value.x <= 1e-4f;
+ return !roughness_input->link && roughness <= 1e-4f;
}
void GlassBsdfNode::compile(SVMCompiler& compiler)
{
- closure = (ClosureType)distribution_enum[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"));
}
void GlassBsdfNode::compile(OSLCompiler& compiler)
{
- compiler.parameter("distribution", distribution);
+ compiler.parameter(this, "distribution");
compiler.add(this, "node_glass_bsdf");
}
/* Refraction BSDF Closure */
-static ShaderEnum refraction_distribution_init()
+NODE_DEFINE(RefractionBsdfNode)
{
- ShaderEnum enm;
+ NodeType* type = NodeType::add("refraction_bsdf", create, NodeType::SHADER);
- enm.insert("Sharp", CLOSURE_BSDF_REFRACTION_ID);
- enm.insert("Beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID);
- enm.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID);
+ 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);
- return enm;
-}
+ 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);
-ShaderEnum RefractionBsdfNode::distribution_enum = refraction_distribution_init();
+ SOCKET_OUT_CLOSURE(BSDF, "BSDF");
+
+ return type;
+}
RefractionBsdfNode::RefractionBsdfNode()
+: BsdfNode(node_type)
{
closure = CLOSURE_BSDF_REFRACTION_ID;
- distribution = ustring("Sharp");
- distribution_orig = ustring("");
-
- add_input("Roughness", SHADER_SOCKET_FLOAT, 0.0f);
- add_input("IOR", SHADER_SOCKET_FLOAT, 0.3f);
+ distribution_orig = NBUILTIN_CLOSURES;
}
void RefractionBsdfNode::simplify_settings(Scene *scene)
{
- if(distribution_orig == "") {
+ if(distribution_orig == NBUILTIN_CLOSURES) {
distribution_orig = distribution;
}
Integrator *integrator = scene->integrator;
@@ -2001,26 +2069,26 @@ void RefractionBsdfNode::simplify_settings(Scene *scene)
* Note: Keep the epsilon in sync with kernel!
*/
ShaderInput *roughness_input = input("Roughness");
- if(!roughness_input->link && roughness_input->value.x <= 1e-4f) {
- distribution = ustring("Sharp");
+ if(!roughness_input->link && roughness <= 1e-4f) {
+ distribution = CLOSURE_BSDF_REFRACTION_ID;
}
}
else {
/* Rollback to original distribution when filter glossy is used. */
distribution = distribution_orig;
}
- closure = (ClosureType)distribution_enum[distribution];
+ closure = distribution;
}
bool RefractionBsdfNode::has_integrator_dependency()
{
ShaderInput *roughness_input = input("Roughness");
- return !roughness_input->link && roughness_input->value.x <= 1e-4f;
+ return !roughness_input->link && roughness <= 1e-4f;
}
void RefractionBsdfNode::compile(SVMCompiler& compiler)
{
- closure = (ClosureType)distribution_enum[distribution];
+ closure = distribution;
if(closure == CLOSURE_BSDF_REFRACTION_ID)
BsdfNode::compile(compiler, NULL, input("IOR"));
@@ -2030,53 +2098,71 @@ void RefractionBsdfNode::compile(SVMCompiler& compiler)
void RefractionBsdfNode::compile(OSLCompiler& compiler)
{
- compiler.parameter("distribution", distribution);
+ compiler.parameter(this, "distribution");
compiler.add(this, "node_refraction_bsdf");
}
/* Toon BSDF Closure */
-static ShaderEnum toon_component_init()
+NODE_DEFINE(ToonBsdfNode)
{
- ShaderEnum enm;
+ NodeType* type = NodeType::add("toon_bsdf", create, NodeType::SHADER);
- enm.insert("Diffuse", CLOSURE_BSDF_DIFFUSE_TOON_ID);
- enm.insert("Glossy", CLOSURE_BSDF_GLOSSY_TOON_ID);
+ 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);
- return enm;
-}
+ 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");
-ShaderEnum ToonBsdfNode::component_enum = toon_component_init();
+ return type;
+}
ToonBsdfNode::ToonBsdfNode()
+: BsdfNode(node_type)
{
closure = CLOSURE_BSDF_DIFFUSE_TOON_ID;
- component = ustring("Diffuse");
-
- add_input("Size", SHADER_SOCKET_FLOAT, 0.5f);
- add_input("Smooth", SHADER_SOCKET_FLOAT, 0.0f);
}
void ToonBsdfNode::compile(SVMCompiler& compiler)
{
- closure = (ClosureType)component_enum[component];
+ closure = component;
BsdfNode::compile(compiler, input("Size"), input("Smooth"));
}
void ToonBsdfNode::compile(OSLCompiler& compiler)
{
- compiler.parameter("component", component);
+ 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);
+
+ 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");
+
+ return type;
+}
+
VelvetBsdfNode::VelvetBsdfNode()
+: BsdfNode(node_type)
{
closure = CLOSURE_BSDF_ASHIKHMIN_VELVET_ID;
-
- add_input("Sigma", SHADER_SOCKET_FLOAT, 1.0f);
}
void VelvetBsdfNode::compile(SVMCompiler& compiler)
@@ -2091,10 +2177,24 @@ void VelvetBsdfNode::compile(OSLCompiler& compiler)
/* Diffuse BSDF Closure */
+NODE_DEFINE(DiffuseBsdfNode)
+{
+ 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_OUT_CLOSURE(BSDF, "BSDF");
+
+ return type;
+}
+
DiffuseBsdfNode::DiffuseBsdfNode()
+: BsdfNode(node_type)
{
closure = CLOSURE_BSDF_DIFFUSE_ID;
- add_input("Roughness", SHADER_SOCKET_FLOAT, 0.0f);
}
void DiffuseBsdfNode::compile(SVMCompiler& compiler)
@@ -2108,33 +2208,40 @@ void DiffuseBsdfNode::compile(OSLCompiler& compiler)
}
/* Disney BSDF Closure */
+NODE_DEFINE(DisneyBsdfNode)
+{
+ NodeType* type = NodeType::add("disney_bsdf", create, NodeType::SHADER);
+
+ SOCKET_IN_COLOR(base_color, "BaseColor", make_float3(0.8f, 0.8f, 0.8f));
+ SOCKET_IN_COLOR(subsurface_color, "SubsurfaceColor", make_float3(0.8f, 0.8f, 0.8f));
+ SOCKET_IN_FLOAT(metallic, "Metallic", 0.0f);
+ SOCKET_IN_FLOAT(subsurface, "Subsurface", 0.0f);
+ SOCKET_IN_FLOAT(specular, "Specular", 0.0f);
+ SOCKET_IN_FLOAT(roughness, "Roughness", 0.0f);
+ SOCKET_IN_FLOAT(specularTint, "SpecularTint", 0.0f);
+ SOCKET_IN_FLOAT(anisotropic, "Anisotropic", 0.0f);
+ SOCKET_IN_FLOAT(sheen, "Sheen", 0.0f);
+ SOCKET_IN_FLOAT(sheenTint, "SheenTint", 0.0f);
+ SOCKET_IN_FLOAT(clearcoat, "Clearcoat", 0.0f);
+ SOCKET_IN_FLOAT(clearcoatGloss, "ClearcoatGloss", 0.0f);
+ SOCKET_IN_FLOAT(ior, "IOR", 0.0f);
+ SOCKET_IN_FLOAT(transparency, "Transparency", 0.0f);
+ SOCKET_IN_FLOAT(refractionRoughness, "RefractionRoughness", 0.0f);
+ SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
+ SOCKET_IN_NORMAL(clearcoatNormal, "ClearcoatNormal", 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;
+}
+
DisneyBsdfNode::DisneyBsdfNode()
- : ShaderNode("bsdf")
+ : ShaderNode(node_type)
{
special_type = SHADER_SPECIAL_TYPE_CLOSURE;
closure = CLOSURE_BSDF_DISNEY_ID;
-
- add_input("BaseColor", SHADER_SOCKET_COLOR, make_float3(0.646f, 0.415f, 0.017f));
- add_input("SubsurfaceColor", SHADER_SOCKET_COLOR, make_float3(0.646f, 0.415f, 0.017f));
- add_input("Metallic", SHADER_SOCKET_FLOAT, 0.0f);
- add_input("Subsurface", SHADER_SOCKET_FLOAT, 0.0f);
- add_input("Specular", SHADER_SOCKET_FLOAT, 0.5f);
- add_input("Roughness", SHADER_SOCKET_FLOAT, 0.5f);
- add_input("SpecularTint", SHADER_SOCKET_FLOAT, 0.0f);
- add_input("Anisotropic", SHADER_SOCKET_FLOAT, 0.0f);
- add_input("Sheen", SHADER_SOCKET_FLOAT, 0.0f);
- add_input("SheenTint", SHADER_SOCKET_FLOAT, 0.5f);
- add_input("Clearcoat", SHADER_SOCKET_FLOAT, 0.0f);
- add_input("ClearcoatGloss", SHADER_SOCKET_FLOAT, 1.0f);
- add_input("IOR", SHADER_SOCKET_FLOAT, 1.45f);
- add_input("Transparency", SHADER_SOCKET_FLOAT, 0.0f);
- add_input("RefractionRoughness", SHADER_SOCKET_FLOAT, 0.0f);
- add_input("Normal", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL);
- add_input("ClearcoatNormal", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL);
- add_input("Tangent", SHADER_SOCKET_VECTOR, ShaderInput::TANGENT);
- add_input("SurfaceMixWeight", SHADER_SOCKET_FLOAT, 0.0f, ShaderInput::USE_SVM);
-
- add_output("BSDF", SHADER_SOCKET_CLOSURE);
}
void DisneyBsdfNode::compile(SVMCompiler& compiler, ShaderInput *metallic, ShaderInput *subsurface,
@@ -2176,8 +2283,8 @@ void DisneyBsdfNode::compile(SVMCompiler& compiler, ShaderInput *metallic, Shade
compiler.stack_assign(metallic),
compiler.stack_assign(subsurface),
compiler.closure_mix_weight_offset()),
- __float_as_int(metallic->value.x),
- __float_as_int(subsurface->value.x));
+ __float_as_int((metallic) ? get_float(metallic->socket_type) : 0.0f),
+ __float_as_int((subsurface) ? get_float(subsurface->socket_type) : 0.0f));
compiler.add_node(normal_offset, tangent_offset,
compiler.encode_uchar4(specular_offset, roughness_offset, specularTint_offset, anisotropic_offset),
@@ -2186,13 +2293,17 @@ void DisneyBsdfNode::compile(SVMCompiler& compiler, ShaderInput *metallic, Shade
compiler.add_node(compiler.encode_uchar4(ior_offset, transparency_offset, refr_roughness_offset, SVM_STACK_INVALID),
SVM_STACK_INVALID, SVM_STACK_INVALID, 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(base_color_in->value.x), __float_as_int(base_color_in->value.y), __float_as_int(base_color_in->value.z));
+ __float_as_int(bc_default.x), __float_as_int(bc_default.y), __float_as_int(bc_default.z));
compiler.add_node(clearcoat_normal_offset, SVM_STACK_INVALID, 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(subsurface_color_in->value.x), __float_as_int(subsurface_color_in->value.y), __float_as_int(subsurface_color_in->value.z));
+ __float_as_int(ss_default.x), __float_as_int(ss_default.y), __float_as_int(ss_default.z));
}
void DisneyBsdfNode::compile(SVMCompiler& compiler)
@@ -2216,7 +2327,21 @@ bool DisneyBsdfNode::has_bssrdf_bump()
/* Translucent BSDF Closure */
+NODE_DEFINE(TranslucentBsdfNode)
+{
+ 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_OUT_CLOSURE(BSDF, "BSDF");
+
+ return type;
+}
+
TranslucentBsdfNode::TranslucentBsdfNode()
+: BsdfNode(node_type)
{
closure = CLOSURE_BSDF_TRANSLUCENT_ID;
}
@@ -2233,9 +2358,21 @@ void TranslucentBsdfNode::compile(OSLCompiler& compiler)
/* Transparent BSDF Closure */
+NODE_DEFINE(TransparentBsdfNode)
+{
+ 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_OUT_CLOSURE(BSDF, "BSDF");
+
+ return type;
+}
+
TransparentBsdfNode::TransparentBsdfNode()
+: BsdfNode(node_type)
{
- name = "transparent";
closure = CLOSURE_BSDF_TRANSPARENT_ID;
}
@@ -2251,39 +2388,45 @@ void TransparentBsdfNode::compile(OSLCompiler& compiler)
/* Subsurface Scattering Closure */
-static ShaderEnum subsurface_falloff_init()
+NODE_DEFINE(SubsurfaceScatteringNode)
{
- ShaderEnum enm;
+ NodeType* type = NodeType::add("subsurface_scattering", create, NodeType::SHADER);
- enm.insert("Cubic", CLOSURE_BSSRDF_CUBIC_ID);
- enm.insert("Gaussian", CLOSURE_BSSRDF_GAUSSIAN_ID);
- enm.insert("Burley", CLOSURE_BSSRDF_BURLEY_ID);
+ 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);
- return enm;
-}
+ 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);
+ 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");
-ShaderEnum SubsurfaceScatteringNode::falloff_enum = subsurface_falloff_init();
+ return type;
+}
SubsurfaceScatteringNode::SubsurfaceScatteringNode()
-: BsdfNode(true)
+: BsdfNode(node_type)
{
- name = "subsurface_scattering";
- closure = CLOSURE_BSSRDF_CUBIC_ID;
-
- add_input("Scale", SHADER_SOCKET_FLOAT, 0.01f);
- add_input("Radius", SHADER_SOCKET_VECTOR, make_float3(0.1f, 0.1f, 0.1f));
- add_input("Sharpness", SHADER_SOCKET_FLOAT, 0.0f);
- add_input("Texture Blur", SHADER_SOCKET_FLOAT, 1.0f);
+ closure = falloff;
}
void SubsurfaceScatteringNode::compile(SVMCompiler& compiler)
{
+ closure = falloff;
BsdfNode::compile(compiler, input("Scale"), input("Texture Blur"), input("Radius"), input("Sharpness"));
}
void SubsurfaceScatteringNode::compile(OSLCompiler& compiler)
{
- compiler.parameter("Falloff", falloff_enum[closure]);
+ closure = falloff;
+ compiler.parameter(this, "falloff");
compiler.add(this, "node_subsurface_scattering");
}
@@ -2296,14 +2439,22 @@ bool SubsurfaceScatteringNode::has_bssrdf_bump()
/* Emissive Closure */
-EmissionNode::EmissionNode()
-: ShaderNode("emission")
+NODE_DEFINE(EmissionNode)
{
- add_input("Color", SHADER_SOCKET_COLOR, make_float3(0.8f, 0.8f, 0.8f));
- add_input("Strength", SHADER_SOCKET_FLOAT, 10.0f);
- add_input("SurfaceMixWeight", SHADER_SOCKET_FLOAT, 0.0f, ShaderInput::USE_SVM);
+ NodeType* type = NodeType::add("emission", create, NodeType::SHADER);
- add_output("Emission", SHADER_SOCKET_CLOSURE);
+ 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");
+
+ return type;
+}
+
+EmissionNode::EmissionNode()
+: ShaderNode(node_type)
+{
}
void EmissionNode::compile(SVMCompiler& compiler)
@@ -2314,10 +2465,10 @@ void EmissionNode::compile(SVMCompiler& compiler)
if(color_in->link || strength_in->link) {
compiler.add_node(NODE_EMISSION_WEIGHT,
compiler.stack_assign(color_in),
- compiler.stack_assign(strength_in));
+ compiler.stack_assign(strength_in));
}
else
- compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color_in->value * strength_in->value.x);
+ compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color * strength);
compiler.add_node(NODE_CLOSURE_EMISSION, compiler.closure_mix_weight_offset());
}
@@ -2327,25 +2478,35 @@ void EmissionNode::compile(OSLCompiler& compiler)
compiler.add(this, "node_emission");
}
-bool EmissionNode::constant_fold(ShaderGraph * /*graph*/, ShaderOutput * /*socket*/, float3 * /*optimized_value*/)
+void EmissionNode::constant_fold(const ConstantFolder& folder)
{
ShaderInput *color_in = input("Color");
ShaderInput *strength_in = input("Strength");
- return ((!color_in->link && color_in->value == make_float3(0.0f, 0.0f, 0.0f)) ||
- (!strength_in->link && strength_in->value.x == 0.0f));
+ if ((!color_in->link && color == make_float3(0.0f, 0.0f, 0.0f)) ||
+ (!strength_in->link && strength == 0.0f)) {
+ folder.discard();
+ }
}
/* Background Closure */
-BackgroundNode::BackgroundNode()
-: ShaderNode("background")
+NODE_DEFINE(BackgroundNode)
{
- add_input("Color", SHADER_SOCKET_COLOR, make_float3(0.8f, 0.8f, 0.8f));
- add_input("Strength", SHADER_SOCKET_FLOAT, 1.0f);
- add_input("SurfaceMixWeight", SHADER_SOCKET_FLOAT, 0.0f, ShaderInput::USE_SVM);
+ 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_OUT_CLOSURE(background, "Background");
+
+ return type;
+}
- add_output("Background", SHADER_SOCKET_CLOSURE);
+BackgroundNode::BackgroundNode()
+: ShaderNode(node_type)
+{
}
void BackgroundNode::compile(SVMCompiler& compiler)
@@ -2359,7 +2520,7 @@ void BackgroundNode::compile(SVMCompiler& compiler)
compiler.stack_assign(strength_in));
}
else
- compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color_in->value*strength_in->value.x);
+ compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color*strength);
compiler.add_node(NODE_CLOSURE_BACKGROUND, compiler.closure_mix_weight_offset());
}
@@ -2369,24 +2530,34 @@ void BackgroundNode::compile(OSLCompiler& compiler)
compiler.add(this, "node_background");
}
-bool BackgroundNode::constant_fold(ShaderGraph * /*graph*/, ShaderOutput * /*socket*/, float3 * /*optimized_value*/)
+void BackgroundNode::constant_fold(const ConstantFolder& folder)
{
ShaderInput *color_in = input("Color");
ShaderInput *strength_in = input("Strength");
- return ((!color_in->link && color_in->value == make_float3(0.0f, 0.0f, 0.0f)) ||
- (!strength_in->link && strength_in->value.x == 0.0f));
+ if ((!color_in->link && color == make_float3(0.0f, 0.0f, 0.0f)) ||
+ (!strength_in->link && strength == 0.0f)) {
+ folder.discard();
+ }
}
/* Holdout Closure */
-HoldoutNode::HoldoutNode()
-: ShaderNode("holdout")
+NODE_DEFINE(HoldoutNode)
{
- add_input("SurfaceMixWeight", SHADER_SOCKET_FLOAT, 0.0f, ShaderInput::USE_SVM);
- add_input("VolumeMixWeight", SHADER_SOCKET_FLOAT, 0.0f, ShaderInput::USE_SVM);
+ 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);
- add_output("Holdout", SHADER_SOCKET_CLOSURE);
+ SOCKET_OUT_CLOSURE(holdout, "Holdout");
+
+ return type;
+}
+
+HoldoutNode::HoldoutNode()
+: ShaderNode(node_type)
+{
}
void HoldoutNode::compile(SVMCompiler& compiler)
@@ -2404,14 +2575,22 @@ void HoldoutNode::compile(OSLCompiler& compiler)
/* Ambient Occlusion */
-AmbientOcclusionNode::AmbientOcclusionNode()
-: ShaderNode("ambient_occlusion")
+NODE_DEFINE(AmbientOcclusionNode)
{
- add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, ShaderInput::USE_OSL);
- add_input("Color", SHADER_SOCKET_COLOR, make_float3(0.8f, 0.8f, 0.8f));
- add_input("SurfaceMixWeight", SHADER_SOCKET_FLOAT, 0.0f, ShaderInput::USE_SVM);
+ NodeType* type = NodeType::add("ambient_occlusion", create, NodeType::SHADER);
- add_output("AO", SHADER_SOCKET_CLOSURE);
+ SOCKET_IN_NORMAL(normal_osl, "NormalIn", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL | SocketType::OSL_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(AO, "AO");
+
+ return type;
+}
+
+AmbientOcclusionNode::AmbientOcclusionNode()
+: ShaderNode(node_type)
+{
}
void AmbientOcclusionNode::compile(SVMCompiler& compiler)
@@ -2421,7 +2600,7 @@ void AmbientOcclusionNode::compile(SVMCompiler& compiler)
if(color_in->link)
compiler.add_node(NODE_CLOSURE_WEIGHT, compiler.stack_assign(color_in));
else
- compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color_in->value);
+ compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color);
compiler.add_node(NODE_CLOSURE_AMBIENT_OCCLUSION, compiler.closure_mix_weight_offset());
}
@@ -2433,16 +2612,10 @@ void AmbientOcclusionNode::compile(OSLCompiler& compiler)
/* Volume Closure */
-VolumeNode::VolumeNode()
-: ShaderNode("volume")
+VolumeNode::VolumeNode(const NodeType *node_type)
+: ShaderNode(node_type)
{
closure = CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID;
-
- add_input("Color", SHADER_SOCKET_COLOR, make_float3(0.8f, 0.8f, 0.8f));
- add_input("Density", SHADER_SOCKET_FLOAT, 1.0f);
- add_input("VolumeMixWeight", SHADER_SOCKET_FLOAT, 0.0f, ShaderInput::USE_SVM);
-
- add_output("Volume", SHADER_SOCKET_CLOSURE);
}
void VolumeNode::compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *param2)
@@ -2452,15 +2625,15 @@ void VolumeNode::compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput
if(color_in->link)
compiler.add_node(NODE_CLOSURE_WEIGHT, compiler.stack_assign(color_in));
else
- compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color_in->value);
+ 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)? param1->value.x: 0.0f),
- __float_as_int((param2)? param2->value.x: 0.0f));
+ __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)
@@ -2475,7 +2648,21 @@ void VolumeNode::compile(OSLCompiler& /*compiler*/)
/* Absorption Volume Closure */
+NODE_DEFINE(AbsorptionVolumeNode)
+{
+ 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_OUT_CLOSURE(volume, "Volume");
+
+ return type;
+}
+
AbsorptionVolumeNode::AbsorptionVolumeNode()
+: VolumeNode(node_type)
{
closure = CLOSURE_VOLUME_ABSORPTION_ID;
}
@@ -2492,11 +2679,24 @@ void AbsorptionVolumeNode::compile(OSLCompiler& compiler)
/* Scatter Volume Closure */
+NODE_DEFINE(ScatterVolumeNode)
+{
+ 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_OUT_CLOSURE(volume, "Volume");
+
+ return type;
+}
+
ScatterVolumeNode::ScatterVolumeNode()
+: VolumeNode(node_type)
{
closure = CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID;
-
- add_input("Anisotropy", SHADER_SOCKET_FLOAT, 0.0f);
}
void ScatterVolumeNode::compile(SVMCompiler& compiler)
@@ -2511,59 +2711,71 @@ void ScatterVolumeNode::compile(OSLCompiler& compiler)
/* Hair BSDF Closure */
-static ShaderEnum hair_component_init()
+NODE_DEFINE(HairBsdfNode)
{
- ShaderEnum enm;
+ NodeType* type = NodeType::add("hair_bsdf", create, NodeType::SHADER);
- enm.insert("Reflection", CLOSURE_BSDF_HAIR_REFLECTION_ID);
- enm.insert("Transmission", CLOSURE_BSDF_HAIR_TRANSMISSION_ID);
+ 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);
- return enm;
-}
+ 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");
-ShaderEnum HairBsdfNode::component_enum = hair_component_init();
+ return type;
+}
HairBsdfNode::HairBsdfNode()
+: BsdfNode(node_type)
{
closure = CLOSURE_BSDF_HAIR_REFLECTION_ID;
- component = ustring("Reflection");
-
- add_input("Offset", SHADER_SOCKET_FLOAT);
- add_input("RoughnessU", SHADER_SOCKET_FLOAT);
- add_input("RoughnessV", SHADER_SOCKET_FLOAT);
- add_input("Tangent", SHADER_SOCKET_VECTOR);
}
void HairBsdfNode::compile(SVMCompiler& compiler)
{
- closure = (ClosureType)component_enum[component];
+ closure = component;
BsdfNode::compile(compiler, input("RoughnessU"), input("RoughnessV"), input("Offset"));
}
void HairBsdfNode::compile(OSLCompiler& compiler)
{
- compiler.parameter("component", component);
-
+ compiler.parameter(this, "component");
compiler.add(this, "node_hair_bsdf");
}
/* Geometry */
+NODE_DEFINE(GeometryNode)
+{
+ 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_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;
+}
+
GeometryNode::GeometryNode()
-: ShaderNode("geometry")
+: ShaderNode(node_type)
{
special_type = SHADER_SPECIAL_TYPE_GEOMETRY;
-
- add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, ShaderInput::USE_OSL);
- add_output("Position", SHADER_SOCKET_POINT);
- add_output("Normal", SHADER_SOCKET_NORMAL);
- add_output("Tangent", SHADER_SOCKET_NORMAL);
- add_output("True Normal", SHADER_SOCKET_NORMAL);
- add_output("Incoming", SHADER_SOCKET_VECTOR);
- add_output("Parametric", SHADER_SOCKET_POINT);
- add_output("Backfacing", SHADER_SOCKET_FLOAT);
- add_output("Pointiness", SHADER_SOCKET_FLOAT);
}
void GeometryNode::attributes(Shader *shader, AttributeRequestSet *attributes)
@@ -2658,21 +2870,30 @@ void GeometryNode::compile(OSLCompiler& compiler)
/* TextureCoordinate */
-TextureCoordinateNode::TextureCoordinateNode()
-: ShaderNode("texture_coordinate")
+NODE_DEFINE(TextureCoordinateNode)
{
- add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, ShaderInput::USE_OSL);
- add_output("Generated", SHADER_SOCKET_POINT);
- add_output("Normal", SHADER_SOCKET_NORMAL);
- add_output("UV", SHADER_SOCKET_POINT);
- add_output("Object", SHADER_SOCKET_POINT);
- add_output("Camera", SHADER_SOCKET_POINT);
- add_output("Window", SHADER_SOCKET_POINT);
- add_output("Reflection", SHADER_SOCKET_NORMAL);
+ 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_IN_NORMAL(normal_osl, "NormalIn", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL);
- from_dupli = false;
- use_transform = false;
- ob_tfm = transform_identity();
+ 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;
+}
+
+TextureCoordinateNode::TextureCoordinateNode()
+: ShaderNode(node_type)
+{
}
void TextureCoordinateNode::attributes(Shader *shader, AttributeRequestSet *attributes)
@@ -2796,22 +3017,32 @@ void TextureCoordinateNode::compile(OSLCompiler& compiler)
compiler.parameter("is_background", true);
if(compiler.output_type() == SHADER_TYPE_VOLUME)
compiler.parameter("is_volume", true);
- compiler.parameter("use_transform", use_transform);
+ compiler.parameter(this, "use_transform");
Transform ob_itfm = transform_transpose(transform_inverse(ob_tfm));
compiler.parameter("object_itfm", ob_itfm);
- compiler.parameter("from_dupli", from_dupli);
+ compiler.parameter(this, "from_dupli");
compiler.add(this, "node_texture_coordinate");
}
-UVMapNode::UVMapNode()
-: ShaderNode("uvmap")
+/* UV Map */
+
+NODE_DEFINE(UVMapNode)
{
- attribute = "";
- from_dupli = false;
+ NodeType* type = NodeType::add("uvmap", create, NodeType::SHADER);
+
+ SOCKET_IN_STRING(attribute, "attribute", ustring(""));
+ SOCKET_IN_BOOLEAN(from_dupli, "from dupli", false);
+
+ SOCKET_OUT_POINT(UV, "UV");
- add_output("UV", SHADER_SOCKET_POINT);
+ return type;
+}
+
+UVMapNode::UVMapNode()
+: ShaderNode(node_type)
+{
}
void UVMapNode::attributes(Shader *shader, AttributeRequestSet *attributes)
@@ -2870,28 +3101,36 @@ void UVMapNode::compile(OSLCompiler& compiler)
else
compiler.parameter("bump_offset", "center");
- compiler.parameter("from_dupli", from_dupli);
- compiler.parameter("name", attribute.c_str());
+ 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);
+
+ 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(transparent_depth, "Transparent Depth");
+ SOCKET_OUT_FLOAT(transmission_depth, "Transmission Depth");
+
+ return type;
+}
+
LightPathNode::LightPathNode()
-: ShaderNode("light_path")
-{
- add_output("Is Camera Ray", SHADER_SOCKET_FLOAT);
- add_output("Is Shadow Ray", SHADER_SOCKET_FLOAT);
- add_output("Is Diffuse Ray", SHADER_SOCKET_FLOAT);
- add_output("Is Glossy Ray", SHADER_SOCKET_FLOAT);
- add_output("Is Singular Ray", SHADER_SOCKET_FLOAT);
- add_output("Is Reflection Ray", SHADER_SOCKET_FLOAT);
- add_output("Is Transmission Ray", SHADER_SOCKET_FLOAT);
- add_output("Is Volume Scatter Ray", SHADER_SOCKET_FLOAT);
- add_output("Ray Length", SHADER_SOCKET_FLOAT);
- add_output("Ray Depth", SHADER_SOCKET_FLOAT);
- add_output("Transparent Depth", SHADER_SOCKET_FLOAT);
- add_output("Transmission Depth", SHADER_SOCKET_FLOAT);
+: ShaderNode(node_type)
+{
}
void LightPathNode::compile(SVMCompiler& compiler)
@@ -2967,14 +3206,23 @@ void LightPathNode::compile(OSLCompiler& compiler)
/* Light Falloff */
+NODE_DEFINE(LightFalloffNode)
+{
+ NodeType* type = NodeType::add("light_fallof", create, NodeType::SHADER);
+
+ 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");
+
+ return type;
+}
+
LightFalloffNode::LightFalloffNode()
-: ShaderNode("light_fallof")
+: ShaderNode(node_type)
{
- add_input("Strength", SHADER_SOCKET_FLOAT, 100.0f);
- add_input("Smooth", SHADER_SOCKET_FLOAT, 0.0f);
- add_output("Quadratic", SHADER_SOCKET_FLOAT);
- add_output("Linear", SHADER_SOCKET_FLOAT);
- add_output("Constant", SHADER_SOCKET_FLOAT);
}
void LightFalloffNode::compile(SVMCompiler& compiler)
@@ -3017,13 +3265,21 @@ void LightFalloffNode::compile(OSLCompiler& compiler)
/* Object Info */
+NODE_DEFINE(ObjectInfoNode)
+{
+ 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");
+
+ return type;
+}
+
ObjectInfoNode::ObjectInfoNode()
-: ShaderNode("object_info")
+: ShaderNode(node_type)
{
- add_output("Location", SHADER_SOCKET_VECTOR);
- add_output("Object Index", SHADER_SOCKET_FLOAT);
- add_output("Material Index", SHADER_SOCKET_FLOAT);
- add_output("Random", SHADER_SOCKET_FLOAT);
}
void ObjectInfoNode::compile(SVMCompiler& compiler)
@@ -3056,19 +3312,27 @@ void ObjectInfoNode::compile(OSLCompiler& compiler)
/* Particle Info */
-ParticleInfoNode::ParticleInfoNode()
-: ShaderNode("particle_info")
+NODE_DEFINE(ParticleInfoNode)
{
- add_output("Index", SHADER_SOCKET_FLOAT);
- add_output("Age", SHADER_SOCKET_FLOAT);
- add_output("Lifetime", SHADER_SOCKET_FLOAT);
- add_output("Location", SHADER_SOCKET_POINT);
+ NodeType* type = NodeType::add("particle_info", create, NodeType::SHADER);
+
+ SOCKET_OUT_FLOAT(index, "Index");
+ SOCKET_OUT_FLOAT(age, "Age");
+ SOCKET_OUT_FLOAT(lifetime, "Lifetime");
+ SOCKET_OUT_POINT(location, "Location");
#if 0 /* not yet supported */
- add_output("Rotation", SHADER_SOCKET_QUATERNION);
+ SOCKET_OUT_QUATERNION(rotation, "Rotation");
#endif
- add_output("Size", SHADER_SOCKET_FLOAT);
- add_output("Velocity", SHADER_SOCKET_VECTOR);
- add_output("Angular Velocity", SHADER_SOCKET_VECTOR);
+ SOCKET_OUT_FLOAT(size, "Size");
+ SOCKET_OUT_VECTOR(velocity, "Velocity");
+ SOCKET_OUT_VECTOR(angular_velocity, "Angular Velocity");
+
+ return type;
+}
+
+ParticleInfoNode::ParticleInfoNode()
+: ShaderNode(node_type)
+{
}
void ParticleInfoNode::attributes(Shader *shader, AttributeRequestSet *attributes)
@@ -3150,15 +3414,24 @@ void ParticleInfoNode::compile(OSLCompiler& compiler)
/* Hair Info */
+NODE_DEFINE(HairInfoNode)
+{
+ 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");
+#if 0 /*output for minimum hair width transparency - deactivated */
+ SOCKET_OUT_FLOAT(fade, "Fade");
+#endif
+
+ return type;
+}
+
HairInfoNode::HairInfoNode()
-: ShaderNode("hair_info")
+: ShaderNode(node_type)
{
- add_output("Is Strand", SHADER_SOCKET_FLOAT);
- add_output("Intercept", SHADER_SOCKET_FLOAT);
- add_output("Thickness", SHADER_SOCKET_FLOAT);
- add_output("Tangent Normal", SHADER_SOCKET_NORMAL);
- /*output for minimum hair width transparency - deactivated*/
- /*add_output("Fade", SHADER_SOCKET_FLOAT);*/
}
void HairInfoNode::attributes(Shader *shader, AttributeRequestSet *attributes)
@@ -3212,19 +3485,24 @@ void HairInfoNode::compile(OSLCompiler& compiler)
/* Value */
-ValueNode::ValueNode()
-: ShaderNode("value")
+NODE_DEFINE(ValueNode)
{
- value = 0.0f;
+ NodeType* type = NodeType::add("value", create, NodeType::SHADER);
+
+ SOCKET_FLOAT(value, "Value", 0.0f);
+ SOCKET_OUT_FLOAT(value, "Value");
- add_output("Value", SHADER_SOCKET_FLOAT);
+ return type;
}
-bool ValueNode::constant_fold(ShaderGraph * /*graph*/, ShaderOutput * /*socket*/,
- float3 *optimized_value)
+ValueNode::ValueNode()
+: ShaderNode(node_type)
{
- *optimized_value = make_float3(value, value, value);
- return true;
+}
+
+void ValueNode::constant_fold(const ConstantFolder& folder)
+{
+ folder.make_constant(value);
}
void ValueNode::compile(SVMCompiler& compiler)
@@ -3242,19 +3520,24 @@ void ValueNode::compile(OSLCompiler& compiler)
/* Color */
-ColorNode::ColorNode()
-: ShaderNode("color")
+NODE_DEFINE(ColorNode)
{
- value = make_float3(0.0f, 0.0f, 0.0f);
+ NodeType* type = NodeType::add("color", create, NodeType::SHADER);
- add_output("Color", SHADER_SOCKET_COLOR);
+ SOCKET_COLOR(value, "Value", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_OUT_COLOR(color, "Color");
+
+ return type;
}
-bool ColorNode::constant_fold(ShaderGraph * /*graph*/, ShaderOutput * /*socket*/,
- float3 *optimized_value)
+ColorNode::ColorNode()
+: ShaderNode(node_type)
{
- *optimized_value = value;
- return true;
+}
+
+void ColorNode::constant_fold(const ConstantFolder& folder)
+{
+ folder.make_constant(value);
}
void ColorNode::compile(SVMCompiler& compiler)
@@ -3276,14 +3559,21 @@ void ColorNode::compile(OSLCompiler& compiler)
/* Add Closure */
+NODE_DEFINE(AddClosureNode)
+{
+ NodeType* type = NodeType::add("add_closure", create, NodeType::SHADER);
+
+ SOCKET_IN_CLOSURE(closure1, "Closure1");
+ SOCKET_IN_CLOSURE(closure2, "Closure2");
+ SOCKET_OUT_CLOSURE(closure, "Closure");
+
+ return type;
+}
+
AddClosureNode::AddClosureNode()
-: ShaderNode("add_closure")
+: ShaderNode(node_type)
{
special_type = SHADER_SPECIAL_TYPE_COMBINE_CLOSURE;
-
- add_input("Closure1", SHADER_SOCKET_CLOSURE);
- add_input("Closure2", SHADER_SOCKET_CLOSURE);
- add_output("Closure", SHADER_SOCKET_CLOSURE);
}
void AddClosureNode::compile(SVMCompiler& /*compiler*/)
@@ -3296,17 +3586,39 @@ void AddClosureNode::compile(OSLCompiler& compiler)
compiler.add(this, "node_add_closure");
}
+void AddClosureNode::constant_fold(const ConstantFolder& folder)
+{
+ 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);
+ }
+}
+
/* Mix Closure */
+NODE_DEFINE(MixClosureNode)
+{
+ 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_OUT_CLOSURE(closure, "Closure");
+
+ return type;
+}
+
MixClosureNode::MixClosureNode()
-: ShaderNode("mix_closure")
+: ShaderNode(node_type)
{
special_type = SHADER_SPECIAL_TYPE_COMBINE_CLOSURE;
-
- add_input("Fac", SHADER_SOCKET_FLOAT, 0.5f);
- add_input("Closure1", SHADER_SOCKET_CLOSURE);
- add_input("Closure2", SHADER_SOCKET_CLOSURE);
- add_output("Closure", SHADER_SOCKET_CLOSURE);
}
void MixClosureNode::compile(SVMCompiler& /*compiler*/)
@@ -3319,46 +3631,48 @@ void MixClosureNode::compile(OSLCompiler& compiler)
compiler.add(this, "node_mix_closure");
}
-bool MixClosureNode::constant_fold(ShaderGraph *graph, ShaderOutput * /*socket*/, float3 * /*optimized_value*/)
+void MixClosureNode::constant_fold(const ConstantFolder& folder)
{
ShaderInput *fac_in = input("Fac");
ShaderInput *closure1_in = input("Closure1");
ShaderInput *closure2_in = input("Closure2");
- ShaderOutput *closure_out = output("Closure");
/* remove useless mix closures nodes */
if(closure1_in->link == closure2_in->link) {
- graph->relink(this, closure_out, closure1_in->link);
- return true;
+ 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 */
- if(closure1_in->link && closure2_in->link && !fac_in->link) {
+ /* 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_in->value.x == 0.0f) {
- graph->relink(this, closure_out, closure1_in->link);
- return true;
+ if(fac <= 0.0f) {
+ folder.bypass_or_discard(closure1_in);
}
/* factor 1.0 */
- else if(fac_in->value.x == 1.0f) {
- graph->relink(this, closure_out, closure2_in->link);
- return true;
+ else if(fac >= 1.0f) {
+ folder.bypass_or_discard(closure2_in);
}
}
-
- return false;
}
/* Mix Closure */
+NODE_DEFINE(MixClosureWeightNode)
+{
+ 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_OUT_FLOAT(weight1, "Weight1");
+ SOCKET_OUT_FLOAT(weight2, "Weight2");
+
+ return type;
+}
+
MixClosureWeightNode::MixClosureWeightNode()
-: ShaderNode("mix_closure_weight")
+: ShaderNode(node_type)
{
- add_input("Weight", SHADER_SOCKET_FLOAT, 1.0f);
- add_input("Fac", SHADER_SOCKET_FLOAT, 1.0f);
- add_output("Weight1", SHADER_SOCKET_FLOAT);
- add_output("Weight2", SHADER_SOCKET_FLOAT);
}
void MixClosureWeightNode::compile(SVMCompiler& compiler)
@@ -3383,12 +3697,38 @@ void MixClosureWeightNode::compile(OSLCompiler& /*compiler*/)
/* Invert */
+NODE_DEFINE(InvertNode)
+{
+ 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_OUT_COLOR(color, "Color");
+
+ return type;
+}
+
InvertNode::InvertNode()
-: ShaderNode("invert")
+: ShaderNode(node_type)
+{
+}
+
+void InvertNode::constant_fold(const ConstantFolder& folder)
{
- add_input("Fac", SHADER_SOCKET_FLOAT, 1.0f);
- add_input("Color", SHADER_SOCKET_COLOR);
- add_output("Color", SHADER_SOCKET_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);
+ }
+ }
}
void InvertNode::compile(SVMCompiler& compiler)
@@ -3410,46 +3750,46 @@ void InvertNode::compile(OSLCompiler& compiler)
/* Mix */
-MixNode::MixNode()
-: ShaderNode("mix")
+NODE_DEFINE(MixNode)
{
- type = ustring("Mix");
+ NodeType* type = NodeType::add("mix", create, NodeType::SHADER);
- use_clamp = false;
+ 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);
- add_input("Fac", SHADER_SOCKET_FLOAT, 0.5f);
- add_input("Color1", SHADER_SOCKET_COLOR);
- add_input("Color2", SHADER_SOCKET_COLOR);
- add_output("Color", SHADER_SOCKET_COLOR);
-}
+ SOCKET_BOOLEAN(use_clamp, "Use Clamp", false);
-static ShaderEnum mix_type_init()
-{
- ShaderEnum enm;
+ 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));
- enm.insert("Mix", NODE_MIX_BLEND);
- enm.insert("Add", NODE_MIX_ADD);
- enm.insert("Multiply", NODE_MIX_MUL);
- enm.insert("Screen", NODE_MIX_SCREEN);
- enm.insert("Overlay", NODE_MIX_OVERLAY);
- enm.insert("Subtract", NODE_MIX_SUB);
- enm.insert("Divide", NODE_MIX_DIV);
- enm.insert("Difference", NODE_MIX_DIFF);
- enm.insert("Darken", NODE_MIX_DARK);
- enm.insert("Lighten", NODE_MIX_LIGHT);
- enm.insert("Dodge", NODE_MIX_DODGE);
- enm.insert("Burn", NODE_MIX_BURN);
- enm.insert("Hue", NODE_MIX_HUE);
- enm.insert("Saturation", NODE_MIX_SAT);
- enm.insert("Value", NODE_MIX_VAL);
- enm.insert("Color", NODE_MIX_COLOR);
- enm.insert("Soft Light", NODE_MIX_SOFT);
- enm.insert("Linear Light", NODE_MIX_LINEAR);
+ SOCKET_OUT_COLOR(color, "Color");
- return enm;
+ return type;
}
-ShaderEnum MixNode::type_enum = mix_type_init();
+MixNode::MixNode()
+: ShaderNode(node_type)
+{
+}
void MixNode::compile(SVMCompiler& compiler)
{
@@ -3462,7 +3802,7 @@ void MixNode::compile(SVMCompiler& compiler)
compiler.stack_assign(fac_in),
compiler.stack_assign(color1_in),
compiler.stack_assign(color2_in));
- compiler.add_node(NODE_MIX, type_enum[type], compiler.stack_assign(color_out));
+ 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));
@@ -3472,59 +3812,46 @@ void MixNode::compile(SVMCompiler& compiler)
void MixNode::compile(OSLCompiler& compiler)
{
- compiler.parameter("type", type);
- compiler.parameter("Clamp", use_clamp);
+ compiler.parameter(this, "type");
+ compiler.parameter(this, "use_clamp");
compiler.add(this, "node_mix");
}
-bool MixNode::constant_fold(ShaderGraph *graph, ShaderOutput * /*socket*/, float3 * optimized_value)
+void MixNode::constant_fold(const ConstantFolder& folder)
{
- if(type != ustring("Mix")) {
- return false;
+ if(folder.all_inputs_constant()) {
+ folder.make_constant_clamp(svm_mix(type, fac, color1, color2), use_clamp);
}
+ else {
+ folder.fold_mix(type, use_clamp);
+ }
+}
- ShaderInput *fac_in = input("Fac");
- ShaderInput *color1_in = input("Color1");
- ShaderInput *color2_in = input("Color2");
- ShaderOutput *color_out = output("Color");
+/* Combine RGB */
- /* remove useless mix colors nodes */
- if(color1_in->link && color1_in->link == color2_in->link) {
- graph->relink(this, color_out, color1_in->link);
- return true;
- }
+NODE_DEFINE(CombineRGBNode)
+{
+ NodeType* type = NodeType::add("combine_rgb", create, NodeType::SHADER);
- /* remove unused mix color input when factor is 0.0 or 1.0 */
- if(!fac_in->link) {
- /* factor 0.0 */
- if(fac_in->value.x == 0.0f) {
- if(color1_in->link)
- graph->relink(this, color_out, color1_in->link);
- else
- *optimized_value = color1_in->value;
- return true;
- }
- /* factor 1.0 */
- else if(fac_in->value.x == 1.0f) {
- if(color2_in->link)
- graph->relink(this, color_out, color2_in->link);
- else
- *optimized_value = color2_in->value;
- return true;
- }
- }
+ SOCKET_IN_FLOAT(r, "R", 0.0f);
+ SOCKET_IN_FLOAT(g, "G", 0.0f);
+ SOCKET_IN_FLOAT(b, "B", 0.0f);
- return false;
+ SOCKET_OUT_COLOR(image, "Image");
+
+ return type;
}
-/* Combine RGB */
CombineRGBNode::CombineRGBNode()
-: ShaderNode("combine_rgb")
+: ShaderNode(node_type)
+{
+}
+
+void CombineRGBNode::constant_fold(const ConstantFolder& folder)
{
- add_input("R", SHADER_SOCKET_FLOAT);
- add_input("G", SHADER_SOCKET_FLOAT);
- add_input("B", SHADER_SOCKET_FLOAT);
- add_output("Image", SHADER_SOCKET_COLOR);
+ if(folder.all_inputs_constant()) {
+ folder.make_constant(make_float3(r, g, b));
+ }
}
void CombineRGBNode::compile(SVMCompiler& compiler)
@@ -3553,13 +3880,30 @@ void CombineRGBNode::compile(OSLCompiler& compiler)
}
/* Combine XYZ */
+
+NODE_DEFINE(CombineXYZNode)
+{
+ 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_OUT_VECTOR(vector, "Vector");
+
+ return type;
+}
+
CombineXYZNode::CombineXYZNode()
-: ShaderNode("combine_xyz")
+: ShaderNode(node_type)
+{
+}
+
+void CombineXYZNode::constant_fold(const ConstantFolder& folder)
{
- add_input("X", SHADER_SOCKET_FLOAT);
- add_input("Y", SHADER_SOCKET_FLOAT);
- add_input("Z", SHADER_SOCKET_FLOAT);
- add_output("Vector", SHADER_SOCKET_VECTOR);
+ if(folder.all_inputs_constant()) {
+ folder.make_constant(make_float3(x, y, z));
+ }
}
void CombineXYZNode::compile(SVMCompiler& compiler)
@@ -3588,13 +3932,30 @@ void CombineXYZNode::compile(OSLCompiler& compiler)
}
/* Combine HSV */
+
+NODE_DEFINE(CombineHSVNode)
+{
+ 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_OUT_COLOR(color, "Color");
+
+ return type;
+}
+
CombineHSVNode::CombineHSVNode()
-: ShaderNode("combine_hsv")
+: ShaderNode(node_type)
{
- add_input("H", SHADER_SOCKET_FLOAT);
- add_input("S", SHADER_SOCKET_FLOAT);
- add_input("V", SHADER_SOCKET_FLOAT);
- add_output("Color", SHADER_SOCKET_COLOR);
+}
+
+void CombineHSVNode::constant_fold(const ConstantFolder& folder)
+{
+ if(folder.all_inputs_constant()) {
+ folder.make_constant(hsv_to_rgb(make_float3(h, s, v)));
+ }
}
void CombineHSVNode::compile(SVMCompiler& compiler)
@@ -3618,28 +3979,28 @@ void CombineHSVNode::compile(OSLCompiler& compiler)
}
/* Gamma */
-GammaNode::GammaNode()
-: ShaderNode("gamma")
+
+NODE_DEFINE(GammaNode)
{
- add_input("Color", SHADER_SOCKET_COLOR);
- add_input("Gamma", SHADER_SOCKET_FLOAT);
- add_output("Color", SHADER_SOCKET_COLOR);
+ 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");
+
+ return type;
}
-bool GammaNode::constant_fold(ShaderGraph * /*graph*/, ShaderOutput *socket, float3 *optimized_value)
+GammaNode::GammaNode()
+: ShaderNode(node_type)
{
- ShaderInput *color_in = input("Color");
- ShaderInput *gamma_in = input("Gamma");
+}
- if(socket == output("Color")) {
- if(color_in->link == NULL && gamma_in->link == NULL) {
- *optimized_value = svm_math_gamma_color(color_in->value,
- gamma_in->value.x);
- return true;
- }
+void GammaNode::constant_fold(const ConstantFolder& folder)
+{
+ if(folder.all_inputs_constant()) {
+ folder.make_constant(svm_math_gamma_color(color, gamma));
}
-
- return false;
}
void GammaNode::compile(SVMCompiler& compiler)
@@ -3660,13 +4021,30 @@ void GammaNode::compile(OSLCompiler& compiler)
}
/* Bright Contrast */
+
+NODE_DEFINE(BrightContrastNode)
+{
+ 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_OUT_COLOR(color, "Color");
+
+ return type;
+}
+
BrightContrastNode::BrightContrastNode()
-: ShaderNode("brightness")
+: ShaderNode(node_type)
+{
+}
+
+void BrightContrastNode::constant_fold(const ConstantFolder& folder)
{
- add_input("Color", SHADER_SOCKET_COLOR);
- add_input("Bright", SHADER_SOCKET_FLOAT);
- add_input("Contrast", SHADER_SOCKET_FLOAT);
- add_output("Color", SHADER_SOCKET_COLOR);
+ if(folder.all_inputs_constant()) {
+ folder.make_constant(svm_brightness_contrast(color, bright, contrast));
+ }
}
void BrightContrastNode::compile(SVMCompiler& compiler)
@@ -3690,13 +4068,35 @@ void BrightContrastNode::compile(OSLCompiler& compiler)
}
/* Separate RGB */
+
+NODE_DEFINE(SeparateRGBNode)
+{
+ NodeType* type = NodeType::add("separate_rgb", create, NodeType::SHADER);
+
+ SOCKET_IN_COLOR(color, "Image", make_float3(0.0f, 0.0f, 0.0f));
+
+ SOCKET_OUT_FLOAT(g, "R");
+ SOCKET_OUT_FLOAT(g, "G");
+ SOCKET_OUT_FLOAT(b, "B");
+
+ return type;
+}
+
SeparateRGBNode::SeparateRGBNode()
-: ShaderNode("separate_rgb")
+: ShaderNode(node_type)
+{
+}
+
+void SeparateRGBNode::constant_fold(const ConstantFolder& folder)
{
- add_input("Image", SHADER_SOCKET_COLOR);
- add_output("R", SHADER_SOCKET_FLOAT);
- add_output("G", SHADER_SOCKET_FLOAT);
- add_output("B", SHADER_SOCKET_FLOAT);
+ 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)
@@ -3725,13 +4125,35 @@ void SeparateRGBNode::compile(OSLCompiler& compiler)
}
/* Separate XYZ */
+
+NODE_DEFINE(SeparateXYZNode)
+{
+ NodeType* type = NodeType::add("separate_xyz", create, NodeType::SHADER);
+
+ 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");
+
+ return type;
+}
+
SeparateXYZNode::SeparateXYZNode()
-: ShaderNode("separate_xyz")
+: ShaderNode(node_type)
+{
+}
+
+void SeparateXYZNode::constant_fold(const ConstantFolder& folder)
{
- add_input("Vector", SHADER_SOCKET_VECTOR);
- add_output("X", SHADER_SOCKET_FLOAT);
- add_output("Y", SHADER_SOCKET_FLOAT);
- add_output("Z", SHADER_SOCKET_FLOAT);
+ 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)
@@ -3760,13 +4182,37 @@ void SeparateXYZNode::compile(OSLCompiler& compiler)
}
/* Separate HSV */
+
+NODE_DEFINE(SeparateHSVNode)
+{
+ NodeType* type = NodeType::add("separate_hsv", create, NodeType::SHADER);
+
+ 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");
+
+ return type;
+}
+
SeparateHSVNode::SeparateHSVNode()
-: ShaderNode("separate_hsv")
+: ShaderNode(node_type)
+{
+}
+
+void SeparateHSVNode::constant_fold(const ConstantFolder& folder)
{
- add_input("Color", SHADER_SOCKET_COLOR);
- add_output("H", SHADER_SOCKET_FLOAT);
- add_output("S", SHADER_SOCKET_FLOAT);
- add_output("V", SHADER_SOCKET_FLOAT);
+ 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;
+ }
+ }
+ }
}
void SeparateHSVNode::compile(SVMCompiler& compiler)
@@ -3790,15 +4236,25 @@ void SeparateHSVNode::compile(OSLCompiler& compiler)
}
/* Hue Saturation Value */
+
+NODE_DEFINE(HSVNode)
+{
+ 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_OUT_COLOR(color, "Color");
+
+ return type;
+}
+
HSVNode::HSVNode()
-: ShaderNode("hsv")
+: ShaderNode(node_type)
{
- add_input("Hue", SHADER_SOCKET_FLOAT);
- add_input("Saturation", SHADER_SOCKET_FLOAT);
- add_input("Value", SHADER_SOCKET_FLOAT);
- add_input("Fac", SHADER_SOCKET_FLOAT);
- add_input("Color", SHADER_SOCKET_COLOR);
- add_output("Color", SHADER_SOCKET_COLOR);
}
void HSVNode::compile(SVMCompiler& compiler)
@@ -3828,14 +4284,22 @@ void HSVNode::compile(OSLCompiler& compiler)
/* Attribute */
-AttributeNode::AttributeNode()
-: ShaderNode("attribute")
+NODE_DEFINE(AttributeNode)
{
- attribute = "";
+ NodeType* type = NodeType::add("attribute", create, NodeType::SHADER);
+
+ SOCKET_STRING(attribute, "Attribute", ustring(""));
+
+ SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_OUT_VECTOR(vector, "Vector");
+ SOCKET_OUT_FLOAT(fac, "Fac");
+
+ return type;
+}
- add_output("Color", SHADER_SOCKET_COLOR);
- add_output("Vector", SHADER_SOCKET_VECTOR);
- add_output("Fac", SHADER_SOCKET_FLOAT);
+AttributeNode::AttributeNode()
+: ShaderNode(node_type)
+{
}
void AttributeNode::attributes(Shader *shader, AttributeRequestSet *attributes)
@@ -3911,12 +4375,20 @@ void AttributeNode::compile(OSLCompiler& compiler)
/* Camera */
+NODE_DEFINE(CameraNode)
+{
+ 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");
+
+ return type;
+}
+
CameraNode::CameraNode()
-: ShaderNode("camera")
+: ShaderNode(node_type)
{
- add_output("View Vector", SHADER_SOCKET_VECTOR);
- add_output("View Z Depth", SHADER_SOCKET_FLOAT);
- add_output("View Distance", SHADER_SOCKET_FLOAT);
}
void CameraNode::compile(SVMCompiler& compiler)
@@ -3938,12 +4410,21 @@ void CameraNode::compile(OSLCompiler& compiler)
/* Fresnel */
+NODE_DEFINE(FresnelNode)
+{
+ 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_OUT_FLOAT(fac, "Fac");
+
+ return type;
+}
+
FresnelNode::FresnelNode()
-: ShaderNode("fresnel")
+: ShaderNode(node_type)
{
- add_input("Normal", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, ShaderInput::USE_OSL);
- add_input("IOR", SHADER_SOCKET_FLOAT, 1.45f);
- add_output("Fac", SHADER_SOCKET_FLOAT);
}
void FresnelNode::compile(SVMCompiler& compiler)
@@ -3954,7 +4435,7 @@ void FresnelNode::compile(SVMCompiler& compiler)
compiler.add_node(NODE_FRESNEL,
compiler.stack_assign(IOR_in),
- __float_as_int(IOR_in->value.x),
+ __float_as_int(IOR),
compiler.encode_uchar4(
compiler.stack_assign_if_linked(normal_in),
compiler.stack_assign(fac_out)));
@@ -3967,14 +4448,22 @@ void FresnelNode::compile(OSLCompiler& compiler)
/* Layer Weight */
-LayerWeightNode::LayerWeightNode()
-: ShaderNode("layer_weight")
+NODE_DEFINE(LayerWeightNode)
{
- add_input("Normal", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, ShaderInput::USE_OSL);
- add_input("Blend", SHADER_SOCKET_FLOAT, 0.5f);
+ 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_OUT_FLOAT(fresnel, "Fresnel");
+ SOCKET_OUT_FLOAT(facing, "Facing");
+
+ return type;
+}
- add_output("Fresnel", SHADER_SOCKET_FLOAT);
- add_output("Facing", SHADER_SOCKET_FLOAT);
+LayerWeightNode::LayerWeightNode()
+: ShaderNode(node_type)
+{
}
void LayerWeightNode::compile(SVMCompiler& compiler)
@@ -3987,7 +4476,7 @@ void LayerWeightNode::compile(SVMCompiler& compiler)
if(!fresnel_out->links.empty()) {
compiler.add_node(NODE_LAYER_WEIGHT,
compiler.stack_assign_if_linked(blend_in),
- __float_as_int(blend_in->value.x),
+ __float_as_int(blend),
compiler.encode_uchar4(NODE_LAYER_WEIGHT_FRESNEL,
compiler.stack_assign_if_linked(normal_in),
compiler.stack_assign(fresnel_out)));
@@ -3996,7 +4485,7 @@ void LayerWeightNode::compile(SVMCompiler& compiler)
if(!facing_out->links.empty()) {
compiler.add_node(NODE_LAYER_WEIGHT,
compiler.stack_assign_if_linked(blend_in),
- __float_as_int(blend_in->value.x),
+ __float_as_int(blend),
compiler.encode_uchar4(NODE_LAYER_WEIGHT_FACING,
compiler.stack_assign_if_linked(normal_in),
compiler.stack_assign(facing_out)));
@@ -4010,13 +4499,20 @@ void LayerWeightNode::compile(OSLCompiler& compiler)
/* Wireframe */
+NODE_DEFINE(WireframeNode)
+{
+ 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");
+
+ return type;
+}
+
WireframeNode::WireframeNode()
-: ShaderNode("wireframe")
+: ShaderNode(node_type)
{
- add_input("Size", SHADER_SOCKET_FLOAT, 0.01f);
- add_output("Fac", SHADER_SOCKET_FLOAT);
-
- use_pixel_size = false;
}
void WireframeNode::compile(SVMCompiler& compiler)
@@ -4049,17 +4545,25 @@ void WireframeNode::compile(OSLCompiler& compiler)
else {
compiler.parameter("bump_offset", "center");
}
- compiler.parameter("use_pixel_size", use_pixel_size);
+ compiler.parameter(this, "use_pixel_size");
compiler.add(this, "node_wireframe");
}
/* Wavelength */
+NODE_DEFINE(WavelengthNode)
+{
+ NodeType* type = NodeType::add("wavelength", create, NodeType::SHADER);
+
+ SOCKET_IN_FLOAT(wavelength, "Wavelength", 500.0f);
+ SOCKET_OUT_COLOR(color, "Color");
+
+ return type;
+}
+
WavelengthNode::WavelengthNode()
-: ShaderNode("wavelength")
+: ShaderNode(node_type)
{
- add_input("Wavelength", SHADER_SOCKET_FLOAT, 500.0f);
- add_output("Color", SHADER_SOCKET_COLOR);
}
void WavelengthNode::compile(SVMCompiler& compiler)
@@ -4079,25 +4583,26 @@ void WavelengthNode::compile(OSLCompiler& compiler)
/* Blackbody */
-BlackbodyNode::BlackbodyNode()
-: ShaderNode("blackbody")
+NODE_DEFINE(BlackbodyNode)
{
- add_input("Temperature", SHADER_SOCKET_FLOAT, 1200.0f);
- add_output("Color", SHADER_SOCKET_COLOR);
+ NodeType* type = NodeType::add("blackbody", create, NodeType::SHADER);
+
+ SOCKET_IN_FLOAT(temperature, "Temperature", 1200.0f);
+ SOCKET_OUT_COLOR(color, "Color");
+
+ return type;
}
-bool BlackbodyNode::constant_fold(ShaderGraph * /*graph*/, ShaderOutput *socket, float3 *optimized_value)
+BlackbodyNode::BlackbodyNode()
+: ShaderNode(node_type)
{
- ShaderInput *temperature_in = input("Temperature");
+}
- if(socket == output("Color")) {
- if(temperature_in->link == NULL) {
- *optimized_value = svm_math_blackbody_color(temperature_in->value.x);
- return true;
- }
+void BlackbodyNode::constant_fold(const ConstantFolder& folder)
+{
+ if(folder.all_inputs_constant()) {
+ folder.make_constant(svm_math_blackbody_color(temperature));
}
-
- return false;
}
void BlackbodyNode::compile(SVMCompiler& compiler)
@@ -4117,15 +4622,22 @@ void BlackbodyNode::compile(OSLCompiler& compiler)
/* Output */
+NODE_DEFINE(OutputNode)
+{
+ NodeType* type = NodeType::add("output", create, NodeType::SHADER);
+
+ SOCKET_IN_CLOSURE(surface, "Surface");
+ SOCKET_IN_CLOSURE(volume, "Volume");
+ SOCKET_IN_FLOAT(displacement, "Displacement", 0.0f);
+ SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f));
+
+ return type;
+}
+
OutputNode::OutputNode()
-: ShaderNode("output")
+: ShaderNode(node_type)
{
special_type = SHADER_SPECIAL_TYPE_OUTPUT;
-
- add_input("Surface", SHADER_SOCKET_CLOSURE);
- add_input("Volume", SHADER_SOCKET_CLOSURE);
- add_input("Displacement", SHADER_SOCKET_FLOAT);
- add_input("Normal", SHADER_SOCKET_NORMAL);
}
void OutputNode::compile(SVMCompiler& compiler)
@@ -4151,67 +4663,55 @@ void OutputNode::compile(OSLCompiler& compiler)
/* Math */
-MathNode::MathNode()
-: ShaderNode("math")
+NODE_DEFINE(MathNode)
{
- type = ustring("Add");
+ NodeType* type = NodeType::add("math", create, NodeType::SHADER);
- use_clamp = false;
+ 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);
+ SOCKET_ENUM(type, "Type", type_enum, NODE_MATH_ADD);
- add_input("Value1", SHADER_SOCKET_FLOAT);
- add_input("Value2", SHADER_SOCKET_FLOAT);
- add_output("Value", SHADER_SOCKET_FLOAT);
-}
+ SOCKET_BOOLEAN(use_clamp, "Use Clamp", false);
-static ShaderEnum math_type_init()
-{
- ShaderEnum enm;
+ SOCKET_IN_FLOAT(value1, "Value1", 0.0f);
+ SOCKET_IN_FLOAT(value2, "Value2", 0.0f);
- enm.insert("Add", NODE_MATH_ADD);
- enm.insert("Subtract", NODE_MATH_SUBTRACT);
- enm.insert("Multiply", NODE_MATH_MULTIPLY);
- enm.insert("Divide", NODE_MATH_DIVIDE);
- enm.insert("Sine", NODE_MATH_SINE);
- enm.insert("Cosine", NODE_MATH_COSINE);
- enm.insert("Tangent", NODE_MATH_TANGENT);
- enm.insert("Arcsine", NODE_MATH_ARCSINE);
- enm.insert("Arccosine", NODE_MATH_ARCCOSINE);
- enm.insert("Arctangent", NODE_MATH_ARCTANGENT);
- enm.insert("Power", NODE_MATH_POWER);
- enm.insert("Logarithm", NODE_MATH_LOGARITHM);
- enm.insert("Minimum", NODE_MATH_MINIMUM);
- enm.insert("Maximum", NODE_MATH_MAXIMUM);
- enm.insert("Round", NODE_MATH_ROUND);
- enm.insert("Less Than", NODE_MATH_LESS_THAN);
- enm.insert("Greater Than", NODE_MATH_GREATER_THAN);
- enm.insert("Modulo", NODE_MATH_MODULO);
- enm.insert("Absolute", NODE_MATH_ABSOLUTE);
+ SOCKET_OUT_FLOAT(value, "Value");
- return enm;
+ return type;
}
-ShaderEnum MathNode::type_enum = math_type_init();
-
-bool MathNode::constant_fold(ShaderGraph * /*graph*/, ShaderOutput *socket, float3 *optimized_value)
+MathNode::MathNode()
+: ShaderNode(node_type)
{
- ShaderInput *value1_in = input("Value1");
- ShaderInput *value2_in = input("Value2");
-
- if(socket == output("Value")) {
- if(value1_in->link == NULL && value2_in->link == NULL) {
- optimized_value->x = svm_math((NodeMath)type_enum[type],
- value1_in->value.x,
- value2_in->value.x);
-
- if(use_clamp) {
- optimized_value->x = saturate(optimized_value->x);
- }
+}
- return true;
- }
+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);
}
-
- return false;
}
void MathNode::compile(SVMCompiler& compiler)
@@ -4220,10 +4720,7 @@ void MathNode::compile(SVMCompiler& compiler)
ShaderInput *value2_in = input("Value2");
ShaderOutput *value_out = output("Value");
- compiler.add_node(NODE_MATH,
- type_enum[type],
- compiler.stack_assign(value1_in),
- compiler.stack_assign(value2_in));
+ 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) {
@@ -4234,66 +4731,62 @@ void MathNode::compile(SVMCompiler& compiler)
void MathNode::compile(OSLCompiler& compiler)
{
- compiler.parameter("type", type);
- compiler.parameter("Clamp", use_clamp);
+ compiler.parameter(this, "type");
+ compiler.parameter(this, "use_clamp");
compiler.add(this, "node_math");
}
/* VectorMath */
-VectorMathNode::VectorMathNode()
-: ShaderNode("vector_math")
+NODE_DEFINE(VectorMathNode)
{
- type = ustring("Add");
+ NodeType* type = NodeType::add("vector_math", create, NodeType::SHADER);
- add_input("Vector1", SHADER_SOCKET_VECTOR);
- add_input("Vector2", SHADER_SOCKET_VECTOR);
- add_output("Value", SHADER_SOCKET_FLOAT);
- add_output("Vector", SHADER_SOCKET_VECTOR);
-}
+ 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 ShaderEnum vector_math_type_init()
-{
- ShaderEnum enm;
+ 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));
- enm.insert("Add", NODE_VECTOR_MATH_ADD);
- enm.insert("Subtract", NODE_VECTOR_MATH_SUBTRACT);
- enm.insert("Average", NODE_VECTOR_MATH_AVERAGE);
- enm.insert("Dot Product", NODE_VECTOR_MATH_DOT_PRODUCT);
- enm.insert("Cross Product", NODE_VECTOR_MATH_CROSS_PRODUCT);
- enm.insert("Normalize", NODE_VECTOR_MATH_NORMALIZE);
+ SOCKET_OUT_FLOAT(value, "Value");
+ SOCKET_OUT_VECTOR(vector, "Vector");
- return enm;
+ return type;
}
-ShaderEnum VectorMathNode::type_enum = vector_math_type_init();
-
-bool VectorMathNode::constant_fold(ShaderGraph * /*graph*/, ShaderOutput *socket, float3 *optimized_value)
+VectorMathNode::VectorMathNode()
+: ShaderNode(node_type)
{
- ShaderInput *vector1_in = input("Vector1");
- ShaderInput *vector2_in = input("Vector2");
+}
+void VectorMathNode::constant_fold(const ConstantFolder& folder)
+{
float value;
float3 vector;
- if(vector1_in->link == NULL && vector2_in->link == NULL) {
+ if(folder.all_inputs_constant()) {
svm_vector_math(&value,
&vector,
- (NodeVectorMath)type_enum[type],
- vector1_in->value,
- vector2_in->value);
+ type,
+ vector1,
+ vector2);
- if(socket == output("Value")) {
- optimized_value->x = value;
- return true;
+ if(folder.output == output("Value")) {
+ folder.make_constant(value);
}
- else if(socket == output("Vector")) {
- *optimized_value = vector;
- return true;
+ else if(folder.output == output("Vector")) {
+ folder.make_constant(vector);
}
}
-
- return false;
+ else {
+ folder.fold_vector_math(type);
+ }
}
void VectorMathNode::compile(SVMCompiler& compiler)
@@ -4304,7 +4797,7 @@ void VectorMathNode::compile(SVMCompiler& compiler)
ShaderOutput *vector_out = output("Vector");
compiler.add_node(NODE_VECTOR_MATH,
- type_enum[type],
+ type,
compiler.stack_assign(vector1_in),
compiler.stack_assign(vector2_in));
compiler.add_node(NODE_VECTOR_MATH,
@@ -4314,90 +4807,87 @@ void VectorMathNode::compile(SVMCompiler& compiler)
void VectorMathNode::compile(OSLCompiler& compiler)
{
- compiler.parameter("type", type);
+ compiler.parameter(this, "type");
compiler.add(this, "node_vector_math");
}
/* VectorTransform */
-VectorTransformNode::VectorTransformNode()
-: ShaderNode("vector_transform")
+NODE_DEFINE(VectorTransformNode)
{
- type = ustring("Vector");
- convert_from = ustring("world");
- convert_to = ustring("object");
+ NodeType* type = NodeType::add("vector_transform", create, NodeType::SHADER);
- add_input("Vector", SHADER_SOCKET_VECTOR);
- add_output("Vector", SHADER_SOCKET_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 ShaderEnum vector_transform_type_init()
-{
- ShaderEnum enm;
+ 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);
- enm.insert("Vector", NODE_VECTOR_TRANSFORM_TYPE_VECTOR);
- enm.insert("Point", NODE_VECTOR_TRANSFORM_TYPE_POINT);
- enm.insert("Normal", NODE_VECTOR_TRANSFORM_TYPE_NORMAL);
+ SOCKET_IN_VECTOR(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f));
+ SOCKET_OUT_VECTOR(vector, "Vector");
- return enm;
+ return type;
}
-static ShaderEnum vector_transform_convert_space_init()
+VectorTransformNode::VectorTransformNode()
+: ShaderNode(node_type)
{
- ShaderEnum enm;
-
- enm.insert("world", NODE_VECTOR_TRANSFORM_CONVERT_SPACE_WORLD);
- enm.insert("object", NODE_VECTOR_TRANSFORM_CONVERT_SPACE_OBJECT);
- enm.insert("camera", NODE_VECTOR_TRANSFORM_CONVERT_SPACE_CAMERA);
-
- return enm;
}
-ShaderEnum VectorTransformNode::type_enum = vector_transform_type_init();
-ShaderEnum VectorTransformNode::convert_space_enum = vector_transform_convert_space_init();
-
void VectorTransformNode::compile(SVMCompiler& compiler)
{
ShaderInput *vector_in = input("Vector");
ShaderOutput *vector_out = output("Vector");
compiler.add_node(NODE_VECTOR_TRANSFORM,
- compiler.encode_uchar4(type_enum[type],
- convert_space_enum[convert_from],
- convert_space_enum[convert_to]),
+ 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)
{
- compiler.parameter("type", type);
- compiler.parameter("convert_from", convert_from);
- compiler.parameter("convert_to", convert_to);
+ compiler.parameter(this, "type");
+ compiler.parameter(this, "convert_from");
+ compiler.parameter(this, "convert_to");
compiler.add(this, "node_vector_transform");
}
/* BumpNode */
-BumpNode::BumpNode()
-: ShaderNode("bump")
+NODE_DEFINE(BumpNode)
{
- invert = false;
+ NodeType* type = NodeType::add("bump", create, NodeType::SHADER);
- special_type = SHADER_SPECIAL_TYPE_BUMP;
+ SOCKET_BOOLEAN(invert, "Invert", 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 */
- add_input("Height", SHADER_SOCKET_FLOAT);
+ 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_OUT_NORMAL(normal, "Normal");
- add_input("SampleCenter", SHADER_SOCKET_FLOAT);
- add_input("SampleX", SHADER_SOCKET_FLOAT);
- add_input("SampleY", SHADER_SOCKET_FLOAT);
- add_input("Normal", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL);
- add_input("Strength", SHADER_SOCKET_FLOAT, 1.0f);
- add_input("Distance", SHADER_SOCKET_FLOAT, 0.1f);
+ return type;
+}
- add_output("Normal", SHADER_SOCKET_NORMAL);
+BumpNode::BumpNode()
+: ShaderNode(node_type)
+{
+ special_type = SHADER_SPECIAL_TYPE_BUMP;
}
void BumpNode::compile(SVMCompiler& compiler)
@@ -4426,13 +4916,11 @@ void BumpNode::compile(SVMCompiler& compiler)
void BumpNode::compile(OSLCompiler& compiler)
{
- compiler.parameter("invert", invert);
+ compiler.parameter(this, "invert");
compiler.add(this, "node_bump");
}
-bool BumpNode::constant_fold(ShaderGraph *graph,
- ShaderOutput * /*socket*/,
- float3 * /*optimized_value*/)
+void BumpNode::constant_fold(const ConstantFolder& folder)
{
ShaderInput *height_in = input("Height");
ShaderInput *normal_in = input("Normal");
@@ -4440,46 +4928,60 @@ bool BumpNode::constant_fold(ShaderGraph *graph,
if(height_in->link == NULL) {
if(normal_in->link == NULL) {
GeometryNode *geom = new GeometryNode();
- graph->add(geom);
- graph->relink(this, outputs[0], geom->output("Normal"));
+ folder.graph->add(geom);
+ folder.bypass(geom->output("Normal"));
}
else {
- graph->relink(this, outputs[0], normal_in->link);
+ folder.bypass(normal_in->link);
}
- return true;
}
/* TODO(sergey): Ignore bump with zero strength. */
-
- return false;
}
-/* RGBCurvesNode */
-RGBCurvesNode::RGBCurvesNode()
-: ShaderNode("rgb_curves")
+/* Curve node */
+
+CurvesNode::CurvesNode(const NodeType *node_type)
+: ShaderNode(node_type)
+{
+}
+
+void CurvesNode::constant_fold(const ConstantFolder& folder, ShaderInput *value_in)
{
- add_input("Fac", SHADER_SOCKET_FLOAT);
- add_input("Color", SHADER_SOCKET_COLOR);
- add_output("Color", SHADER_SOCKET_COLOR);
+ ShaderInput *fac_in = input("Fac");
- min_x = 0.0f;
- max_x = 1.0f;
+ /* remove no-op node */
+ if(!fac_in->link && fac == 0.0f) {
+ folder.bypass(value_in->link);
+ }
+ /* evaluate fully constant node */
+ else 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;
+
+ 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));
+ }
}
-void RGBCurvesNode::compile(SVMCompiler& compiler)
+void CurvesNode::compile(SVMCompiler& compiler, int type, ShaderInput *value_in, ShaderOutput *value_out)
{
if(curves.size() == 0)
return;
ShaderInput *fac_in = input("Fac");
- ShaderInput *color_in = input("Color");
- ShaderOutput *color_out = output("Color");
- compiler.add_node(NODE_RGB_CURVES,
+ compiler.add_node(type,
compiler.encode_uchar4(compiler.stack_assign(fac_in),
- compiler.stack_assign(color_in),
- compiler.stack_assign(color_out)),
+ compiler.stack_assign(value_in),
+ compiler.stack_assign(value_out)),
__float_as_int(min_x),
__float_as_int(max_x));
@@ -4488,72 +4990,149 @@ void RGBCurvesNode::compile(SVMCompiler& compiler)
compiler.add_node(float3_to_float4(curves[i]));
}
-void RGBCurvesNode::compile(OSLCompiler& compiler)
+void CurvesNode::compile(OSLCompiler& compiler, const char* name)
{
if(curves.size() == 0)
return;
compiler.parameter_color_array("ramp", curves);
- compiler.parameter("min_x", min_x);
- compiler.parameter("max_x", max_x);
- compiler.add(this, "node_rgb_curves");
+ compiler.parameter(this, "min_x");
+ compiler.parameter(this, "max_x");
+ compiler.add(this, name);
}
-/* VectorCurvesNode */
+void CurvesNode::compile(SVMCompiler& /*compiler*/)
+{
+ assert(0);
+}
-VectorCurvesNode::VectorCurvesNode()
-: ShaderNode("vector_curves")
+void CurvesNode::compile(OSLCompiler& /*compiler*/)
+{
+ assert(0);
+}
+
+/* RGBCurvesNode */
+
+NODE_DEFINE(RGBCurvesNode)
{
- add_input("Fac", SHADER_SOCKET_FLOAT);
- add_input("Vector", SHADER_SOCKET_VECTOR);
- add_output("Vector", SHADER_SOCKET_VECTOR);
+ 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);
- min_x = 0.0f;
- 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_OUT_COLOR(value, "Color");
+
+ return type;
}
-void VectorCurvesNode::compile(SVMCompiler& compiler)
+RGBCurvesNode::RGBCurvesNode()
+: CurvesNode(node_type)
{
- if(curves.size() == 0)
- return;
+}
- ShaderInput *fac_in = input("Fac");
- ShaderInput *vector_in = input("Vector");
- ShaderOutput *vector_out = output("Vector");
+void RGBCurvesNode::constant_fold(const ConstantFolder& folder)
+{
+ CurvesNode::constant_fold(folder, input("Color"));
+}
- compiler.add_node(NODE_VECTOR_CURVES,
- compiler.encode_uchar4(compiler.stack_assign(fac_in),
- compiler.stack_assign(vector_in),
- compiler.stack_assign(vector_out)),
- __float_as_int(min_x),
- __float_as_int(max_x));
+void RGBCurvesNode::compile(SVMCompiler& compiler)
+{
+ CurvesNode::compile(compiler, NODE_RGB_CURVES, input("Color"), output("Color"));
+}
- compiler.add_node(curves.size());
- for(int i = 0; i < curves.size(); i++)
- compiler.add_node(float3_to_float4(curves[i]));
+void RGBCurvesNode::compile(OSLCompiler& compiler)
+{
+ CurvesNode::compile(compiler, "node_rgb_curves");
}
-void VectorCurvesNode::compile(OSLCompiler& compiler)
+/* VectorCurvesNode */
+
+NODE_DEFINE(VectorCurvesNode)
{
- if(curves.size() == 0)
- return;
+ NodeType* type = NodeType::add("vector_curves", create, NodeType::SHADER);
- compiler.parameter_color_array("ramp", curves);
- compiler.parameter("min_x", min_x);
- compiler.parameter("max_x", max_x);
- compiler.add(this, "node_vector_curves");
+ 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_OUT_VECTOR(value, "Vector");
+
+ return type;
+}
+
+VectorCurvesNode::VectorCurvesNode()
+: CurvesNode(node_type)
+{
+}
+
+void VectorCurvesNode::constant_fold(const ConstantFolder& folder)
+{
+ CurvesNode::constant_fold(folder, input("Vector"));
+}
+
+void VectorCurvesNode::compile(SVMCompiler& compiler)
+{
+ CurvesNode::compile(compiler, NODE_VECTOR_CURVES, input("Vector"), output("Vector"));
+}
+
+void VectorCurvesNode::compile(OSLCompiler& compiler)
+{
+ CurvesNode::compile(compiler, "node_vector_curves");
}
/* RGBRampNode */
+NODE_DEFINE(RGBRampNode)
+{
+ 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_IN_FLOAT(fac, "Fac", 0.0f);
+
+ SOCKET_OUT_COLOR(color, "Color");
+ SOCKET_OUT_FLOAT(alpha, "Alpha");
+
+ return type;
+}
+
RGBRampNode::RGBRampNode()
-: ShaderNode("rgb_ramp")
+: ShaderNode(node_type)
+{
+}
+
+void RGBRampNode::constant_fold(const ConstantFolder& folder)
{
- add_input("Fac", SHADER_SOCKET_FLOAT);
- add_output("Color", SHADER_SOCKET_COLOR);
- add_output("Alpha", SHADER_SOCKET_FLOAT);
+ 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);
- interpolate = true;
+ /* 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;
+
+ 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)
@@ -4584,18 +5163,26 @@ void RGBRampNode::compile(OSLCompiler& compiler)
compiler.parameter_color_array("ramp_color", ramp);
compiler.parameter_array("ramp_alpha", ramp_alpha.data(), ramp_alpha.size());
- compiler.parameter("ramp_interpolate", interpolate);
+ compiler.parameter(this, "interpolate");
compiler.add(this, "node_rgb_ramp");
}
/* Set Normal Node */
+NODE_DEFINE(SetNormalNode)
+{
+ 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");
+
+ return type;
+}
+
SetNormalNode::SetNormalNode()
-: ShaderNode("set_normal")
+: ShaderNode(node_type)
{
- add_input("Direction", SHADER_SOCKET_VECTOR);
- add_output("Normal", SHADER_SOCKET_NORMAL);
}
void SetNormalNode::compile(SVMCompiler& compiler)
@@ -4613,20 +5200,73 @@ void SetNormalNode::compile(OSLCompiler& compiler)
compiler.add(this, "node_set_normal");
}
-/* OSLScriptNode */
+/* OSLNode */
-OSLScriptNode::OSLScriptNode()
-: ShaderNode("osl_script")
+OSLNode::OSLNode()
+: ShaderNode(new NodeType(NodeType::SHADER))
{
special_type = SHADER_SPECIAL_TYPE_SCRIPT;
}
-void OSLScriptNode::compile(SVMCompiler& /*compiler*/)
+OSLNode::~OSLNode()
+{
+ delete type;
+}
+
+ShaderNode *OSLNode::clone() const
+{
+ return OSLNode::create(this->inputs.size(), this);
+}
+
+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;
+
+ 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);
+
+ OSLNode *node = new(node_memory) OSLNode(*from);
+ node->type = new NodeType(*(from->type));
+ return node;
+ }
+}
+
+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;
+}
+
+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);
+}
+
+void OSLNode::add_output(ustring name, SocketType::Type socket_type)
+{
+ const_cast<NodeType*>(type)->register_output(name, name, socket_type);
+}
+
+void OSLNode::compile(SVMCompiler&)
{
/* doesn't work for SVM, obviously ... */
}
-void OSLScriptNode::compile(OSLCompiler& compiler)
+void OSLNode::compile(OSLCompiler& compiler)
{
if(!filepath.empty())
compiler.add(this, filepath.c_str(), true);
@@ -4636,37 +5276,37 @@ void OSLScriptNode::compile(OSLCompiler& compiler)
/* Normal Map */
-static ShaderEnum normal_map_space_init()
+NODE_DEFINE(NormalMapNode)
{
- ShaderEnum enm;
+ NodeType* type = NodeType::add("normal_map", create, NodeType::SHADER);
- enm.insert("Tangent", NODE_NORMAL_MAP_TANGENT);
- enm.insert("Object", NODE_NORMAL_MAP_OBJECT);
- enm.insert("World", NODE_NORMAL_MAP_WORLD);
- enm.insert("Blender Object", NODE_NORMAL_MAP_BLENDER_OBJECT);
- enm.insert("Blender World", NODE_NORMAL_MAP_BLENDER_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);
+ 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_TANGENT_RADIAL);
- return enm;
-}
+ SOCKET_STRING(attribute, "Attribute", ustring(""));
-ShaderEnum NormalMapNode::space_enum = normal_map_space_init();
+ 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));
-NormalMapNode::NormalMapNode()
-: ShaderNode("normal_map")
-{
- space = ustring("Tangent");
- attribute = ustring("");
+ SOCKET_OUT_NORMAL(normal, "Normal");
- add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, ShaderInput::USE_OSL);
- add_input("Strength", SHADER_SOCKET_FLOAT, 1.0f);
- add_input("Color", SHADER_SOCKET_COLOR);
+ return type;
+}
- add_output("Normal", SHADER_SOCKET_NORMAL);
+NormalMapNode::NormalMapNode()
+: ShaderNode(node_type)
+{
}
void NormalMapNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
- if(shader->has_surface && space == ustring("Tangent")) {
+ if(shader->has_surface && space == NODE_NORMAL_MAP_TANGENT) {
if(attribute == ustring("")) {
attributes->add(ATTR_STD_UV_TANGENT);
attributes->add(ATTR_STD_UV_TANGENT_SIGN);
@@ -4689,7 +5329,7 @@ void NormalMapNode::compile(SVMCompiler& compiler)
ShaderOutput *normal_out = output("Normal");
int attr = 0, attr_sign = 0;
- if(space == ustring("Tangent")) {
+ if(space == NODE_NORMAL_MAP_TANGENT) {
if(attribute == ustring("")) {
attr = compiler.attribute(ATTR_STD_UV_TANGENT);
attr_sign = compiler.attribute(ATTR_STD_UV_TANGENT_SIGN);
@@ -4705,13 +5345,13 @@ void NormalMapNode::compile(SVMCompiler& compiler)
compiler.stack_assign(color_in),
compiler.stack_assign(strength_in),
compiler.stack_assign(normal_out),
- space_enum[space]),
+ space),
attr, attr_sign);
}
void NormalMapNode::compile(OSLCompiler& compiler)
{
- if(space == ustring("Tangent")) {
+ if(space == NODE_NORMAL_MAP_TANGENT) {
if(attribute == ustring("")) {
compiler.parameter("attr_name", ustring("geom:tangent"));
compiler.parameter("attr_sign_name", ustring("geom:tangent_sign"));
@@ -4722,52 +5362,44 @@ void NormalMapNode::compile(OSLCompiler& compiler)
}
}
- compiler.parameter("space", space);
-
+ compiler.parameter(this, "space");
compiler.add(this, "node_normal_map");
}
/* Tangent */
-static ShaderEnum tangent_direction_type_init()
+NODE_DEFINE(TangentNode)
{
- ShaderEnum enm;
+ NodeType* type = NodeType::add("tangent", create, NodeType::SHADER);
- enm.insert("Radial", NODE_TANGENT_RADIAL);
- enm.insert("UV Map", NODE_TANGENT_UVMAP);
+ 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);
- return enm;
-}
+ 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 ShaderEnum tangent_axis_init()
-{
- ShaderEnum enm;
+ SOCKET_STRING(attribute, "Attribute", ustring(""));
- enm.insert("X", NODE_TANGENT_AXIS_X);
- enm.insert("Y", NODE_TANGENT_AXIS_Y);
- enm.insert("Z", NODE_TANGENT_AXIS_Z);
+ 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 enm;
+ return type;
}
-ShaderEnum TangentNode::direction_type_enum = tangent_direction_type_init();
-ShaderEnum TangentNode::axis_enum = tangent_axis_init();
-
TangentNode::TangentNode()
-: ShaderNode("tangent")
+: ShaderNode(node_type)
{
- direction_type = ustring("Radial");
- axis = ustring("X");
- attribute = ustring("");
-
- add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, ShaderInput::USE_OSL);
- add_output("Tangent", SHADER_SOCKET_NORMAL);
}
void TangentNode::attributes(Shader *shader, AttributeRequestSet *attributes)
{
if(shader->has_surface) {
- if(direction_type == ustring("UV Map")) {
+ if(direction_type == NODE_TANGENT_UVMAP) {
if(attribute == ustring(""))
attributes->add(ATTR_STD_UV_TANGENT);
else
@@ -4785,7 +5417,7 @@ void TangentNode::compile(SVMCompiler& compiler)
ShaderOutput *tangent_out = output("Tangent");
int attr;
- if(direction_type == ustring("UV Map")) {
+ if(direction_type == NODE_TANGENT_UVMAP) {
if(attribute == ustring(""))
attr = compiler.attribute(ATTR_STD_UV_TANGENT);
else
@@ -4797,21 +5429,21 @@ void TangentNode::compile(SVMCompiler& compiler)
compiler.add_node(NODE_TANGENT,
compiler.encode_uchar4(
compiler.stack_assign(tangent_out),
- direction_type_enum[direction_type],
- axis_enum[axis]), attr);
+ direction_type,
+ axis), attr);
}
void TangentNode::compile(OSLCompiler& compiler)
{
- if(direction_type == ustring("UV Map")) {
+ if(direction_type == NODE_TANGENT_UVMAP) {
if(attribute == ustring(""))
compiler.parameter("attr_name", ustring("geom:tangent"));
else
compiler.parameter("attr_name", ustring((string(attribute.c_str()) + ".tangent").c_str()));
}
- compiler.parameter("direction_type", direction_type);
- compiler.parameter("axis", axis);
+ compiler.parameter(this, "direction_type");
+ compiler.parameter(this, "axis");
compiler.add(this, "node_tangent");
}
diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h
index c0f0dc29099..6c2467d9bee 100644
--- a/intern/cycles/render/nodes.h
+++ b/intern/cycles/render/nodes.h
@@ -18,6 +18,7 @@
#define __NODES_H__
#include "graph.h"
+#include "node.h"
#include "util_string.h"
@@ -35,6 +36,7 @@ public:
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);
@@ -49,48 +51,26 @@ public:
enum Type { POINT = 0, TEXTURE = 1, VECTOR = 2, NORMAL = 3 };
Type type;
- static ShaderEnum type_enum;
enum Mapping { NONE = 0, X = 1, Y = 2, Z = 3 };
Mapping x_mapping, y_mapping, z_mapping;
- static ShaderEnum mapping_enum;
enum Projection { FLAT, CUBE, TUBE, SPHERE };
Projection projection;
- static ShaderEnum projection_enum;
-
- bool equals(const TextureMapping& other) {
- return translation == other.translation &&
- rotation == other.rotation &&
- scale == other.scale &&
- use_minmax == other.use_minmax &&
- min == other.min &&
- max == other.max &&
- type == other.type &&
- x_mapping == other.x_mapping &&
- y_mapping == other.y_mapping &&
- z_mapping == other.z_mapping &&
- projection == other.projection;
- }
};
/* Nodes */
class TextureNode : public ShaderNode {
public:
- explicit TextureNode(const char *name_) : ShaderNode(name_) {}
+ explicit TextureNode(const NodeType *node_type) : ShaderNode(node_type) {}
TextureMapping tex_mapping;
-
- virtual bool equals(const ShaderNode *other) {
- return ShaderNode::equals(other) &&
- tex_mapping.equals(((const TextureNode*)other)->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 char *name_) : TextureNode(name_) {
+ explicit ImageSlotTextureNode(const NodeType *node_type) : TextureNode(node_type) {
special_type = SHADER_SPECIAL_TYPE_IMAGE_SLOT;
}
int slot;
@@ -107,30 +87,22 @@ public:
int is_float;
bool is_linear;
bool use_alpha;
- string filename;
+ ustring filename;
void *builtin_data;
- ustring color_space;
- ustring projection;
+ NodeImageColorSpace color_space;
+ NodeImageProjection projection;
InterpolationType interpolation;
ExtensionType extension;
float projection_blend;
bool animated;
+ float3 vector;
- static ShaderEnum color_space_enum;
- static ShaderEnum projection_enum;
-
- virtual bool equals(const ShaderNode *other) {
- const ImageTextureNode *image_node = (const ImageTextureNode*)other;
+ virtual bool equals(const ShaderNode& other)
+ {
+ const ImageTextureNode& image_node = (const ImageTextureNode&)other;
return ImageSlotTextureNode::equals(other) &&
- use_alpha == image_node->use_alpha &&
- filename == image_node->filename &&
- builtin_data == image_node->builtin_data &&
- color_space == image_node->color_space &&
- projection == image_node->projection &&
- interpolation == image_node->interpolation &&
- extension == image_node->extension &&
- projection_blend == image_node->projection_blend &&
- animated == image_node->animated;
+ builtin_data == image_node.builtin_data &&
+ animated == image_node.animated;
}
};
@@ -146,26 +118,20 @@ public:
int is_float;
bool is_linear;
bool use_alpha;
- string filename;
+ ustring filename;
void *builtin_data;
- ustring color_space;
- ustring projection;
+ NodeImageColorSpace color_space;
+ NodeEnvironmentProjection projection;
InterpolationType interpolation;
bool animated;
+ float3 vector;
- static ShaderEnum color_space_enum;
- static ShaderEnum projection_enum;
-
- virtual bool equals(const ShaderNode *other) {
- const EnvironmentTextureNode *env_node = (const EnvironmentTextureNode*)other;
+ virtual bool equals(const ShaderNode& other)
+ {
+ const EnvironmentTextureNode& env_node = (const EnvironmentTextureNode&)other;
return ImageSlotTextureNode::equals(other) &&
- use_alpha == env_node->use_alpha &&
- filename == env_node->filename &&
- builtin_data == env_node->builtin_data &&
- color_space == env_node->color_space &&
- projection == env_node->projection &&
- interpolation == env_node->interpolation &&
- animated == env_node->animated;
+ builtin_data == env_node.builtin_data &&
+ animated == env_node.animated;
}
};
@@ -175,29 +141,24 @@ public:
virtual int get_group() { return NODE_GROUP_LEVEL_2; }
+ NodeSkyType type;
float3 sun_direction;
float turbidity;
float ground_albedo;
-
- ustring type;
- static ShaderEnum type_enum;
-
- virtual bool equals(const ShaderNode *other) {
- const SkyTextureNode *sky_node = (const SkyTextureNode*)other;
- return TextureNode::equals(other) &&
- sun_direction == sky_node->sun_direction &&
- turbidity == sky_node->turbidity &&
- ground_albedo == sky_node->ground_albedo &&
- type == sky_node->type;
- }
+ float3 vector;
};
class OutputNode : public ShaderNode {
public:
SHADER_NODE_CLASS(OutputNode)
+ void *surface;
+ void *volume;
+ float displacement;
+ float3 normal;
+
/* Don't allow output node de-duplication. */
- virtual bool equals(const ShaderNode * /*other*/) { return false; }
+ virtual bool equals(const ShaderNode& /*other*/) { return false; }
};
class GradientTextureNode : public TextureNode {
@@ -206,19 +167,16 @@ public:
virtual int get_group() { return NODE_GROUP_LEVEL_2; }
- ustring type;
- static ShaderEnum type_enum;
-
- virtual bool equals(const ShaderNode *other) {
- const GradientTextureNode *gradient_node = (const GradientTextureNode*)other;
- return TextureNode::equals(other) &&
- type == gradient_node->type;
- }
+ NodeGradientType type;
+ float3 vector;
};
class NoiseTextureNode : public TextureNode {
public:
SHADER_NODE_CLASS(NoiseTextureNode)
+
+ float scale, detail, distortion;
+ float3 vector;
};
class VoronoiTextureNode : public TextureNode {
@@ -227,15 +185,9 @@ public:
virtual int get_group() { return NODE_GROUP_LEVEL_2; }
- ustring coloring;
-
- static ShaderEnum coloring_enum;
-
- virtual bool equals(const ShaderNode *other) {
- const VoronoiTextureNode *voronoi_node = (const VoronoiTextureNode*)other;
- return TextureNode::equals(other) &&
- coloring == voronoi_node->coloring;
- }
+ NodeVoronoiColoring coloring;
+ float scale;
+ float3 vector;
};
class MusgraveTextureNode : public TextureNode {
@@ -244,15 +196,9 @@ public:
virtual int get_group() { return NODE_GROUP_LEVEL_2; }
- ustring type;
-
- static ShaderEnum type_enum;
-
- virtual bool equals(const ShaderNode *other) {
- const MusgraveTextureNode *musgrave_node = (const MusgraveTextureNode*)other;
- return TextureNode::equals(other) &&
- type == musgrave_node->type;
- }
+ NodeMusgraveType type;
+ float scale, detail, dimension, lacunarity, offset, gain;
+ float3 vector;
};
class WaveTextureNode : public TextureNode {
@@ -261,17 +207,11 @@ public:
virtual int get_group() { return NODE_GROUP_LEVEL_2; }
- ustring type;
- ustring profile;
- static ShaderEnum type_enum;
- static ShaderEnum profile_enum;
+ NodeWaveType type;
+ NodeWaveProfile profile;
- virtual bool equals(const ShaderNode *other) {
- const WaveTextureNode *wave_node = (const WaveTextureNode*)other;
- return TextureNode::equals(other) &&
- type == wave_node->type &&
- profile == wave_node->profile;
- }
+ float scale, distortion, detail, detail_scale;
+ float3 vector;
};
class MagicTextureNode : public TextureNode {
@@ -281,18 +221,17 @@ public:
virtual int get_group() { return NODE_GROUP_LEVEL_2; }
int depth;
-
- virtual bool equals(const ShaderNode *other) {
- const MagicTextureNode *magic_node = (const MagicTextureNode*)other;
- return TextureNode::equals(other) &&
- depth == magic_node->depth;
- }
+ float3 vector;
+ float scale, distortion;
};
class CheckerTextureNode : public TextureNode {
public:
SHADER_NODE_CLASS(CheckerTextureNode)
+ float3 vector, color1, color2;
+ float scale;
+
virtual int get_group() { return NODE_GROUP_LEVEL_2; }
};
@@ -303,16 +242,11 @@ public:
float offset, squash;
int offset_frequency, squash_frequency;
- virtual int get_group() { return NODE_GROUP_LEVEL_2; }
+ float3 color1, color2, mortar;
+ float scale, mortar_size, bias, brick_width, row_height;
+ float3 vector;
- virtual bool equals(const ShaderNode *other) {
- const BrickTextureNode *brick_node = (const BrickTextureNode*)other;
- return TextureNode::equals(other) &&
- offset == brick_node->offset &&
- squash == brick_node->squash &&
- offset_frequency == brick_node->offset_frequency &&
- squash_frequency == brick_node->squash_frequency;
- }
+ virtual int get_group() { return NODE_GROUP_LEVEL_2; }
};
class PointDensityTextureNode : public ShaderNode {
@@ -326,25 +260,20 @@ public:
bool has_spatial_varying() { return true; }
bool has_object_dependency() { return true; }
- ImageManager *image_manager;
- int slot;
- string filename;
- ustring space;
- void *builtin_data;
+ ustring filename;
+ NodeTexVoxelSpace space;
InterpolationType interpolation;
-
Transform tfm;
+ float3 vector;
- static ShaderEnum space_enum;
+ ImageManager *image_manager;
+ int slot;
+ void *builtin_data;
- virtual bool equals(const ShaderNode *other) {
- const PointDensityTextureNode *point_dendity_node = (const PointDensityTextureNode*)other;
+ virtual bool equals(const ShaderNode& other) {
+ const PointDensityTextureNode& point_dendity_node = (const PointDensityTextureNode&)other;
return ShaderNode::equals(other) &&
- filename == point_dendity_node->filename &&
- space == point_dendity_node->space &&
- builtin_data == point_dendity_node->builtin_data &&
- interpolation == point_dendity_node->interpolation &&
- tfm == point_dendity_node->tfm;
+ builtin_data == point_dendity_node.builtin_data;
}
};
@@ -353,46 +282,60 @@ public:
SHADER_NODE_CLASS(MappingNode)
virtual int get_group() { return NODE_GROUP_LEVEL_2; }
+ float3 vector;
TextureMapping tex_mapping;
+};
- virtual bool equals(const ShaderNode *other) {
- const MappingNode *mapping_node = (const MappingNode*)other;
- return ShaderNode::equals(other) &&
- tex_mapping.equals(mapping_node->tex_mapping);
- }
+class RGBToBWNode : public ShaderNode {
+public:
+ SHADER_NODE_CLASS(RGBToBWNode)
+ void constant_fold(const ConstantFolder& folder);
+
+ float3 color;
};
class ConvertNode : public ShaderNode {
public:
- ConvertNode(ShaderSocketType from, ShaderSocketType to, bool autoconvert = false);
+ ConvertNode(SocketType::Type from, SocketType::Type to, bool autoconvert = false);
SHADER_NODE_BASE_CLASS(ConvertNode)
- bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, float3 *optimized_value);
+ void constant_fold(const ConstantFolder& folder);
- ShaderSocketType from, to;
+ SocketType::Type from, to;
- virtual bool equals(const ShaderNode *other)
- {
- const ConvertNode *convert_node = (const ConvertNode*)other;
- return ShaderNode::equals(other) &&
- from == convert_node->from &&
- to == convert_node->to;
- }
+ 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;
};
class BsdfNode : public ShaderNode {
public:
- explicit BsdfNode(bool scattering = false);
+ explicit BsdfNode(const NodeType *node_type);
SHADER_NODE_BASE_CLASS(BsdfNode);
bool has_spatial_varying() { return true; }
void compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *param2, ShaderInput *param3 = NULL, ShaderInput *param4 = NULL);
virtual ClosureType get_closure_type() { return closure; }
+ float3 color;
+ float3 normal;
+ float surface_mix_weight;
ClosureType closure;
- bool scattering;
- virtual bool equals(const ShaderNode * /*other*/)
+ virtual bool equals(const ShaderNode& /*other*/)
{
/* TODO(sergey): With some care BSDF nodes can be de-duplicated. */
return false;
@@ -403,15 +346,19 @@ class AnisotropicBsdfNode : public BsdfNode {
public:
SHADER_NODE_CLASS(AnisotropicBsdfNode)
- ustring distribution;
- static ShaderEnum distribution_enum;
+ float3 tangent;
+ float roughness, anisotropy, rotation;
+ ClosureType distribution;
+ ClosureType get_closure_type() { return distribution; }
void attributes(Shader *shader, AttributeRequestSet *attributes);
};
class DiffuseBsdfNode : public BsdfNode {
public:
SHADER_NODE_CLASS(DiffuseBsdfNode)
+
+ float roughness;
};
/* Disney BRDF */
@@ -427,6 +374,12 @@ public:
ShaderInput *sheen, ShaderInput *sheenTint, ShaderInput *clearcoat, ShaderInput *clearcoatGloss,
ShaderInput *ior, ShaderInput *transparency, ShaderInput *refr_roughness);
+ float3 base_color;
+ float3 subsurface_color;
+ float metallic, subsurface, specular, roughness, specularTint, anisotropic,
+ sheen, sheenTint, clearcoat, clearcoatGloss, ior, transparency, refractionRoughness;
+ float3 normal, clearcoatNormal, tangent;
+ float surface_mix_weight;
ClosureType closure;
virtual bool equals(const ShaderNode * /*other*/)
@@ -451,6 +404,8 @@ public:
class VelvetBsdfNode : public BsdfNode {
public:
SHADER_NODE_CLASS(VelvetBsdfNode)
+
+ float sigma;
};
class GlossyBsdfNode : public BsdfNode {
@@ -459,9 +414,10 @@ public:
void simplify_settings(Scene *scene);
bool has_integrator_dependency();
+ ClosureType get_closure_type() { return distribution; }
- ustring distribution, distribution_orig;
- static ShaderEnum distribution_enum;
+ float roughness;
+ ClosureType distribution, distribution_orig;
};
class GlassBsdfNode : public BsdfNode {
@@ -470,9 +426,10 @@ public:
void simplify_settings(Scene *scene);
bool has_integrator_dependency();
+ ClosureType get_closure_type() { return distribution; }
- ustring distribution, distribution_orig;
- static ShaderEnum distribution_enum;
+ float roughness, IOR;
+ ClosureType distribution, distribution_orig;
};
class RefractionBsdfNode : public BsdfNode {
@@ -481,17 +438,18 @@ public:
void simplify_settings(Scene *scene);
bool has_integrator_dependency();
+ ClosureType get_closure_type() { return distribution; }
- ustring distribution, distribution_orig;
- static ShaderEnum distribution_enum;
+ float roughness, IOR;
+ ClosureType distribution, distribution_orig;
};
class ToonBsdfNode : public BsdfNode {
public:
SHADER_NODE_CLASS(ToonBsdfNode)
- ustring component;
- static ShaderEnum component_enum;
+ float smooth, size;
+ ClosureType component;
};
class SubsurfaceScatteringNode : public BsdfNode {
@@ -499,24 +457,37 @@ public:
SHADER_NODE_CLASS(SubsurfaceScatteringNode)
bool has_surface_bssrdf() { return true; }
bool has_bssrdf_bump();
+ ClosureType get_closure_type() { return falloff; }
- static ShaderEnum falloff_enum;
+ float scale;
+ float3 radius;
+ float sharpness;
+ float texture_blur;
+ ClosureType falloff;
};
class EmissionNode : public ShaderNode {
public:
SHADER_NODE_CLASS(EmissionNode)
- bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, float3 *optimized_value);
+ void constant_fold(const ConstantFolder& folder);
virtual ClosureType get_closure_type() { return CLOSURE_EMISSION_ID; }
bool has_surface_emission() { return true; }
+
+ float3 color;
+ float strength;
+ float surface_mix_weight;
};
class BackgroundNode : public ShaderNode {
public:
SHADER_NODE_CLASS(BackgroundNode)
- bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, float3 *optimized_value);
+ void constant_fold(const ConstantFolder& folder);
virtual ClosureType get_closure_type() { return CLOSURE_BACKGROUND_ID; }
+
+ float3 color;
+ float strength;
+ float surface_mix_weight;
};
class HoldoutNode : public ShaderNode {
@@ -524,6 +495,9 @@ 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;
};
class AmbientOcclusionNode : public ShaderNode {
@@ -533,11 +507,16 @@ public:
bool has_spatial_varying() { return true; }
virtual int get_group() { return NODE_GROUP_LEVEL_1; }
virtual ClosureType get_closure_type() { return CLOSURE_AMBIENT_OCCLUSION_ID; }
+
+ float3 normal_osl;
+ float3 color;
+ float surface_mix_weight;
};
class VolumeNode : public ShaderNode {
public:
- SHADER_NODE_CLASS(VolumeNode)
+ 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; }
@@ -546,9 +525,12 @@ public:
}
virtual ClosureType get_closure_type() { return closure; }
+ float3 color;
+ float density;
+ float volume_mix_weight;
ClosureType closure;
- virtual bool equals(const ShaderNode * /*other*/)
+ virtual bool equals(const ShaderNode& /*other*/)
{
/* TODO(sergey): With some care Volume nodes can be de-duplicated. */
return false;
@@ -563,15 +545,20 @@ public:
class ScatterVolumeNode : public VolumeNode {
public:
SHADER_NODE_CLASS(ScatterVolumeNode)
+
+ float anisotropy;
};
class HairBsdfNode : public BsdfNode {
public:
SHADER_NODE_CLASS(HairBsdfNode)
+ ClosureType get_closure_type() { return component; }
- ustring component;
- static ShaderEnum component_enum;
-
+ ClosureType component;
+ float offset;
+ float roughness_u;
+ float roughness_v;
+ float3 tangent;
};
class GeometryNode : public ShaderNode {
@@ -579,6 +566,8 @@ public:
SHADER_NODE_CLASS(GeometryNode)
void attributes(Shader *shader, AttributeRequestSet *attributes);
bool has_spatial_varying() { return true; }
+
+ float3 normal_osl;
};
class TextureCoordinateNode : public ShaderNode {
@@ -588,17 +577,10 @@ public:
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;
-
- virtual bool equals(const ShaderNode *other) {
- const TextureCoordinateNode *texco_node = (const TextureCoordinateNode*)other;
- return ShaderNode::equals(other) &&
- from_dupli == texco_node->from_dupli &&
- use_transform == texco_node->use_transform &&
- ob_tfm == texco_node->ob_tfm;
- }
};
class UVMapNode : public ShaderNode {
@@ -610,13 +592,6 @@ public:
ustring attribute;
bool from_dupli;
-
- virtual bool equals(const ShaderNode *other) {
- const UVMapNode *uv_map_node = (const UVMapNode*)other;
- return ShaderNode::equals(other) &&
- attribute == uv_map_node->attribute &&
- from_dupli == uv_map_node->from_dupli;
- }
};
class LightPathNode : public ShaderNode {
@@ -630,6 +605,9 @@ public:
SHADER_NODE_CLASS(LightFalloffNode)
bool has_spatial_varying() { return true; }
virtual int get_group() { return NODE_GROUP_LEVEL_2; }
+
+ float strength;
+ float smooth;
};
class ObjectInfoNode : public ShaderNode {
@@ -661,136 +639,150 @@ class ValueNode : public ShaderNode {
public:
SHADER_NODE_CLASS(ValueNode)
- bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, float3 *optimized_value);
+ void constant_fold(const ConstantFolder& folder);
float value;
-
- virtual bool equals(const ShaderNode *other) {
- const ValueNode *value_node = (const ValueNode*)other;
- return ShaderNode::equals(other) &&
- value == value_node->value;
- }
};
class ColorNode : public ShaderNode {
public:
SHADER_NODE_CLASS(ColorNode)
- bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, float3 *optimized_value);
+ void constant_fold(const ConstantFolder& folder);
float3 value;
-
- virtual bool equals(const ShaderNode *other) {
- const ColorNode *color_node = (const ColorNode*)other;
- return ShaderNode::equals(other) &&
- value == color_node->value;
- }
};
class AddClosureNode : public ShaderNode {
public:
SHADER_NODE_CLASS(AddClosureNode)
+ void constant_fold(const ConstantFolder& folder);
};
class MixClosureNode : public ShaderNode {
public:
SHADER_NODE_CLASS(MixClosureNode)
- bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, float3 *optimized_value);
+ void constant_fold(const ConstantFolder& folder);
+
+ float fac;
};
class MixClosureWeightNode : public ShaderNode {
public:
SHADER_NODE_CLASS(MixClosureWeightNode);
+
+ 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; }
+
+ float fac;
+ float3 color;
};
class MixNode : public ShaderNode {
public:
SHADER_NODE_CLASS(MixNode)
- bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, float3 *optimized_value);
+ void constant_fold(const ConstantFolder& folder);
virtual int get_group() { return NODE_GROUP_LEVEL_3; }
+ NodeMix type;
bool use_clamp;
-
- ustring type;
- static ShaderEnum type_enum;
-
- virtual bool equals(const ShaderNode *other)
- {
- const MixNode *mix_node = (const MixNode*)other;
- return ShaderNode::equals(other) &&
- use_clamp == mix_node->use_clamp &&
- type == mix_node->type;
- }
+ 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; }
+
+ 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; }
+
+ 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; }
+
+ float x, y, z;
};
class GammaNode : public ShaderNode {
public:
SHADER_NODE_CLASS(GammaNode)
-
- bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, float3 *optimized_value);
-
+ void constant_fold(const ConstantFolder& folder);
virtual int get_group() { return NODE_GROUP_LEVEL_1; }
+
+ 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; }
+
+ 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; }
+
+ 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; }
+
+ 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; }
+
+ float3 vector;
};
class HSVNode : public ShaderNode {
public:
SHADER_NODE_CLASS(HSVNode)
+
+ float hue;
+ float saturation;
+ float value;
+ float fac;
+ float3 color;
};
class AttributeNode : public ShaderNode {
@@ -800,12 +792,6 @@ public:
bool has_spatial_varying() { return true; }
ustring attribute;
-
- virtual bool equals(const ShaderNode *other) {
- const AttributeNode *color_node = (const AttributeNode*)other;
- return ShaderNode::equals(other) &&
- attribute == color_node->attribute;
- }
};
class CameraNode : public ShaderNode {
@@ -819,6 +805,9 @@ public:
SHADER_NODE_CLASS(FresnelNode)
bool has_spatial_varying() { return true; }
virtual int get_group() { return NODE_GROUP_LEVEL_1; }
+
+ float3 normal;
+ float IOR;
};
class LayerWeightNode : public ShaderNode {
@@ -826,6 +815,9 @@ public:
SHADER_NODE_CLASS(LayerWeightNode)
bool has_spatial_varying() { return true; }
virtual int get_group() { return NODE_GROUP_LEVEL_1; }
+
+ float3 normal;
+ float blend;
};
class WireframeNode : public ShaderNode {
@@ -834,42 +826,37 @@ public:
bool has_spatial_varying() { return true; }
virtual int get_group() { return NODE_GROUP_LEVEL_3; }
+ float size;
bool use_pixel_size;
};
class WavelengthNode : public ShaderNode {
public:
SHADER_NODE_CLASS(WavelengthNode)
-
virtual int get_group() { return NODE_GROUP_LEVEL_3; }
+
+ float wavelength;
};
class BlackbodyNode : public ShaderNode {
public:
SHADER_NODE_CLASS(BlackbodyNode)
- bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, float3 *optimized_value);
-
+ void constant_fold(const ConstantFolder& folder);
virtual int get_group() { return NODE_GROUP_LEVEL_3; }
+
+ float temperature;
};
class MathNode : public ShaderNode {
public:
SHADER_NODE_CLASS(MathNode)
virtual int get_group() { return NODE_GROUP_LEVEL_1; }
- bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, float3 *optimized_value);
+ void constant_fold(const ConstantFolder& folder);
+ float value1;
+ float value2;
+ NodeMath type;
bool use_clamp;
-
- ustring type;
- static ShaderEnum type_enum;
-
- virtual bool equals(const ShaderNode *other)
- {
- const MathNode *math_node = (const MathNode*)other;
- return ShaderNode::equals(other) &&
- use_clamp == math_node->use_clamp &&
- type == math_node->type;
- }
};
class NormalNode : public ShaderNode {
@@ -878,30 +865,18 @@ public:
virtual int get_group() { return NODE_GROUP_LEVEL_2; }
float3 direction;
-
- virtual bool equals(const ShaderNode *other)
- {
- const NormalNode *normal_node = (const NormalNode*)other;
- return ShaderNode::equals(other) &&
- direction == normal_node->direction;
- }
+ float3 normal;
};
class VectorMathNode : public ShaderNode {
public:
SHADER_NODE_CLASS(VectorMathNode)
virtual int get_group() { return NODE_GROUP_LEVEL_1; }
- bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, float3 *optimized_value);
+ void constant_fold(const ConstantFolder& folder);
- ustring type;
- static ShaderEnum type_enum;
-
- virtual bool equals(const ShaderNode *other)
- {
- const MathNode *math_node = (const MathNode*)other;
- return ShaderNode::equals(other) &&
- type == math_node->type;
- }
+ float3 vector1;
+ float3 vector2;
+ NodeVectorMath type;
};
class VectorTransformNode : public ShaderNode {
@@ -910,88 +885,97 @@ public:
virtual int get_group() { return NODE_GROUP_LEVEL_3; }
- ustring type;
- ustring convert_from;
- ustring convert_to;
-
- static ShaderEnum type_enum;
- static ShaderEnum convert_space_enum;
-
- virtual bool equals(const ShaderNode *other) {
- const VectorTransformNode *vector_transform_node = (const VectorTransformNode*)other;
- return ShaderNode::equals(other) &&
- type == vector_transform_node->type &&
- convert_from == vector_transform_node->convert_from &&
- convert_to == vector_transform_node->convert_to;
- }
+ NodeVectorTransformType type;
+ NodeVectorTransformConvertSpace convert_from;
+ NodeVectorTransformConvertSpace convert_to;
+ float3 vector;
};
class BumpNode : public ShaderNode {
public:
SHADER_NODE_CLASS(BumpNode)
- bool constant_fold(ShaderGraph *graph, ShaderOutput *socket, float3 *optimized_value);
+ void constant_fold(const ConstantFolder& folder);
bool has_spatial_varying() { return true; }
virtual int get_feature() {
return NODE_FEATURE_BUMP;
}
bool invert;
-
- virtual bool equals(const ShaderNode *other) {
- const BumpNode *bump_node = (const BumpNode*)other;
- return ShaderNode::equals(other) &&
- invert == bump_node->invert;
- }
+ float height;
+ float sample_center;
+ float sample_x;
+ float sample_y;
+ float3 normal;
+ float strength;
+ float distance;
};
-class RGBCurvesNode : public ShaderNode {
+class CurvesNode : public ShaderNode {
public:
- SHADER_NODE_CLASS(RGBCurvesNode)
+ explicit CurvesNode(const NodeType *node_type);
+ SHADER_NODE_BASE_CLASS(CurvesNode);
virtual int get_group() { return NODE_GROUP_LEVEL_3; }
- virtual bool equals(const ShaderNode * /*other*/) { return false; }
array<float3> curves;
- float min_x, max_x;
+ float min_x, max_x, fac;
+ float3 value;
+
+protected:
+ 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 VectorCurvesNode : public ShaderNode {
+class RGBCurvesNode : public CurvesNode {
public:
- SHADER_NODE_CLASS(VectorCurvesNode)
-
- virtual int get_group() { return NODE_GROUP_LEVEL_3; }
- virtual bool equals(const ShaderNode * /*other*/) { return false; }
+ SHADER_NODE_CLASS(RGBCurvesNode)
+ void constant_fold(const ConstantFolder& folder);
+};
- array<float3> curves;
- float min_x, max_x;
+class VectorCurvesNode : public CurvesNode {
+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; }
+
array<float3> ramp;
array<float> ramp_alpha;
+ float fac;
bool interpolate;
- virtual int get_group() { return NODE_GROUP_LEVEL_1; }
- virtual bool equals(const ShaderNode * /*other*/) { return false; }
};
class SetNormalNode : public ShaderNode {
public:
SHADER_NODE_CLASS(SetNormalNode)
+ float3 direction;
};
-class OSLScriptNode : public ShaderNode {
+class OSLNode : public ShaderNode {
public:
- SHADER_NODE_CLASS(OSLScriptNode)
+ static OSLNode *create(size_t num_inputs, const OSLNode *from = NULL);
+ ~OSLNode();
+
+ ShaderNode *clone() const;
+
+ 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)
/* ideally we could beter detect this, but we can't query this now */
bool has_spatial_varying() { return true; }
+ virtual bool equals(const ShaderNode& /*other*/) { return false; }
string filepath;
string bytecode_hash;
-
- virtual bool equals(const ShaderNode * /*other*/) { return false; }
};
class NormalMapNode : public ShaderNode {
@@ -1001,18 +985,11 @@ public:
bool has_spatial_varying() { return true; }
virtual int get_group() { return NODE_GROUP_LEVEL_3; }
- ustring space;
- static ShaderEnum space_enum;
-
+ NodeNormalMapSpace space;
ustring attribute;
-
- virtual bool equals(const ShaderNode *other)
- {
- const NormalMapNode *normal_map_node = (const NormalMapNode*)other;
- return ShaderNode::equals(other) &&
- space == normal_map_node->space &&
- attribute == normal_map_node->attribute;
- }
+ float strength;
+ float3 color;
+ float3 normal_osl;
};
class TangentNode : public ShaderNode {
@@ -1022,22 +999,10 @@ public:
bool has_spatial_varying() { return true; }
virtual int get_group() { return NODE_GROUP_LEVEL_3; }
- ustring direction_type;
- static ShaderEnum direction_type_enum;
-
- ustring axis;
- static ShaderEnum axis_enum;
-
+ NodeTangentDirectionType direction_type;
+ NodeTangentAxis axis;
ustring attribute;
-
- virtual bool equals(const ShaderNode *other)
- {
- const TangentNode *tangent_node = (const TangentNode*)other;
- return ShaderNode::equals(other) &&
- direction_type == tangent_node->direction_type &&
- axis == tangent_node->axis &&
- attribute == tangent_node->attribute;
- }
+ float3 normal_osl;
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp
index e2fe0bd72a1..662d87e8b6b 100644
--- a/intern/cycles/render/object.cpp
+++ b/intern/cycles/render/object.cpp
@@ -33,14 +33,25 @@ CCL_NAMESPACE_BEGIN
/* 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_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));
+
+ return type;
+}
+
Object::Object()
+: Node(node_type)
{
- name = "";
- mesh = NULL;
- tfm = transform_identity();
- visibility = ~0;
- random_id = 0;
- pass_id = 0;
particle_system = NULL;
particle_index = 0;
bounds = BoundBox::empty;
@@ -48,9 +59,6 @@ Object::Object()
motion.mid = transform_identity();
motion.post = transform_identity();
use_motion = false;
- use_holdout = false;
- dupli_generated = make_float3(0.0f, 0.0f, 0.0f);
- dupli_uv = make_float2(0.0f, 0.0f);
}
Object::~Object()
@@ -137,12 +145,12 @@ void Object::apply_transform(bool apply_to_motion)
/* apply transform to curve keys */
for(size_t i = 0; i < mesh->curve_keys.size(); i++) {
- float3 co = transform_point(&tfm, float4_to_float3(mesh->curve_keys[i]));
- float radius = mesh->curve_keys[i].w * scalar;
+ 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] = float3_to_float4(co);
- mesh->curve_keys[i].w = radius;
+ mesh->curve_keys[i] = co;
+ mesh->curve_radius[i] = radius;
}
if(apply_to_motion) {
@@ -176,7 +184,7 @@ void Object::apply_transform(bool apply_to_motion)
}
/* tfm is not reset to identity, all code that uses it needs to check the
- transform_applied boolean */
+ * transform_applied boolean */
}
void Object::tag_update(Scene *scene)
@@ -217,6 +225,16 @@ vector<float> Object::motion_times()
return times;
}
+bool Object::is_traceable()
+{
+ /* Mesh itself can be empty,can skip all such objects. */
+ if (bounds.size() == make_float3(0.0f, 0.0f, 0.0f)) {
+ return false;
+ }
+ /* TODO(sergey): Check for mesh vertices/curves. visibility flags. */
+ return true;
+}
+
/* Object Manager */
ObjectManager::ObjectManager()
@@ -269,7 +287,9 @@ void ObjectManager::device_update_object_transform(UpdateObejctTransformState *s
state->surface_area_lock.unlock();
if(it == state->surface_area_map.end()) {
- foreach(Mesh::Triangle& t, mesh->triangles) {
+ 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]];
@@ -288,7 +308,9 @@ void ObjectManager::device_update_object_transform(UpdateObejctTransformState *s
surface_area *= uniform_scale;
}
else {
- foreach(Mesh::Triangle& t, mesh->triangles) {
+ 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]]);
@@ -360,7 +382,7 @@ void ObjectManager::device_update_object_transform(UpdateObejctTransformState *s
state->object_flag[object_index] = flag;
/* Have curves. */
- if(mesh->curves.size()) {
+ if(mesh->num_curves()) {
state->have_curves = true;
}
}
diff --git a/intern/cycles/render/object.h b/intern/cycles/render/object.h
index c2a79ca8dc4..7ab73f3c91a 100644
--- a/intern/cycles/render/object.h
+++ b/intern/cycles/render/object.h
@@ -17,6 +17,7 @@
#ifndef __OBJECT_H__
#define __OBJECT_H__
+#include "node.h"
#include "scene.h"
#include "util_boundbox.h"
@@ -37,12 +38,13 @@ struct Transform;
/* Object */
-class Object {
+class Object : public Node {
public:
+ NODE_DECLARE;
+
Mesh *mesh;
Transform tfm;
BoundBox bounds;
- ustring name;
uint random_id;
int pass_id;
vector<ParamValue> attributes;
@@ -66,6 +68,11 @@ public:
void apply_transform(bool apply_to_motion);
vector<float> motion_times();
+
+ /* Check whether object is traceable and it worth adding it to
+ * kernel scene.
+ */
+ bool is_traceable();
};
/* Object Manager */
diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp
index 3d14965b4ca..676afad997e 100644
--- a/intern/cycles/render/osl.cpp
+++ b/intern/cycles/render/osl.cpp
@@ -394,16 +394,145 @@ const char *OSLShaderManager::shader_load_bytecode(const string& hash, const str
{
ss->LoadMemoryCompiledShader(hash.c_str(), bytecode.c_str());
- /* this is a bit weak, but works */
OSLShaderInfo info;
+
+ 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);
+
loaded_shaders[hash] = info;
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)
+{
+ /* 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_, ImageManager *image_manager_)
@@ -427,7 +556,7 @@ string OSLCompiler::id(ShaderNode *node)
string OSLCompiler::compatible_name(ShaderNode *node, ShaderInput *input)
{
- string sname(input->name);
+ string sname(input->name().string());
size_t i;
/* strip whitespace */
@@ -436,7 +565,7 @@ string OSLCompiler::compatible_name(ShaderNode *node, ShaderInput *input)
/* if output exists with the same name, add "In" suffix */
foreach(ShaderOutput *output, node->outputs) {
- if(strcmp(input->name, output->name)==0) {
+ if(input->name() == output->name()) {
sname += "In";
break;
}
@@ -447,7 +576,7 @@ string OSLCompiler::compatible_name(ShaderNode *node, ShaderInput *input)
string OSLCompiler::compatible_name(ShaderNode *node, ShaderOutput *output)
{
- string sname(output->name);
+ string sname(output->name().string());
size_t i;
/* strip whitespace */
@@ -456,7 +585,7 @@ string OSLCompiler::compatible_name(ShaderNode *node, ShaderOutput *output)
/* if input exists with the same name, add "Out" suffix */
foreach(ShaderInput *input, node->inputs) {
- if(strcmp(input->name, output->name)==0) {
+ if(input->name() == output->name()) {
sname += "Out";
break;
}
@@ -470,21 +599,21 @@ 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->usage & ShaderInput::USE_OSL))
+ if(input->flags() & SocketType::SVM_INTERNAL)
return true;
if(node->special_type == SHADER_SPECIAL_TYPE_OUTPUT) {
- if(strcmp(input->name, "Surface") == 0 && current_type != SHADER_TYPE_SURFACE)
+ if(input->name() == "Surface" && current_type != SHADER_TYPE_SURFACE)
return true;
- if(strcmp(input->name, "Volume") == 0 && current_type != SHADER_TYPE_VOLUME)
+ if(input->name() == "Volume" && current_type != SHADER_TYPE_VOLUME)
return true;
- if(strcmp(input->name, "Displacement") == 0 && current_type != SHADER_TYPE_DISPLACEMENT)
+ if(input->name() == "Displacement" && current_type != SHADER_TYPE_DISPLACEMENT)
return true;
- if(strcmp(input->name, "Normal") == 0)
+ if(input->name() == "Normal")
return true;
}
else if(node->special_type == SHADER_SPECIAL_TYPE_BUMP) {
- if(strcmp(input->name, "Height") == 0)
+ if(input->name() == "Height")
return true;
}
else if(current_type == SHADER_TYPE_DISPLACEMENT && input->link && input->link->parent->special_type == SHADER_SPECIAL_TYPE_BUMP)
@@ -512,34 +641,36 @@ void OSLCompiler::add(ShaderNode *node, const char *name, bool isfilepath)
if(node_skip_input(node, input))
continue;
/* already has default value assigned */
- else if(input->default_value != ShaderInput::NONE)
+ else if(input->flags() & SocketType::DEFAULT_LINK_MASK)
continue;
string param_name = compatible_name(node, input);
- switch(input->type) {
- case SHADER_SOCKET_COLOR:
- parameter_color(param_name.c_str(), input->value);
+ const SocketType& socket = input->socket_type;
+ switch(input->type()) {
+ case SocketType::COLOR:
+ parameter_color(param_name.c_str(), node->get_float3(socket));
break;
- case SHADER_SOCKET_POINT:
- parameter_point(param_name.c_str(), input->value);
+ case SocketType::POINT:
+ parameter_point(param_name.c_str(), node->get_float3(socket));
break;
- case SHADER_SOCKET_VECTOR:
- parameter_vector(param_name.c_str(), input->value);
+ case SocketType::VECTOR:
+ parameter_vector(param_name.c_str(), node->get_float3(socket));
break;
- case SHADER_SOCKET_NORMAL:
- parameter_normal(param_name.c_str(), input->value);
+ case SocketType::NORMAL:
+ parameter_normal(param_name.c_str(), node->get_float3(socket));
break;
- case SHADER_SOCKET_FLOAT:
- parameter(param_name.c_str(), input->value.x);
+ case SocketType::FLOAT:
+ parameter(param_name.c_str(), node->get_float(socket));
break;
- case SHADER_SOCKET_INT:
- parameter(param_name.c_str(), (int)input->value.x);
+ case SocketType::INT:
+ parameter(param_name.c_str(), node->get_int(socket));
break;
- case SHADER_SOCKET_STRING:
- parameter(param_name.c_str(), input->value_string);
+ case SocketType::STRING:
+ parameter(param_name.c_str(), node->get_string(socket));
break;
- case SHADER_SOCKET_CLOSURE:
- case SHADER_SOCKET_UNDEFINED:
+ case SocketType::CLOSURE:
+ case SocketType::UNDEFINED:
+ default:
break;
}
}
@@ -605,6 +736,169 @@ void OSLCompiler::add(ShaderNode *node, const char *name, bool isfilepath)
}
}
+static TypeDesc array_typedesc(TypeDesc typedesc, int arraylength)
+{
+ return TypeDesc((TypeDesc::BASETYPE)typedesc.basetype,
+ (TypeDesc::AGGREGATE)typedesc.aggregate,
+ (TypeDesc::VECSEMANTICS)typedesc.vecsemantics,
+ arraylength);
+}
+
+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);
+ ss->Parameter(uname, TypeDesc::TypeMatrix, &value);
+ 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);
+ ss->Parameter(uname, array_typedesc(TypeDesc::TypeMatrix, value.size()), value.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;
@@ -868,6 +1162,10 @@ void OSLCompiler::add(ShaderNode * /*node*/, const char * /*name*/, bool /*isfil
{
}
+void OSLCompiler::parameter(ShaderNode * /*node*/, const char * /*name*/)
+{
+}
+
void OSLCompiler::parameter(const char * /*name*/, float /*f*/)
{
}
diff --git a/intern/cycles/render/osl.h b/intern/cycles/render/osl.h
index 110897ff300..b131b672b8c 100644
--- a/intern/cycles/render/osl.h
+++ b/intern/cycles/render/osl.h
@@ -22,6 +22,7 @@
#include "util_thread.h"
#include "graph.h"
+#include "nodes.h"
#include "shader.h"
#ifdef WITH_OSL
@@ -54,6 +55,7 @@ struct OSLShaderInfo {
has_surface_bssrdf(false)
{}
+ OSL::OSLQuery query;
bool has_surface_emission;
bool has_surface_transparent;
bool has_surface_bssrdf;
@@ -83,6 +85,11 @@ public:
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();
@@ -118,6 +125,8 @@ public:
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);
diff --git a/intern/cycles/render/particles.cpp b/intern/cycles/render/particles.cpp
index 50726bb4574..1a35d60fb4b 100644
--- a/intern/cycles/render/particles.cpp
+++ b/intern/cycles/render/particles.cpp
@@ -58,8 +58,8 @@ void ParticleSystemManager::device_update_particles(Device *device, DeviceScene
* 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;
- foreach(ParticleSystem *psys, scene->particle_systems)
- num_particles += psys->particles.size();
+ for(size_t j = 0; j < scene->particle_systems.size(); j++)
+ num_particles += scene->particle_systems[j]->particles.size();
float4 *particles = dscene->particles.resize(PARTICLE_SIZE*num_particles);
@@ -71,9 +71,12 @@ void ParticleSystemManager::device_update_particles(Device *device, DeviceScene
particles[4] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
int i = 1;
- foreach(ParticleSystem *psys, scene->particle_systems) {
- foreach(Particle &pa, psys->particles) {
+ 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];
int offset = i*PARTICLE_SIZE;
particles[offset] = make_float4(pa.index, pa.age, pa.lifetime, pa.size);
diff --git a/intern/cycles/render/particles.h b/intern/cycles/render/particles.h
index bf2b6b77015..2509e27b44b 100644
--- a/intern/cycles/render/particles.h
+++ b/intern/cycles/render/particles.h
@@ -47,7 +47,7 @@ public:
void tag_update(Scene *scene);
- vector<Particle> particles;
+ array<Particle> particles;
};
/* ParticleSystem Manager */
diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp
index b0052c30af4..b341837b7e8 100644
--- a/intern/cycles/render/scene.cpp
+++ b/intern/cycles/render/scene.cpp
@@ -242,9 +242,14 @@ void Scene::device_update(Device *device_, Progress& progress)
}
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: " << util_guarded_get_mem_used() << "\n"
- << " Peak: " << util_guarded_get_mem_peak();
+ << " 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) << ")";
}
}
@@ -258,6 +263,14 @@ Scene::MotionType Scene::need_motion(bool advanced_shading)
return MOTION_NONE;
}
+float Scene::motion_shutter_time()
+{
+ 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)
diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h
index 33c03d40f27..9e72f197cce 100644
--- a/intern/cycles/render/scene.h
+++ b/intern/cycles/render/scene.h
@@ -63,7 +63,8 @@ public:
device_vector<float4> bvh_nodes;
device_vector<float4> bvh_leaf_nodes;
device_vector<uint> object_node;
- device_vector<float4> tri_storage;
+ device_vector<uint> prim_tri_index;
+ device_vector<float4> prim_tri_verts;
device_vector<uint> prim_type;
device_vector<uint> prim_visibility;
device_vector<uint> prim_index;
@@ -72,12 +73,15 @@ public:
/* mesh */
device_vector<uint> tri_shader;
device_vector<float4> tri_vnormal;
- device_vector<float4> tri_vindex;
- device_vector<float4> tri_verts;
+ 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<float4> objects;
device_vector<float4> objects_vector;
@@ -109,10 +113,12 @@ public:
device_vector<uint> sobol_directions;
/* cpu images */
- device_vector<uchar4> tex_byte4_image[TEX_NUM_BYTE4_IMAGES_CPU];
- device_vector<float4> tex_float4_image[TEX_NUM_FLOAT4_IMAGES_CPU];
- device_vector<float> tex_float_image[TEX_NUM_FLOAT_IMAGES_CPU];
- device_vector<uchar> tex_byte_image[TEX_NUM_BYTE_IMAGES_CPU];
+ device_vector<uchar4> tex_byte4_image[TEX_NUM_BYTE4_CPU];
+ device_vector<float4> tex_float4_image[TEX_NUM_FLOAT4_CPU];
+ device_vector<float> tex_float_image[TEX_NUM_FLOAT_CPU];
+ device_vector<uchar> tex_byte_image[TEX_NUM_BYTE_CPU];
+ device_vector<half4> tex_half4_image[TEX_NUM_HALF4_CPU];
+ device_vector<half> tex_half_image[TEX_NUM_HALF_CPU];
/* opencl images */
device_vector<uchar4> tex_image_byte4_packed;
@@ -134,6 +140,7 @@ public:
BVH_NUM_TYPES,
} bvh_type;
bool use_bvh_spatial_split;
+ bool use_bvh_unaligned_nodes;
bool use_qbvh;
bool persistent_data;
@@ -142,6 +149,7 @@ public:
shadingsystem = SHADINGSYSTEM_SVM;
bvh_type = BVH_DYNAMIC;
use_bvh_spatial_split = false;
+ use_bvh_unaligned_nodes = true;
use_qbvh = false;
persistent_data = false;
}
@@ -150,6 +158,7 @@ public:
{ return !(shadingsystem == params.shadingsystem
&& bvh_type == params.bvh_type
&& use_bvh_spatial_split == params.use_bvh_spatial_split
+ && use_bvh_unaligned_nodes == params.use_bvh_unaligned_nodes
&& use_qbvh == params.use_qbvh
&& persistent_data == params.persistent_data); }
};
@@ -208,6 +217,7 @@ public:
enum MotionType { MOTION_NONE = 0, MOTION_PASS, MOTION_BLUR };
MotionType need_motion(bool advanced_shading = true);
+ float motion_shutter_time();
bool need_update();
bool need_reset();
diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp
index 76979e9ba3e..1cd76ff2b39 100644
--- a/intern/cycles/render/session.cpp
+++ b/intern/cycles/render/session.cpp
@@ -630,7 +630,7 @@ DeviceRequestedFeatures Session::get_requested_device_features()
requested_features.use_camera_motion = scene->camera->use_motion;
foreach(Object *object, scene->objects) {
Mesh *mesh = object->mesh;
- if(mesh->curves.size() > 0) {
+ if(mesh->num_curves()) {
requested_features.use_hair = true;
}
requested_features.use_object_motion |= object->use_motion | mesh->use_motion_blur;
diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp
index 635024d7bdf..4cdb878df45 100644
--- a/intern/cycles/render/shader.cpp
+++ b/intern/cycles/render/shader.cpp
@@ -449,17 +449,15 @@ void ShaderManager::device_free_common(Device *device, DeviceScene *dscene, Scen
void ShaderManager::add_default(Scene *scene)
{
- ShaderNode *closure, *out;
-
/* default surface */
{
ShaderGraph *graph = new ShaderGraph();
- closure = graph->add(new DiffuseBsdfNode());
- closure->input("Color")->value = make_float3(0.8f, 0.8f, 0.8f);
- out = graph->output();
+ DiffuseBsdfNode *diffuse = new DiffuseBsdfNode();
+ diffuse->color = make_float3(0.8f, 0.8f, 0.8f);
+ graph->add(diffuse);
- graph->connect(closure->output("BSDF"), out->input("Surface"));
+ graph->connect(diffuse->output("BSDF"), graph->output()->input("Surface"));
Shader *shader = new Shader();
shader->name = "default_surface";
@@ -472,12 +470,12 @@ void ShaderManager::add_default(Scene *scene)
{
ShaderGraph *graph = new ShaderGraph();
- closure = graph->add(new EmissionNode());
- closure->input("Color")->value = make_float3(0.8f, 0.8f, 0.8f);
- closure->input("Strength")->value.x = 0.0f;
- out = graph->output();
+ EmissionNode *emission = new EmissionNode();
+ emission->color = make_float3(0.8f, 0.8f, 0.8f);
+ emission->strength = 0.0f;
+ graph->add(emission);
- graph->connect(closure->output("Emission"), out->input("Surface"));
+ graph->connect(emission->output("Emission"), graph->output()->input("Surface"));
Shader *shader = new Shader();
shader->name = "default_light";
diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp
index 4c97a5ad792..1a166885e2b 100644
--- a/intern/cycles/render/svm.cpp
+++ b/intern/cycles/render/svm.cpp
@@ -65,20 +65,21 @@ void SVMShaderManager::device_update(Device *device, DeviceScene *dscene, Scene
svm_nodes.push_back(make_int4(NODE_SHADER_JUMP, 0, 0, 0));
svm_nodes.push_back(make_int4(NODE_SHADER_JUMP, 0, 0, 0));
}
-
+
foreach(Shader *shader, scene->shaders) {
if(progress.get_cancel()) return;
assert(shader->graph);
- if(shader->use_mis && shader->has_surface_emission)
- scene->light_manager->need_update = true;
-
SVMCompiler::Summary summary;
SVMCompiler compiler(scene->shader_manager, scene->image_manager);
compiler.background = (shader == scene->default_background);
compiler.compile(scene, shader, svm_nodes, shader->id, &summary);
+ if(shader->use_mis && shader->has_surface_emission) {
+ scene->light_manager->need_update = true;
+ }
+
VLOG(2) << "Compilation summary:\n"
<< "Shader name: " << shader->name << "\n"
<< summary.full_report();
@@ -120,22 +121,22 @@ SVMCompiler::SVMCompiler(ShaderManager *shader_manager_, ImageManager *image_man
compile_failed = false;
}
-int SVMCompiler::stack_size(ShaderSocketType type)
+int SVMCompiler::stack_size(SocketType::Type type)
{
int size = 0;
switch(type) {
- case SHADER_SOCKET_FLOAT:
- case SHADER_SOCKET_INT:
+ case SocketType::FLOAT:
+ case SocketType::INT:
size = 1;
break;
- case SHADER_SOCKET_COLOR:
- case SHADER_SOCKET_VECTOR:
- case SHADER_SOCKET_NORMAL:
- case SHADER_SOCKET_POINT:
+ case SocketType::COLOR:
+ case SocketType::VECTOR:
+ case SocketType::NORMAL:
+ case SocketType::POINT:
size = 3;
break;
- case SHADER_SOCKET_CLOSURE:
+ case SocketType::CLOSURE:
size = 0;
break;
default:
@@ -146,7 +147,7 @@ int SVMCompiler::stack_size(ShaderSocketType type)
return size;
}
-int SVMCompiler::stack_find_offset(ShaderSocketType type)
+int SVMCompiler::stack_find_offset(SocketType::Type type)
{
int size = stack_size(type);
int offset = -1;
@@ -175,7 +176,7 @@ int SVMCompiler::stack_find_offset(ShaderSocketType type)
return 0;
}
-void SVMCompiler::stack_clear_offset(ShaderSocketType type, int offset)
+void SVMCompiler::stack_clear_offset(SocketType::Type type, int offset)
{
int size = stack_size(type);
@@ -192,23 +193,25 @@ int SVMCompiler::stack_assign(ShaderInput *input)
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);
+ input->stack_offset = stack_find_offset(input->type());
- if(input->type == SHADER_SOCKET_FLOAT) {
- add_node(NODE_VALUE_F, __float_as_int(input->value.x), input->stack_offset);
+ 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 == SHADER_SOCKET_INT) {
- add_node(NODE_VALUE_F, (int)input->value.x, 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 == SHADER_SOCKET_VECTOR ||
- input->type == SHADER_SOCKET_NORMAL ||
- input->type == SHADER_SOCKET_POINT ||
- input->type == SHADER_SOCKET_COLOR)
+ 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, input->value);
+ add_node(NODE_VALUE_V, node->get_float3(input->socket_type));
}
else /* should not get called for closure */
assert(0);
@@ -222,7 +225,7 @@ 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);
+ output->stack_offset = stack_find_offset(output->type());
return output->stack_offset;
}
@@ -247,11 +250,11 @@ 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));
+ assert(stack_size(output->type()) == stack_size(input->link->type()));
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]++;
@@ -279,7 +282,7 @@ void SVMCompiler::stack_clear_users(ShaderNode *node, ShaderNodeSet& done)
all_done = false;
if(all_done) {
- stack_clear_offset(output->type, output->stack_offset);
+ stack_clear_offset(output->type(), output->stack_offset);
output->stack_offset = SVM_STACK_INVALID;
foreach(ShaderInput *in, output->links)
@@ -293,7 +296,7 @@ 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);
+ stack_clear_offset(input->type(), input->stack_offset);
input->stack_offset = SVM_STACK_INVALID;
}
}
@@ -446,7 +449,7 @@ void SVMCompiler::generate_closure_node(ShaderNode *node,
const char *weight_name = (current_type == SHADER_TYPE_VOLUME)? "VolumeMixWeight": "SurfaceMixWeight";
ShaderInput *weight_in = node->input(weight_name);
- if(weight_in && (weight_in->link || weight_in->value.x != 1.0f))
+ 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;
@@ -479,7 +482,7 @@ void SVMCompiler::generated_shared_closure_nodes(ShaderNode *root_node,
}
else {
foreach(ShaderInput *in, node->inputs) {
- if(in->type == SHADER_SOCKET_CLOSURE && in->link)
+ if(in->type() == SocketType::CLOSURE && in->link)
generated_shared_closure_nodes(root_node,
in->link->parent,
state,
diff --git a/intern/cycles/render/svm.h b/intern/cycles/render/svm.h
index dbf1b1de947..e14d57d7601 100644
--- a/intern/cycles/render/svm.h
+++ b/intern/cycles/render/svm.h
@@ -99,8 +99,8 @@ public:
int stack_assign(ShaderInput *input);
int stack_assign_if_linked(ShaderInput *input);
int stack_assign_if_linked(ShaderOutput *output);
- int stack_find_offset(ShaderSocketType type);
- void stack_clear_offset(ShaderSocketType type, int offset);
+ 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);
@@ -172,7 +172,7 @@ protected:
};
void stack_clear_temporary(ShaderNode *node);
- int stack_size(ShaderSocketType type);
+ int stack_size(SocketType::Type type);
void stack_clear_users(ShaderNode *node, ShaderNodeSet& done);
bool node_skip_input(ShaderNode *node, ShaderInput *input);
diff --git a/intern/cycles/subd/CMakeLists.txt b/intern/cycles/subd/CMakeLists.txt
index d1708868fd0..db497013693 100644
--- a/intern/cycles/subd/CMakeLists.txt
+++ b/intern/cycles/subd/CMakeLists.txt
@@ -14,14 +14,12 @@ set(INC_SYS
set(SRC
subd_dice.cpp
- subd_mesh.cpp
subd_patch.cpp
subd_split.cpp
)
set(SRC_HEADERS
subd_dice.h
- subd_mesh.h
subd_patch.h
subd_split.h
)
diff --git a/intern/cycles/subd/subd_dice.cpp b/intern/cycles/subd/subd_dice.cpp
index a5dfcd21ceb..36981a20f3c 100644
--- a/intern/cycles/subd/subd_dice.cpp
+++ b/intern/cycles/subd/subd_dice.cpp
@@ -41,14 +41,19 @@ EdgeDice::EdgeDice(const SubdParams& params_)
}
}
-void EdgeDice::reserve(int num_verts, int num_tris)
+void EdgeDice::reserve(int num_verts)
{
Mesh *mesh = params.mesh;
vert_offset = mesh->verts.size();
- tri_offset = mesh->triangles.size();
+ tri_offset = mesh->num_triangles();
- mesh->reserve(vert_offset + num_verts, tri_offset + num_tris, 0, 0);
+ /* 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);
Attribute *attr_vN = mesh->attributes.add(ATTR_STD_VERTEX_NORMAL);
@@ -66,25 +71,35 @@ int EdgeDice::add_vert(Patch *patch, float2 uv)
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.reserve();
+ params.mesh->attributes.resize();
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++;
+
return vert_offset++;
}
void EdgeDice::add_triangle(Patch *patch, int v0, int v1, int v2)
{
- params.mesh->add_triangle(v0, v1, v2, params.shader, params.smooth, false);
+ 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));
+
+ 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.reserve();
+ params.mesh->attributes.resize();
float *ptex_face_id = attr_ptex_face_id->data_float();
ptex_face_id[tri_offset] = (float)patch->ptex_face_id();
@@ -141,8 +156,7 @@ 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);
- int num_tris = 0;
- EdgeDice::reserve(num_verts, num_tris);
+ EdgeDice::reserve(num_verts);
}
float2 QuadDice::map_uv(SubPatch& sub, float u, float v)
@@ -335,160 +349,5 @@ void QuadDice::dice(SubPatch& sub, EdgeFactors& ef)
assert(vert_offset == params.mesh->verts.size());
}
-/* TriangleDice */
-
-TriangleDice::TriangleDice(const SubdParams& params_)
-: EdgeDice(params_)
-{
-}
-
-void TriangleDice::reserve(EdgeFactors& ef, int M)
-{
- int num_verts = ef.tu + ef.tv + ef.tw;
-
- for(int m = M-2; m > 0; m -= 2)
- num_verts += 3 + (m-1)*3;
-
- if(!(M & 1))
- num_verts++;
-
- EdgeDice::reserve(num_verts, 0);
-}
-
-float2 TriangleDice::map_uv(SubPatch& sub, float2 uv)
-{
- /* map UV from subpatch to patch parametric coordinates */
- return uv.x*sub.Pu + uv.y*sub.Pv + (1.0f - uv.x - uv.y)*sub.Pw;
-}
-
-int TriangleDice::add_vert(SubPatch& sub, float2 uv)
-{
- return EdgeDice::add_vert(sub.patch, map_uv(sub, uv));
-}
-
-void TriangleDice::add_grid(SubPatch& sub, EdgeFactors& ef, int M)
-{
- // XXX normals are flipped, why?
-
- /* grid is constructed starting from the outside edges, and adding
- * progressively smaller inner triangles that connected to the outer
- * one, until M = 1 or 2, the we fill up the last part. */
- vector<int> outer_u, outer_v, outer_w;
- int m;
-
- /* add outer corners vertices */
- {
- float2 p_u = make_float2(1.0f, 0.0f);
- float2 p_v = make_float2(0.0f, 1.0f);
- float2 p_w = make_float2(0.0f, 0.0f);
-
- int corner_u = add_vert(sub, p_u);
- int corner_v = add_vert(sub, p_v);
- int corner_w = add_vert(sub, p_w);
-
- outer_u.push_back(corner_v);
- outer_v.push_back(corner_w);
- outer_w.push_back(corner_u);
-
- for(int i = 1; i < ef.tu; i++)
- outer_u.push_back(add_vert(sub, interp(p_v, p_w, i/(float)ef.tu)));
- for(int i = 1; i < ef.tv; i++)
- outer_v.push_back(add_vert(sub, interp(p_w, p_u, i/(float)ef.tv)));
- for(int i = 1; i < ef.tw; i++)
- outer_w.push_back(add_vert(sub, interp(p_u, p_v, i/(float)ef.tw)));
-
- outer_u.push_back(corner_w);
- outer_v.push_back(corner_u);
- outer_w.push_back(corner_v);
- }
-
- for(m = M-2; m > 0; m -= 2) {
- vector<int> inner_u, inner_v, inner_w;
-
- const float t0 = m / (float)M;
- float2 center = make_float2(1.0f/3.0f, 1.0f/3.0f);
-
- /* 3 corner vertices */
- float2 p_u = interp(center, make_float2(1.0f, 0.0f), t0);
- float2 p_v = interp(center, make_float2(0.0f, 1.0f), t0);
- float2 p_w = interp(center, make_float2(0.0f, 0.0f), t0);
-
- int corner_u = add_vert(sub, p_u);
- int corner_v = add_vert(sub, p_v);
- int corner_w = add_vert(sub, p_w);
-
- /* construct array of vertex indices for each side */
- inner_u.push_back(corner_v);
- inner_v.push_back(corner_w);
- inner_w.push_back(corner_u);
-
- for(int i = 1; i < m; i++) {
- /* add vertices between corners */
- const float t1 = i / (float)m;
-
- inner_u.push_back(add_vert(sub, interp(p_v, p_w, t1)));
- inner_v.push_back(add_vert(sub, interp(p_w, p_u, t1)));
- inner_w.push_back(add_vert(sub, interp(p_u, p_v, t1)));
- }
-
- inner_u.push_back(corner_w);
- inner_v.push_back(corner_u);
- inner_w.push_back(corner_v);
-
- /* stitch together inner/outer with triangles */
- stitch_triangles(sub.patch, outer_u, inner_u);
- stitch_triangles(sub.patch, outer_v, inner_v);
- stitch_triangles(sub.patch, outer_w, inner_w);
-
- outer_u = inner_u;
- outer_v = inner_v;
- outer_w = inner_w;
- }
-
- /* fill up last part */
- if(m == -1) {
- /* single triangle */
- add_triangle(sub.patch, outer_w[0], outer_u[0], outer_v[0]);
- }
- else {
- /* center vertex + up to 6 triangles */
- int center = add_vert(sub, make_float2(1.0f/3.0f, 1.0f/3.0f));
-
- add_triangle(sub.patch, outer_w[0], outer_w[1], center);
- /* if this is false then there is only one triangle on this side */
- if(outer_w.size() > 2)
- add_triangle(sub.patch, outer_w[1], outer_w[2], center);
-
- add_triangle(sub.patch, outer_u[0], outer_u[1], center);
- if(outer_u.size() > 2)
- add_triangle(sub.patch, outer_u[1], outer_u[2], center);
-
- add_triangle(sub.patch, outer_v[0], outer_v[1], center);
- if(outer_v.size() > 2)
- add_triangle(sub.patch, outer_v[1], outer_v[2], center);
- }
-}
-
-void TriangleDice::dice(SubPatch& sub, EdgeFactors& ef)
-{
- /* todo: handle 2 1 1 resolution */
- int M = max(ef.tu, max(ef.tv, ef.tw));
-
- /* Due to the "slant" of the edges of a triangle compared to a quad, the internal
- * triangles end up smaller, causing over-tessellation. This is to correct for this
- * difference in area. Technically its only correct for equilateral triangles, but
- * its better than how it was.
- *
- * (2*cos(radians(30))/3)**0.5
- */
- float S = 0.7598356856515927f;
- M = max((int)ceil(S*M), 1);
-
- reserve(ef, M);
- add_grid(sub, ef, M);
-
- 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 49f786e949e..3002ec780e8 100644
--- a/intern/cycles/subd/subd_dice.h
+++ b/intern/cycles/subd/subd_dice.h
@@ -33,8 +33,6 @@ class Patch;
struct SubdParams {
Mesh *mesh;
- int shader;
- bool smooth;
bool ptex;
int test_steps;
@@ -44,11 +42,9 @@ struct SubdParams {
Camera *camera;
Transform objecttoworld;
- SubdParams(Mesh *mesh_, int shader_, bool smooth_ = true, bool ptex_ = false)
+ SubdParams(Mesh *mesh_, bool ptex_ = false)
{
mesh = mesh_;
- shader = shader_;
- smooth = smooth_;
ptex = ptex_;
test_steps = 3;
@@ -72,7 +68,7 @@ public:
explicit EdgeDice(const SubdParams& params);
- void reserve(int num_verts, int num_tris);
+ void reserve(int num_verts);
int add_vert(Patch *patch, float2 uv);
void add_triangle(Patch *patch, int v0, int v1, int v2);
@@ -136,46 +132,6 @@ public:
void dice(SubPatch& sub, EdgeFactors& ef);
};
-/* Triangle EdgeDice
- *
- * Edge tessellation factors and subpatch coordinates are as follows:
- *
- * Pw
- * /\
- * tv / \ tu
- * / \
- * / \
- * Pu -------- Pv
- * tw
- */
-
-class TriangleDice : public EdgeDice {
-public:
- struct SubPatch {
- Patch *patch;
-
- float2 Pu;
- float2 Pv;
- float2 Pw;
- };
-
- struct EdgeFactors {
- int tu;
- int tv;
- int tw;
- };
-
- explicit TriangleDice(const SubdParams& params);
-
- void reserve(EdgeFactors& ef, int M);
-
- float2 map_uv(SubPatch& sub, float2 uv);
- int add_vert(SubPatch& sub, float2 uv);
-
- void add_grid(SubPatch& sub, EdgeFactors& ef, int M);
- void dice(SubPatch& sub, EdgeFactors& ef);
-};
-
CCL_NAMESPACE_END
#endif /* __SUBD_DICE_H__ */
diff --git a/intern/cycles/subd/subd_mesh.cpp b/intern/cycles/subd/subd_mesh.cpp
deleted file mode 100644
index 56d7d2b2303..00000000000
--- a/intern/cycles/subd/subd_mesh.cpp
+++ /dev/null
@@ -1,419 +0,0 @@
-/*
- * Original code in the public domain -- castanyo@yahoo.es
- *
- * Modifications copyright (c) 2011, Blender Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * 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.
- * * 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.
- *
- * 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
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <stdio.h>
-
-#include "subd_mesh.h"
-#include "subd_patch.h"
-#include "subd_split.h"
-
-#include "util_debug.h"
-#include "util_foreach.h"
-
-#ifdef WITH_OPENSUBDIV
-
-#include <osd/vertex.h>
-#include <osd/mesh.h>
-#include <osd/cpuComputeController.h>
-#include <osd/cpuVertexBuffer.h>
-#include <osd/cpuEvalLimitController.h>
-#include <osd/evalLimitContext.h>
-
-CCL_NAMESPACE_BEGIN
-
-/* typedefs */
-typedef OpenSubdiv::OsdVertex OsdVertex;
-typedef OpenSubdiv::FarMesh<OsdVertex> OsdFarMesh;
-typedef OpenSubdiv::FarMeshFactory<OsdVertex> OsdFarMeshFactory;
-typedef OpenSubdiv::HbrCatmarkSubdivision<OsdVertex> OsdHbrCatmarkSubdivision;
-typedef OpenSubdiv::HbrFace<OsdVertex> OsdHbrFace;
-typedef OpenSubdiv::HbrHalfedge<OsdVertex> OsdHbrHalfEdge;
-typedef OpenSubdiv::HbrMesh<OsdVertex> OsdHbrMesh;
-typedef OpenSubdiv::HbrVertex<OsdVertex> OsdHbrVertex;
-typedef OpenSubdiv::OsdCpuComputeContext OsdCpuComputeContext;
-typedef OpenSubdiv::OsdCpuComputeController OsdCpuComputeController;
-typedef OpenSubdiv::OsdCpuEvalLimitContext OsdCpuEvalLimitContext;
-typedef OpenSubdiv::OsdCpuEvalLimitController OsdCpuEvalLimitController;
-typedef OpenSubdiv::OsdCpuVertexBuffer OsdCpuVertexBuffer;
-typedef OpenSubdiv::OsdEvalCoords OsdEvalCoords;
-typedef OpenSubdiv::OsdVertexBufferDescriptor OsdVertexBufferDescriptor;
-
-/* OpenSubdiv Patch */
-
-class OpenSubdPatch : public Patch {
-public:
- int face_id;
-
- OpenSubdPatch(OsdFarMesh *farmesh, OsdCpuVertexBuffer *vbuf_base)
- {
- face_id = 0;
-
- /* create buffers for evaluation */
- vbuf_P = OsdCpuVertexBuffer::Create(3, 1);
- vbuf_dPdu = OsdCpuVertexBuffer::Create(3, 1);
- vbuf_dPdv = OsdCpuVertexBuffer::Create(3, 1);
-
- P = vbuf_P->BindCpuBuffer();
- dPdu = vbuf_dPdu->BindCpuBuffer();
- dPdv = vbuf_dPdv->BindCpuBuffer();
-
- /* setup evaluation context */
- OsdVertexBufferDescriptor in_desc(0, 3, 3), out_desc(0, 3, 3); /* offset, length, stride */
-
- evalctx = OsdCpuEvalLimitContext::Create(farmesh, false);
- evalctx->GetVertexData().Bind(in_desc, vbuf_base, out_desc, vbuf_P, vbuf_dPdu, vbuf_dPdv);
- }
-
- ~OpenSubdPatch()
- {
- evalctx->GetVertexData().Unbind();
-
- delete evalctx;
- delete vbuf_P;
- delete vbuf_dPdu;
- delete vbuf_dPdv;
- }
-
- void eval(float3 *P_, float3 *dPdu_, float3 *dPdv_, float u, float v)
- {
- OsdEvalCoords coords;
- coords.u = u;
- coords.v = v;
- coords.face = face_id;
-
- evalctrl.EvalLimitSample<OsdCpuVertexBuffer,OsdCpuVertexBuffer>(coords, evalctx, 0);
-
- *P_ = make_float3(P[0], P[1], P[2]);
- if(dPdu_) *dPdu_ = make_float3(dPdv[0], dPdv[1], dPdv[2]);
- if(dPdv_) *dPdv_ = make_float3(dPdu[0], dPdu[1], dPdu[2]);
-
- /* optimize: skip evaluating derivatives when not needed */
- /* todo: swapped derivatives, different winding convention? */
- }
-
- BoundBox bound()
- {
- /* not implemented */
- BoundBox bbox = BoundBox::empty;
- return bbox;
- }
-
- int ptex_face_id()
- {
- return face_id;
- }
-
-protected:
- OsdCpuEvalLimitController evalctrl;
- OsdCpuEvalLimitContext *evalctx;
- OsdCpuVertexBuffer *vbuf_P;
- OsdCpuVertexBuffer *vbuf_dPdu;
- OsdCpuVertexBuffer *vbuf_dPdv;
- float *P;
- float *dPdu;
- float *dPdv;
-};
-
-/* OpenSubdiv Mesh */
-
-OpenSubdMesh::OpenSubdMesh()
-{
- /* create osd mesh */
- static OsdHbrCatmarkSubdivision catmark;
- OsdHbrMesh *hbrmesh = new OsdHbrMesh(&catmark);
-
- /* initialize class */
- num_verts = 0;
- num_ptex_faces = 0;
- _hbrmesh = (void*)hbrmesh;
-}
-
-OpenSubdMesh::~OpenSubdMesh()
-{
- OsdHbrMesh *hbrmesh = (OsdHbrMesh*)_hbrmesh;
-
- if(hbrmesh)
- delete hbrmesh;
-}
-
-void OpenSubdMesh::add_vert(const float3& co)
-{
- OsdHbrMesh *hbrmesh = (OsdHbrMesh*)_hbrmesh;
-
- OsdVertex v;
- positions.push_back(co.x);
- positions.push_back(co.y);
- positions.push_back(co.z);
- hbrmesh->NewVertex(num_verts++, v);
-}
-
-void OpenSubdMesh::add_face(int v0, int v1, int v2)
-{
- int index[3] = {v0, v1, v2};
- return add_face(index, 3);
-}
-
-void OpenSubdMesh::add_face(int v0, int v1, int v2, int v3)
-{
- int index[4] = {v0, v1, v2, v3};
- add_face(index, 4);
-}
-
-void OpenSubdMesh::add_face(int *index, int num)
-{
- OsdHbrMesh *hbrmesh = (OsdHbrMesh*)_hbrmesh;
-
-#ifndef NDEBUG
- /* sanity checks */
- for(int j = 0; j < num; j++) {
- OsdHbrVertex *origin = hbrmesh->GetVertex(index[j]);
- OsdHbrVertex *destination = hbrmesh->GetVertex(index[(j+1)%num]);
- OsdHbrHalfEdge *opposite = destination->GetEdge(origin);
-
- if(origin==NULL || destination==NULL)
- assert(!"An edge was specified that connected a nonexistent vertex\n");
-
- if(origin == destination)
- assert(!"An edge was specified that connected a vertex to itself\n");
-
- if(opposite && opposite->GetOpposite())
- assert(!"A non-manifold edge incident to more than 2 faces was found\n");
-
- if(origin->GetEdge(destination)) {
- assert(!"An edge connecting two vertices was specified more than once."
- "It's likely that an incident face was flipped\n");
- }
- }
-#endif
-
- OsdHbrFace *face = hbrmesh->NewFace(num, index, 0);
-
- /* this is required for limit eval patch table? */
- face->SetPtexIndex(num_ptex_faces);
-
- if(num == 4)
- num_ptex_faces++;
- else
- num_ptex_faces += num;
-}
-
-bool OpenSubdMesh::finish()
-{
- OsdHbrMesh *hbrmesh = (OsdHbrMesh*)_hbrmesh;
-
- /* finish hbr mesh construction */
- hbrmesh->SetInterpolateBoundaryMethod(OsdHbrMesh::k_InterpolateBoundaryEdgeOnly);
- hbrmesh->Finish();
-
- return true;
-}
-
-void OpenSubdMesh::tessellate(DiagSplit *split)
-{
- if(num_ptex_faces == 0)
- return;
-
- const int level = 3;
- const bool requirefvar = false;
-
- /* convert HRB to FAR mesh */
- OsdHbrMesh *hbrmesh = (OsdHbrMesh*)_hbrmesh;
-
- OsdFarMeshFactory meshFactory(hbrmesh, level, true);
- OsdFarMesh *farmesh = meshFactory.Create(requirefvar);
- int num_hbr_verts = hbrmesh->GetNumVertices();
-
- delete hbrmesh;
- hbrmesh = NULL;
- _hbrmesh = NULL;
-
- /* refine HBR mesh with vertex coordinates */
- OsdCpuComputeController *compute_controller = new OsdCpuComputeController();
- OsdCpuComputeContext *compute_context = OsdCpuComputeContext::Create(farmesh);
-
- OsdCpuVertexBuffer *vbuf_base = OsdCpuVertexBuffer::Create(3, num_hbr_verts);
- vbuf_base->UpdateData(&positions[0], 0, num_verts);
-
- compute_controller->Refine(compute_context, farmesh->GetKernelBatches(), vbuf_base);
- compute_controller->Synchronize();
-
- /* split & dice patches */
- OpenSubdPatch patch(farmesh, vbuf_base);
-
- for(int f = 0; f < num_ptex_faces; f++) {
- patch.face_id = f;
- split->split_quad(&patch);
- }
-
- /* clean up */
- delete farmesh;
- delete compute_controller;
- delete compute_context;
- delete vbuf_base;
-}
-
-CCL_NAMESPACE_END
-
-#else /* WITH_OPENSUBDIV */
-
-CCL_NAMESPACE_BEGIN
-
-/* Subd Vertex */
-
-class SubdVert
-{
-public:
- int id;
- float3 co;
-
- explicit SubdVert(int id_)
- {
- id = id_;
- co = make_float3(0.0f, 0.0f, 0.0f);
- }
-};
-
-/* Subd Face */
-
-class SubdFace
-{
-public:
- int id;
- int numverts;
- int verts[4];
-
- explicit SubdFace(int id_)
- {
- id = id_;
- numverts = 0;
- }
-};
-
-/* Subd Mesh */
-
-SubdMesh::SubdMesh()
-{
-}
-
-SubdMesh::~SubdMesh()
-{
- foreach(SubdVert *vertex, verts)
- delete vertex;
- foreach(SubdFace *face, faces)
- delete face;
-
- verts.clear();
- faces.clear();
-}
-
-SubdVert *SubdMesh::add_vert(const float3& co)
-{
- SubdVert *v = new SubdVert(verts.size());
- v->co = co;
- verts.push_back(v);
-
- return v;
-}
-
-SubdFace *SubdMesh::add_face(int v0, int v1, int v2)
-{
- int index[3] = {v0, v1, v2};
- return add_face(index, 3);
-}
-
-SubdFace *SubdMesh::add_face(int v0, int v1, int v2, int v3)
-{
- int index[4] = {v0, v1, v2, v3};
- return add_face(index, 4);
-}
-
-SubdFace *SubdMesh::add_face(int *index, int num)
-{
- /* skip ngons */
- if(num < 3 || num > 4)
- return NULL;
-
- SubdFace *f = new SubdFace(faces.size());
-
- for(int i = 0; i < num; i++)
- f->verts[i] = index[i];
-
- f->numverts = num;
- faces.push_back(f);
-
- return f;
-}
-
-bool SubdMesh::finish()
-{
- return true;
-}
-
-void SubdMesh::tessellate(DiagSplit *split)
-{
- int num_faces = faces.size();
-
- for(int f = 0; f < num_faces; f++) {
- SubdFace *face = faces[f];
- Patch *patch;
- float3 *hull;
-
- if(face->numverts == 3) {
- LinearTrianglePatch *lpatch = new LinearTrianglePatch();
- hull = lpatch->hull;
- patch = lpatch;
- }
- else if(face->numverts == 4) {
- LinearQuadPatch *lpatch = new LinearQuadPatch();
- hull = lpatch->hull;
- patch = lpatch;
- }
- else {
- assert(0); /* n-gons should have been split already */
- continue;
- }
-
- for(int i = 0; i < face->numverts; i++)
- hull[i] = verts[face->verts[i]]->co;
-
- if(face->numverts == 4)
- swap(hull[2], hull[3]);
-
- if(patch->is_triangle())
- split->split_triangle(patch);
- else
- split->split_quad(patch);
-
- delete patch;
- }
-}
-
-CCL_NAMESPACE_END
-
-#endif /* WITH_OPENSUBDIV */
-
diff --git a/intern/cycles/subd/subd_mesh.h b/intern/cycles/subd/subd_mesh.h
deleted file mode 100644
index f6aefc20318..00000000000
--- a/intern/cycles/subd/subd_mesh.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Original code in the public domain -- castanyo@yahoo.es
- *
- * Modifications copyright (c) 2011, Blender Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * 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.
- * * 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.
- *
- * 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
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __SUBD_MESH_H__
-#define __SUBD_MESH_H__
-
-#include "util_map.h"
-#include "util_types.h"
-#include "util_vector.h"
-
-CCL_NAMESPACE_BEGIN
-
-#ifndef WITH_OPENSUBDIV
-class SubdVert;
-class SubdFace;
-#endif
-
-class DiagSplit;
-class Mesh;
-
-/* Subd Mesh with simple linear subdivision */
-
-class SubdMesh
-{
-public:
- SubdMesh();
- ~SubdMesh();
-
- SubdVert *add_vert(const float3& co);
-
- SubdFace *add_face(int v0, int v1, int v2);
- SubdFace *add_face(int v0, int v1, int v2, int v3);
- SubdFace *add_face(int *index, int num);
-
- bool finish();
- void tessellate(DiagSplit *split);
-
-protected:
-#ifdef WITH_OPENSUBDIV
- void *_hbrmesh;
- vector<float> positions;
- int num_verts, num_ptex_faces;
-#else
- vector<SubdVert*> verts;
- vector<SubdFace*> faces;
-#endif
-
-};
-
-CCL_NAMESPACE_END
-
-#endif /* __SUBD_MESH_H__ */
-
diff --git a/intern/cycles/subd/subd_patch.cpp b/intern/cycles/subd/subd_patch.cpp
index 60a78016054..d3319c5ccf5 100644
--- a/intern/cycles/subd/subd_patch.cpp
+++ b/intern/cycles/subd/subd_patch.cpp
@@ -84,32 +84,6 @@ BoundBox LinearQuadPatch::bound()
return bbox;
}
-/* Linear Triangle Patch */
-
-void LinearTrianglePatch::eval(float3 *P, float3 *dPdu, float3 *dPdv, float3 *N, float u, float v)
-{
- *P = u*hull[0] + v*hull[1] + (1.0f - u - v)*hull[2];
-
- if(dPdu && dPdv) {
- *dPdu = hull[0] - hull[2];
- *dPdv = hull[1] - hull[2];
- }
-
- if(N) {
- *N = normalize(u*normals[0] + v*normals[1] + (1.0f - u - v)*normals[2]);
- }
-}
-
-BoundBox LinearTrianglePatch::bound()
-{
- BoundBox bbox = BoundBox::empty;
-
- for(int i = 0; i < 3; i++)
- bbox.grow(hull[i]);
-
- return bbox;
-}
-
/* Bicubic Patch */
void BicubicPatch::eval(float3 *P, float3 *dPdu, float3 *dPdv, float3 *N, float u, float v)
diff --git a/intern/cycles/subd/subd_patch.h b/intern/cycles/subd/subd_patch.h
index bfa04412c66..360c1abf27b 100644
--- a/intern/cycles/subd/subd_patch.h
+++ b/intern/cycles/subd/subd_patch.h
@@ -26,9 +26,11 @@ class Patch {
public:
virtual ~Patch() {}
virtual void eval(float3 *P, float3 *dPdu, float3 *dPdv, float3 *N, float u, float v) = 0;
- virtual bool is_triangle() { return false; }
virtual BoundBox bound() = 0;
virtual int ptex_face_id() { return -1; }
+
+ int patch_index;
+ int shader;
};
/* Linear Quad Patch */
@@ -39,19 +41,6 @@ public:
float3 normals[4];
void eval(float3 *P, float3 *dPdu, float3 *dPdv, float3 *N, float u, float v);
- bool is_triangle() { return false; }
- BoundBox bound();
-};
-
-/* Linear Triangle Patch */
-
-class LinearTrianglePatch : public Patch {
-public:
- float3 hull[3];
- float3 normals[3];
-
- void eval(float3 *P, float3 *dPdu, float3 *dPdv, float3 *N, float u, float v);
- bool is_triangle() { return true; }
BoundBox bound();
};
@@ -62,7 +51,6 @@ public:
float3 hull[16];
void eval(float3 *P, float3 *dPdu, float3 *dPdv, float3 *N, float u, float v);
- bool is_triangle() { return false; }
BoundBox bound();
};
diff --git a/intern/cycles/subd/subd_split.cpp b/intern/cycles/subd/subd_split.cpp
index c4af8cc8c43..3c91ad8ab0d 100644
--- a/intern/cycles/subd/subd_split.cpp
+++ b/intern/cycles/subd/subd_split.cpp
@@ -40,12 +40,6 @@ void DiagSplit::dispatch(QuadDice::SubPatch& sub, QuadDice::EdgeFactors& ef)
edgefactors_quad.push_back(ef);
}
-void DiagSplit::dispatch(TriangleDice::SubPatch& sub, TriangleDice::EdgeFactors& ef)
-{
- subpatches_triangle.push_back(sub);
- edgefactors_triangle.push_back(ef);
-}
-
float3 DiagSplit::to_world(Patch *patch, float2 uv)
{
float3 P;
@@ -112,34 +106,6 @@ void DiagSplit::partition_edge(Patch *patch, float2 *P, int *t0, int *t1, float2
}
}
-static float2 right_to_equilateral(float2 P)
-{
- static const float2 A = make_float2(1.0f, 0.5f);
- static const float2 B = make_float2(0.0f, sinf(M_PI_F/3.0f));
- return make_float2(dot(P, A), dot(P, B));
-}
-
-static void limit_edge_factors(const TriangleDice::SubPatch& sub, TriangleDice::EdgeFactors& ef, int max_t)
-{
- float2 Pu = sub.Pu;
- float2 Pv = sub.Pv;
- float2 Pw = sub.Pw;
-
- if(sub.patch->is_triangle()) {
- Pu = right_to_equilateral(Pu);
- Pv = right_to_equilateral(Pv);
- Pw = right_to_equilateral(Pw);
- }
-
- int tu = int(max_t * len(Pw - Pv));
- int tv = int(max_t * len(Pw - Pu));
- int tw = int(max_t * len(Pv - Pu));
-
- ef.tu = tu <= 1 ? 1 : min(ef.tu, tu);
- ef.tv = tv <= 1 ? 1 : min(ef.tv, tv);
- ef.tw = tw <= 1 ? 1 : min(ef.tw, tw);
-}
-
static void limit_edge_factors(const QuadDice::SubPatch& sub, QuadDice::EdgeFactors& ef, int max_t)
{
float2 P00 = sub.P00;
@@ -147,13 +113,6 @@ static void limit_edge_factors(const QuadDice::SubPatch& sub, QuadDice::EdgeFact
float2 P10 = sub.P10;
float2 P11 = sub.P11;
- if(sub.patch->is_triangle()) {
- P00 = right_to_equilateral(P00);
- P01 = right_to_equilateral(P01);
- P10 = right_to_equilateral(P10);
- P11 = right_to_equilateral(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));
@@ -165,84 +124,6 @@ static void limit_edge_factors(const QuadDice::SubPatch& sub, QuadDice::EdgeFact
ef.tv1 = tv1 <= 1 ? 1 : min(ef.tv1, tv1);
}
-void DiagSplit::split(TriangleDice::SubPatch& sub, TriangleDice::EdgeFactors& ef, int depth)
-{
- if(depth > 32) {
- /* We should never get here, but just in case end recursion safely. */
- ef.tu = 1;
- ef.tv = 1;
- ef.tw = 1;
-
- dispatch(sub, ef);
- return;
- }
-
- assert(ef.tu == T(sub.patch, sub.Pv, sub.Pw));
- assert(ef.tv == T(sub.patch, sub.Pw, sub.Pu));
- assert(ef.tw == T(sub.patch, sub.Pu, sub.Pv));
-
- int non_uniform_count = int(ef.tu == DSPLIT_NON_UNIFORM) +
- int(ef.tv == DSPLIT_NON_UNIFORM) +
- int(ef.tw == DSPLIT_NON_UNIFORM);
-
- switch(non_uniform_count) {
- case 1: {
- /* TODO(mai): one edge is non-uniform, split into two triangles */
- // fallthru
- }
- case 2: {
- /* TODO(mai): two edges are non-uniform, split into triangle and quad */
- // fallthru
- }
- case 3: {
- /* all three edges are non-uniform, split into three quads */
-
- /* partition edges */
- QuadDice::EdgeFactors ef0, ef1, ef2;
- float2 Pu, Pv, Pw, Pcenter;
-
- partition_edge(sub.patch, &Pu, &ef1.tv0, &ef2.tu0, sub.Pw, sub.Pv, ef.tu);
- partition_edge(sub.patch, &Pv, &ef0.tv0, &ef1.tu0, sub.Pu, sub.Pw, ef.tv);
- partition_edge(sub.patch, &Pw, &ef2.tv0, &ef0.tu0, sub.Pv, sub.Pu, ef.tw);
- Pcenter = (Pu + Pv + Pw) * (1.0f / 3.0f);
-
- /* split */
- int tsplit01 = T(sub.patch, Pv, Pcenter);
- int tsplit12 = T(sub.patch, Pu, Pcenter);
- int tsplit20 = T(sub.patch, Pw, Pcenter);
-
- ef0.tu1 = tsplit01;
- ef0.tv1 = tsplit20;
-
- ef1.tu1 = tsplit12;
- ef1.tv1 = tsplit01;
-
- ef2.tu1 = tsplit20;
- ef2.tv1 = tsplit12;
-
- /* create subpatches */
- QuadDice::SubPatch sub0 = {sub.patch, sub.Pu, Pw, Pv, Pcenter};
- QuadDice::SubPatch sub1 = {sub.patch, sub.Pw, Pv, Pu, Pcenter};
- QuadDice::SubPatch sub2 = {sub.patch, sub.Pv, Pu, Pw, Pcenter};
-
- limit_edge_factors(sub0, ef0, 1 << params.max_level);
- limit_edge_factors(sub1, ef1, 1 << params.max_level);
- limit_edge_factors(sub2, ef2, 1 << params.max_level);
-
- split(sub0, ef0, depth+1);
- split(sub1, ef1, depth+1);
- split(sub2, ef2, depth+1);
-
- break;
- }
- default: {
- /* all edges uniform, no splitting needed */
- dispatch(sub, ef);
- break;
- }
- }
-}
-
void DiagSplit::split(QuadDice::SubPatch& sub, QuadDice::EdgeFactors& ef, int depth)
{
if(depth > 32) {
@@ -259,6 +140,16 @@ void DiagSplit::split(QuadDice::SubPatch& sub, QuadDice::EdgeFactors& ef, int de
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
+ * 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;
}
@@ -324,69 +215,21 @@ void DiagSplit::split(QuadDice::SubPatch& sub, QuadDice::EdgeFactors& ef, int de
}
}
-void DiagSplit::split_triangle(Patch *patch)
-{
- TriangleDice::SubPatch sub_split;
- TriangleDice::EdgeFactors ef_split;
-
- sub_split.patch = patch;
- sub_split.Pu = make_float2(1.0f, 0.0f);
- sub_split.Pv = make_float2(0.0f, 1.0f);
- sub_split.Pw = make_float2(0.0f, 0.0f);
-
- ef_split.tu = T(patch, sub_split.Pv, sub_split.Pw);
- ef_split.tv = T(patch, sub_split.Pw, sub_split.Pu);
- ef_split.tw = T(patch, sub_split.Pu, sub_split.Pv);
-
- limit_edge_factors(sub_split, ef_split, 1 << params.max_level);
-
- split(sub_split, ef_split);
-
- TriangleDice dice(params);
-
- for(size_t i = 0; i < subpatches_triangle.size(); i++) {
- TriangleDice::SubPatch& sub = subpatches_triangle[i];
- TriangleDice::EdgeFactors& ef = edgefactors_triangle[i];
-
- ef.tu = max(ef.tu, 1);
- ef.tv = max(ef.tv, 1);
- ef.tw = max(ef.tw, 1);
-
- dice.dice(sub, ef);
- }
-
- subpatches_triangle.clear();
- edgefactors_triangle.clear();
-
- /* triangle might be split into quads so dice quad subpatches as well */
- QuadDice qdice(params);
-
- 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);
-
- qdice.dice(sub, ef);
- }
-
- subpatches_quad.clear();
- edgefactors_quad.clear();
-}
-
-void DiagSplit::split_quad(Patch *patch)
+void DiagSplit::split_quad(Patch *patch, QuadDice::SubPatch *subpatch)
{
QuadDice::SubPatch sub_split;
QuadDice::EdgeFactors ef_split;
- 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);
diff --git a/intern/cycles/subd/subd_split.h b/intern/cycles/subd/subd_split.h
index bbe921f739c..a2f76dd2e03 100644
--- a/intern/cycles/subd/subd_split.h
+++ b/intern/cycles/subd/subd_split.h
@@ -38,8 +38,6 @@ class DiagSplit {
public:
vector<QuadDice::SubPatch> subpatches_quad;
vector<QuadDice::EdgeFactors> edgefactors_quad;
- vector<TriangleDice::SubPatch> subpatches_triangle;
- vector<TriangleDice::EdgeFactors> edgefactors_triangle;
SubdParams params;
@@ -53,11 +51,7 @@ public:
void dispatch(QuadDice::SubPatch& sub, QuadDice::EdgeFactors& ef);
void split(QuadDice::SubPatch& sub, QuadDice::EdgeFactors& ef, int depth=0);
- void dispatch(TriangleDice::SubPatch& sub, TriangleDice::EdgeFactors& ef);
- void split(TriangleDice::SubPatch& sub, TriangleDice::EdgeFactors& ef, int depth=0);
-
- void split_triangle(Patch *patch);
- void split_quad(Patch *patch);
+ void split_quad(Patch *patch, QuadDice::SubPatch *subpatch=NULL);
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/test/CMakeLists.txt b/intern/cycles/test/CMakeLists.txt
index 2f3a4d0b1df..a6bcf980df2 100644
--- a/intern/cycles/test/CMakeLists.txt
+++ b/intern/cycles/test/CMakeLists.txt
@@ -14,9 +14,37 @@ endmacro()
set(INC
.
..
+ ../device
+ ../graph
+ ../kernel
+ ../render
../util
)
+set(ALL_CYCLES_LIBRARIES
+ cycles_render
+ cycles_device
+ cycles_bvh
+ cycles_graph
+ cycles_kernel_osl
+ cycles_util
+ ${OPENIMAGEIO_LIBRARIES}
+)
+if(WITH_CYCLES_OSL)
+ list(APPEND ALL_CYCLES_LIBRARIES
+ ${OSL_LIBRARIES}
+ ${LLVM_LIBRARIES}
+ )
+endif()
+if(WITH_IMAGE_OPENJPEG AND NOT WITH_SYSTEM_OPENJPEG)
+ list(APPEND ALL_CYCLES_LIBRARIES
+ extern_openjpeg
+ )
+endif()
+list(APPEND ALL_CYCLES_LIBRARIES
+ ${BOOST_LIBRARIES}
+)
+
include_directories(${INC})
link_directories(${BOOST_LIBPATH})
@@ -25,6 +53,7 @@ link_directories(${OPENIMAGEIO_LIBPATH})
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${PLATFORM_LINKFLAGS}")
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${PLATFORM_LINKFLAGS_DEBUG}")
+CYCLES_TEST(render_graph_finalize "${ALL_CYCLES_LIBRARIES}")
CYCLES_TEST(util_aligned_malloc "cycles_util")
CYCLES_TEST(util_path "cycles_util;${BOOST_LIBRARIES};${OPENIMAGEIO_LIBRARIES}")
CYCLES_TEST(util_string "cycles_util;${BOOST_LIBRARIES}")
diff --git a/intern/cycles/test/render_graph_finalize_test.cpp b/intern/cycles/test/render_graph_finalize_test.cpp
new file mode 100644
index 00000000000..4566894d490
--- /dev/null
+++ b/intern/cycles/test/render_graph_finalize_test.cpp
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2011-2016 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "testing/testing.h"
+#include "testing/mock_log.h"
+
+#include "render/graph.h"
+#include "render/scene.h"
+#include "render/nodes.h"
+#include "util/util_logging.h"
+#include "util/util_string.h"
+#include "util/util_vector.h"
+
+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();
+ }
+
+ 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;
+ }
+
+protected:
+ string name_;
+ ShaderNode *node_;
+};
+
+class ShaderGraphBuilder {
+public:
+ explicit ShaderGraphBuilder(ShaderGraph *graph)
+ : graph_(graph)
+ {
+ }
+
+ 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(NULL, find_node(node.name()));
+ 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(2, tokens_from.size());
+ EXPECT_EQ(2, tokens_to.size());
+ 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;
+ }
+
+protected:
+ ShaderGraph *graph_;
+ map<string, ShaderNode *> node_map_;
+};
+
+} // namespace
+
+#define DEFINE_COMMON_VARIABLES(builder_name, mock_log_name) \
+ util_logging_start(); \
+ util_logging_verbosity_set(1); \
+ ScopedMockLog mock_log_name; \
+ DeviceInfo device_info; \
+ SceneParams scene_params; \
+ Scene scene(scene_params, device_info); \
+ ShaderGraph graph; \
+ ShaderGraphBuilder builder(&graph); \
+
+TEST(render_graph, constant_fold_rgb_to_bw)
+{
+ DEFINE_COMMON_VARIABLES(builder, log);
+
+ EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
+ EXPECT_CALL(log, Log(google::INFO, _,
+ HasSubstr("Replacing rgb_to_bw with constant 0.8.")));
+
+ builder
+ .add_node(ShaderNodeBuilder<OutputNode>("OutputNode"))
+ .add_node(ShaderNodeBuilder<EmissionNode>("EmissionNode"))
+ .add_node(ShaderNodeBuilder<RGBToBWNode>("RGBToBWNodeNode")
+ .set("Color", make_float3(0.8f, 0.8f, 0.8f)))
+ .add_connection("RGBToBWNodeNode::Val", "EmissionNode::Color")
+ .add_connection("EmissionNode::Emission", "OutputNode::Surface");
+
+ graph.finalize(&scene);
+}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/util/CMakeLists.txt b/intern/cycles/util/CMakeLists.txt
index cceec8d444c..e6140b3ed09 100644
--- a/intern/cycles/util/CMakeLists.txt
+++ b/intern/cycles/util/CMakeLists.txt
@@ -19,8 +19,10 @@ set(SRC
util_simd.cpp
util_system.cpp
util_task.cpp
+ util_thread.cpp
util_time.cpp
util_transform.cpp
+ util_windows.cpp
)
if(NOT CYCLES_STANDALONE_REPOSITORY)
diff --git a/intern/cycles/util/util_boundbox.h b/intern/cycles/util/util_boundbox.h
index cef5adc0a61..599222da9c5 100644
--- a/intern/cycles/util/util_boundbox.h
+++ b/intern/cycles/util/util_boundbox.h
@@ -151,7 +151,7 @@ public:
(isfinite(max.x) && isfinite(max.y) && isfinite(max.z));
}
- BoundBox transformed(const Transform *tfm)
+ BoundBox transformed(const Transform *tfm) const
{
BoundBox result = BoundBox::empty;
diff --git a/intern/cycles/util/util_half.h b/intern/cycles/util/util_half.h
index f4bac9888a5..ae85ab3a915 100644
--- a/intern/cycles/util/util_half.h
+++ b/intern/cycles/util/util_half.h
@@ -85,6 +85,27 @@ ccl_device_inline void float4_store_half(half *h, float4 f, float scale)
#endif
}
+ccl_device_inline float half_to_float(half h)
+{
+ float f;
+
+ *((int*) &f) = ((h & 0x8000) << 16) | (((h & 0x7c00) + 0x1C000) << 13) | ((h & 0x03FF) << 13);
+
+ return f;
+}
+
+ccl_device_inline float4 half4_to_float4(half4 h)
+{
+ 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);
+
+ return f;
+}
+
#endif
#endif
diff --git a/intern/cycles/util/util_math.h b/intern/cycles/util/util_math.h
index 32924f9a8c2..016f4a6a794 100644
--- a/intern/cycles/util/util_math.h
+++ b/intern/cycles/util/util_math.h
@@ -174,6 +174,11 @@ ccl_device_inline float clamp(float a, float mn, float mx)
return min(max(a, mn), mx);
}
+ccl_device_inline float mix(float a, float b, float t)
+{
+ return a + t*(b - a);
+}
+
#endif
#ifndef __KERNEL_CUDA__
@@ -219,6 +224,11 @@ ccl_device_inline float smoothstepf(float f)
return (3.0f*ff - 2.0f*ff*f);
}
+ccl_device_inline int mod(int x, int m)
+{
+ return (x % m + m) % m;
+}
+
/* Float2 Vector */
#ifndef __KERNEL_OPENCL__
@@ -545,6 +555,11 @@ ccl_device_inline float3 normalize(const float3 a)
#endif
+ccl_device_inline float3 saturate3(float3 a)
+{
+ 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);
@@ -647,6 +662,15 @@ ccl_device_inline float3 interp(float3 a, float3 b, float t)
return a + t*(b - a);
}
+#ifndef __KERNEL_OPENCL__
+
+ccl_device_inline float3 mix(float3 a, float3 b, float t)
+{
+ return a + t*(b - a);
+}
+
+#endif
+
ccl_device_inline bool is_zero(const float3 a)
{
#ifdef __KERNEL_SSE__
@@ -666,6 +690,15 @@ ccl_device_inline float average(const float3 a)
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);
+#else
+ return a == b;
+#endif
+}
+
/* Float4 Vector */
#ifdef __KERNEL_SSE__
@@ -1329,6 +1362,15 @@ ccl_device float safe_modulo(float a, float b)
return (b != 0.0f)? fmodf(a, b): 0.0f;
}
+ccl_device_inline float beta(float x, float y)
+{
+#ifndef __KERNEL_OPENCL__
+ return expf(lgammaf(x) + lgammaf(y) - lgammaf(x+y));
+#else
+ return expf(lgamma(x) + lgamma(y) - lgamma(x+y));
+#endif
+}
+
/* Ray Intersection */
ccl_device bool ray_sphere_intersect(
@@ -1479,21 +1521,25 @@ ccl_device bool ray_triangle_intersect_uv(
return true;
}
-ccl_device bool ray_quad_intersect(float3 ray_P, float3 ray_D, float ray_t,
- float3 quad_P, float3 quad_u, float3 quad_v,
+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)
{
- float3 v0 = quad_P - quad_u*0.5f - quad_v*0.5f;
- float3 v1 = quad_P + quad_u*0.5f - quad_v*0.5f;
- float3 v2 = quad_P + quad_u*0.5f + quad_v*0.5f;
- float3 v3 = quad_P - quad_u*0.5f + quad_v*0.5f;
+ 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;
- if(ray_triangle_intersect(ray_P, ray_D, ray_t, v0, v1, v2, isect_P, isect_t))
- return true;
- else if(ray_triangle_intersect(ray_P, ray_D, ray_t, v0, v2, v3, isect_P, isect_t))
- return true;
-
- return false;
+ float3 hit = ray_P + t*ray_D;
+ float3 inplane = hit - quad_P;
+ if(fabsf(dot(inplane, quad_u) / dot(quad_u, quad_u)) > 0.5f)
+ return false;
+ if(fabsf(dot(inplane, quad_v) / dot(quad_v, quad_v)) > 0.5f)
+ return false;
+
+ if(isect_P) *isect_P = hit;
+ if(isect_t) *isect_t = t;
+
+ return true;
}
/* projections */
diff --git a/intern/cycles/util/util_math_fast.h b/intern/cycles/util/util_math_fast.h
index deb2013daae..d3960deb3b4 100644
--- a/intern/cycles/util/util_math_fast.h
+++ b/intern/cycles/util/util_math_fast.h
@@ -547,6 +547,9 @@ ccl_device_inline float fast_erff(float x)
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 */
diff --git a/intern/cycles/util/util_path.cpp b/intern/cycles/util/util_path.cpp
index 0c848beaafd..f23f2cb0168 100644
--- a/intern/cycles/util/util_path.cpp
+++ b/intern/cycles/util/util_path.cpp
@@ -728,6 +728,17 @@ bool path_remove(const string& path)
return remove(path.c_str()) == 0;
}
+static string line_directive(const string& path, int line)
+{
+ string escaped_path = path;
+ string_replace(escaped_path, "\"", "\\\"");
+ string_replace(escaped_path, "\'", "\\\'");
+ string_replace(escaped_path, "\?", "\\\?");
+ string_replace(escaped_path, "\\", "\\\\");
+ return string_printf("#line %d \"%s\"", line, escaped_path.c_str());
+}
+
+
string path_source_replace_includes(const string& source, const string& path)
{
/* Our own little c preprocessor that replaces #includes with the file
@@ -737,7 +748,7 @@ string path_source_replace_includes(const string& source, const string& path)
string result = "";
vector<string> lines;
- string_split(lines, source, "\n");
+ string_split(lines, source, "\n", false);
for(size_t i = 0; i < lines.size(); ++i) {
string line = lines[i];
@@ -759,7 +770,10 @@ string path_source_replace_includes(const string& source, const string& path)
text = path_source_replace_includes(
text, path_dirname(filepath));
text = path_source_replace_includes(text, path);
- line = token.replace(0, n_end + 1, "\n" + text + "\n");
+ /* Use line directives for better error messages. */
+ line = line_directive(filepath, 1)
+ + token.replace(0, n_end + 1, "\n" + text + "\n")
+ + line_directive(path, i);
}
}
}
diff --git a/intern/cycles/util/util_string.cpp b/intern/cycles/util/util_string.cpp
index b3a8c6d7c2e..5594aa8edb6 100644
--- a/intern/cycles/util/util_string.cpp
+++ b/intern/cycles/util/util_string.cpp
@@ -74,7 +74,10 @@ bool string_iequals(const string& a, const string& b)
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) {
@@ -87,9 +90,9 @@ void string_split(vector<string>& tokens, const string& str, const string& separ
}
else {
/* Current character is a separator,
- * append current token to the list (if token is not empty).
+ * append current token to the list.
*/
- if(token_length > 0) {
+ if(!skip_empty_tokens || token_length > 0) {
string token = str.substr(token_start, token_length);
tokens.push_back(token);
}
@@ -239,5 +242,49 @@ string string_to_ansi(const string& str)
#endif /* _WIN32 */
+string string_human_readable_size(size_t size)
+{
+ static const char suffixes[] = "BKMGTPEZY";
+
+ const char* suffix = suffixes;
+ size_t r = 0;
+
+ 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);
+}
+
+string string_human_readable_number(size_t num)
+{
+ if(num == 0) {
+ return "0";
+ }
+
+ /* Add thousands separators. */
+ char buf[32];
+
+ char* p = buf+31;
+ *p = '\0';
+
+ int i = -1;
+ while(num) {
+ if(++i && i % 3 == 0)
+ *(--p) = ',';
+
+ *(--p) = '0' + (num % 10);
+
+ num /= 10;
+ }
+
+ return p;
+}
+
CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_string.h b/intern/cycles/util/util_string.h
index c4b51bda432..7aeed96f00b 100644
--- a/intern/cycles/util/util_string.h
+++ b/intern/cycles/util/util_string.h
@@ -39,7 +39,10 @@ using std::istringstream;
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 ");
+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);
@@ -62,6 +65,11 @@ 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 */
+string string_human_readable_size(size_t size);
+/* Make a string from a unitless quantity in human readable form */
+string string_human_readable_number(size_t num);
+
CCL_NAMESPACE_END
#endif /* __UTIL_STRING_H__ */
diff --git a/intern/cycles/util/util_system.cpp b/intern/cycles/util/util_system.cpp
index 4ff0ee91d73..d5fac9a0e34 100644
--- a/intern/cycles/util/util_system.cpp
+++ b/intern/cycles/util/util_system.cpp
@@ -15,7 +15,9 @@
*/
#include "util_system.h"
+
#include "util_debug.h"
+#include "util_logging.h"
#include "util_types.h"
#include "util_string.h"
@@ -33,28 +35,56 @@
CCL_NAMESPACE_BEGIN
-int system_cpu_thread_count()
+int system_cpu_group_count()
{
- static uint count = 0;
-
- if(count > 0)
- return count;
+#ifdef _WIN32
+ util_windows_init_numa_groups();
+ return GetActiveProcessorGroupCount();
+#else
+ /* TODO(sergey): Need to adopt for other platforms. */
+ return 1;
+#endif
+}
+int system_cpu_group_thread_count(int group)
+{
+ /* TODO(sergey): Need make other platforms aware of groups. */
#ifdef _WIN32
- SYSTEM_INFO info;
- GetSystemInfo(&info);
- count = (uint)info.dwNumberOfProcessors;
+ util_windows_init_numa_groups();
+ return GetActiveProcessorCount(group);
#elif defined(__APPLE__)
+ (void)group;
+ int count;
size_t len = sizeof(count);
int mib[2] = { CTL_HW, HW_NCPU };
-
sysctl(mib, 2, &count, &len, NULL, 0);
+ return count;
#else
- count = (uint)sysconf(_SC_NPROCESSORS_ONLN);
+ (void)group;
+ return sysconf(_SC_NPROCESSORS_ONLN);
#endif
+}
+
+int system_cpu_thread_count()
+{
+ static uint count = 0;
- if(count < 1)
+ if(count > 0) {
+ return count;
+ }
+
+ int max_group = system_cpu_group_count();
+ VLOG(1) << "Detected " << max_group << " CPU groups.";
+ for(int group = 0; group < max_group; ++group) {
+ int num_threads = system_cpu_group_thread_count(group);
+ VLOG(1) << "Group " << group
+ << " has " << num_threads << " threads.";
+ count += num_threads;
+ }
+
+ if(count < 1) {
count = 1;
+ }
return count;
}
diff --git a/intern/cycles/util/util_system.h b/intern/cycles/util/util_system.h
index 4e7e00f85fd..557aab6cbae 100644
--- a/intern/cycles/util/util_system.h
+++ b/intern/cycles/util/util_system.h
@@ -21,7 +21,15 @@
CCL_NAMESPACE_BEGIN
+/* Get number of available CPU groups. */
+int system_cpu_group_count();
+
+/* Get number of threads/processors in the specified group. */
+int system_cpu_group_thread_count(int group);
+
+/* Get total number of threads in all groups. */
int system_cpu_thread_count();
+
string system_cpu_brand_string();
int system_cpu_bits();
bool system_cpu_support_sse2();
diff --git a/intern/cycles/util/util_task.cpp b/intern/cycles/util/util_task.cpp
index d86aa8a4a46..352ba81c95a 100644
--- a/intern/cycles/util/util_task.cpp
+++ b/intern/cycles/util/util_task.cpp
@@ -16,6 +16,7 @@
#include "util_debug.h"
#include "util_foreach.h"
+#include "util_logging.h"
#include "util_system.h"
#include "util_task.h"
#include "util_time.h"
@@ -198,12 +199,30 @@ void TaskScheduler::init(int num_threads)
/* automatic number of threads */
num_threads = system_cpu_thread_count();
}
+ VLOG(1) << "Creating pool of " << num_threads << " threads.";
/* launch threads that will be waiting for work */
threads.resize(num_threads);
- for(size_t i = 0; i < threads.size(); i++)
- threads[i] = new thread(function_bind(&TaskScheduler::thread_run, i + 1));
+ int num_groups = system_cpu_group_count();
+ int thread_index = 0;
+ for(int group = 0; group < num_groups; ++group) {
+ /* NOTE: That's not really efficient from threading point of view,
+ * but it is simple to read and it doesn't make sense to use more
+ * user-specified threads than logical threads anyway.
+ */
+ int num_group_threads = (group == num_groups - 1)
+ ? (threads.size() - thread_index)
+ : system_cpu_group_thread_count(group);
+ for(int group_thread = 0;
+ group_thread < num_group_threads && thread_index < threads.size();
+ ++group_thread, ++thread_index)
+ {
+ threads[thread_index] = new thread(function_bind(&TaskScheduler::thread_run,
+ thread_index + 1),
+ group);
+ }
+ }
}
users++;
diff --git a/intern/cycles/util/util_texture.h b/intern/cycles/util/util_texture.h
index 6da47858133..2ef47283029 100644
--- a/intern/cycles/util/util_texture.h
+++ b/intern/cycles/util/util_texture.h
@@ -19,43 +19,63 @@
CCL_NAMESPACE_BEGIN
-/* Texture limits on various devices. */
+/* Texture limits on devices. */
/* CPU */
-#define TEX_NUM_BYTE4_IMAGES_CPU 1024
-#define TEX_NUM_FLOAT4_IMAGES_CPU 1024
-#define TEX_NUM_FLOAT_IMAGES_CPU 1024
-#define TEX_NUM_BYTE_IMAGES_CPU 1024
-#define TEX_IMAGE_BYTE4_START_CPU TEX_NUM_FLOAT4_IMAGES_CPU
-#define TEX_IMAGE_FLOAT_START_CPU (TEX_NUM_FLOAT4_IMAGES_CPU + TEX_NUM_BYTE4_IMAGES_CPU)
-#define TEX_IMAGE_BYTE_START_CPU (TEX_NUM_FLOAT4_IMAGES_CPU + TEX_NUM_BYTE4_IMAGES_CPU + TEX_NUM_BYTE_IMAGES_CPU)
+#define TEX_NUM_FLOAT4_CPU 1024
+#define TEX_NUM_BYTE4_CPU 1024
+#define TEX_NUM_FLOAT_CPU 1024
+#define TEX_NUM_BYTE_CPU 1024
+#define TEX_NUM_HALF4_CPU 1024
+#define TEX_NUM_HALF_CPU 1024
+#define TEX_START_FLOAT4_CPU 0
+#define TEX_START_BYTE4_CPU TEX_NUM_FLOAT4_CPU
+#define TEX_START_FLOAT_CPU (TEX_NUM_FLOAT4_CPU + TEX_NUM_BYTE4_CPU)
+#define TEX_START_BYTE_CPU (TEX_NUM_FLOAT4_CPU + TEX_NUM_BYTE4_CPU + TEX_NUM_FLOAT_CPU)
+#define TEX_START_HALF4_CPU (TEX_NUM_FLOAT4_CPU + TEX_NUM_BYTE4_CPU + TEX_NUM_FLOAT_CPU + TEX_NUM_BYTE_CPU)
+#define TEX_START_HALF_CPU (TEX_NUM_FLOAT4_CPU + TEX_NUM_BYTE4_CPU + TEX_NUM_FLOAT_CPU + TEX_NUM_BYTE_CPU + TEX_NUM_HALF4_CPU)
-/* CUDA (Fermi) */
-#define TEX_NUM_BYTE4_IMAGES_CUDA 88
-#define TEX_NUM_FLOAT4_IMAGES_CUDA 5
-#define TEX_NUM_FLOAT_IMAGES_CUDA 0
-#define TEX_NUM_BYTE_IMAGES_CUDA 0
-#define TEX_IMAGE_BYTE4_START_CUDA TEX_NUM_FLOAT4_IMAGES_CUDA
-#define TEX_IMAGE_FLOAT_START_CUDA (TEX_NUM_FLOAT4_IMAGES_CUDA + TEX_NUM_BYTE4_IMAGES_CUDA)
-#define TEX_IMAGE_BYTE_START_CUDA (TEX_NUM_FLOAT4_IMAGES_CUDA + TEX_NUM_BYTE4_IMAGES_CUDA + TEX_NUM_BYTE_IMAGES_CUDA)
+/* CUDA (Geforce 4xx and 5xx) */
+#define TEX_NUM_FLOAT4_CUDA 5
+#define TEX_NUM_BYTE4_CUDA 88
+#define TEX_NUM_FLOAT_CUDA 0
+#define TEX_NUM_BYTE_CUDA 0
+#define TEX_NUM_HALF4_CUDA 0
+#define TEX_NUM_HALF_CUDA 0
+#define TEX_START_FLOAT4_CUDA 0
+#define TEX_START_BYTE4_CUDA TEX_NUM_FLOAT4_CUDA
+#define TEX_START_FLOAT_CUDA (TEX_NUM_FLOAT4_CUDA + TEX_NUM_BYTE4_CUDA)
+#define TEX_START_BYTE_CUDA (TEX_NUM_FLOAT4_CUDA + TEX_NUM_BYTE4_CUDA + TEX_NUM_FLOAT_CUDA)
+#define TEX_START_HALF4_CUDA (TEX_NUM_FLOAT4_CUDA + TEX_NUM_BYTE4_CUDA + TEX_NUM_FLOAT_CUDA + TEX_NUM_BYTE_CUDA)
+#define TEX_START_HALF_CUDA (TEX_NUM_FLOAT4_CUDA + TEX_NUM_BYTE4_CUDA + TEX_NUM_FLOAT_CUDA + TEX_NUM_BYTE_CUDA + TEX_NUM_HALF4_CUDA)
-/* CUDA (KEPLER and above) */
-#define TEX_NUM_BYTE4_IMAGES_CUDA_KEPLER 1024
-#define TEX_NUM_FLOAT4_IMAGES_CUDA_KEPLER 1024
-#define TEX_NUM_FLOAT_IMAGES_CUDA_KEPLER 1024
-#define TEX_NUM_BYTE_IMAGES_CUDA_KEPLER 1024
-#define TEX_IMAGE_BYTE4_START_CUDA_KEPLER TEX_NUM_FLOAT4_IMAGES_CUDA_KEPLER
-#define TEX_IMAGE_FLOAT_START_CUDA_KEPLER (TEX_NUM_FLOAT4_IMAGES_CUDA_KEPLER + TEX_NUM_BYTE4_IMAGES_CUDA_KEPLER)
-#define TEX_IMAGE_BYTE_START_CUDA_KEPLER (TEX_NUM_FLOAT4_IMAGES_CUDA_KEPLER + TEX_NUM_BYTE4_IMAGES_CUDA_KEPLER + TEX_NUM_BYTE_IMAGES_CUDA_KEPLER)
+/* CUDA (Kepler, Geforce 6xx and above) */
+#define TEX_NUM_FLOAT4_CUDA_KEPLER 1024
+#define TEX_NUM_BYTE4_CUDA_KEPLER 1024
+#define TEX_NUM_FLOAT_CUDA_KEPLER 1024
+#define TEX_NUM_BYTE_CUDA_KEPLER 1024
+#define TEX_NUM_HALF4_CUDA_KEPLER 0
+#define TEX_NUM_HALF_CUDA_KEPLER 0
+#define TEX_START_FLOAT4_CUDA_KEPLER 0
+#define TEX_START_BYTE4_CUDA_KEPLER TEX_NUM_FLOAT4_CUDA_KEPLER
+#define TEX_START_FLOAT_CUDA_KEPLER (TEX_NUM_FLOAT4_CUDA_KEPLER + TEX_NUM_BYTE4_CUDA_KEPLER)
+#define TEX_START_BYTE_CUDA_KEPLER (TEX_NUM_FLOAT4_CUDA_KEPLER + TEX_NUM_BYTE4_CUDA_KEPLER + TEX_NUM_FLOAT_CUDA_KEPLER)
+#define TEX_START_HALF4_CUDA_KEPLER (TEX_NUM_FLOAT4_CUDA_KEPLER + TEX_NUM_BYTE4_CUDA_KEPLER + TEX_NUM_FLOAT_CUDA_KEPLER + TEX_NUM_BYTE_CUDA_KEPLER)
+#define TEX_START_HALF_CUDA_KEPLER (TEX_NUM_FLOAT4_CUDA_KEPLER + TEX_NUM_BYTE4_CUDA_KEPLER + TEX_NUM_FLOAT_CUDA_KEPLER + TEX_NUM_BYTE_CUDA_KEPLER + TEX_NUM_HALF4_CUDA_KEPLER)
/* OpenCL */
-#define TEX_NUM_BYTE4_IMAGES_OPENCL 1024
-#define TEX_NUM_FLOAT4_IMAGES_OPENCL 1024
-#define TEX_NUM_FLOAT_IMAGES_OPENCL 0
-#define TEX_NUM_BYTE_IMAGES_OPENCL 0
-#define TEX_IMAGE_BYTE4_START_OPENCL TEX_NUM_FLOAT4_IMAGES_OPENCL
-#define TEX_IMAGE_FLOAT_START_OPENCL (TEX_NUM_FLOAT4_IMAGES_OPENCL + TEX_NUM_BYTE4_IMAGES_OPENCL)
-#define TEX_IMAGE_BYTE_START_OPENCL (TEX_NUM_FLOAT4_IMAGES_OPENCL + TEX_NUM_BYTE4_IMAGES_OPENCL + TEX_NUM_BYTE_IMAGES_OPENCL)
+#define TEX_NUM_FLOAT4_OPENCL 1024
+#define TEX_NUM_BYTE4_OPENCL 1024
+#define TEX_NUM_FLOAT_OPENCL 0
+#define TEX_NUM_BYTE_OPENCL 0
+#define TEX_NUM_HALF4_OPENCL 0
+#define TEX_NUM_HALF_OPENCL 0
+#define TEX_START_FLOAT4_OPENCL 0
+#define TEX_START_BYTE4_OPENCL TEX_NUM_FLOAT4_OPENCL
+#define TEX_START_FLOAT_OPENCL (TEX_NUM_FLOAT4_OPENCL + TEX_NUM_BYTE4_OPENCL)
+#define TEX_START_BYTE_OPENCL (TEX_NUM_FLOAT4_OPENCL + TEX_NUM_BYTE4_OPENCL + TEX_NUM_FLOAT_OPENCL)
+#define TEX_START_HALF4_OPENCL (TEX_NUM_FLOAT4_OPENCL + TEX_NUM_BYTE4_OPENCL + TEX_NUM_FLOAT_OPENCL + TEX_NUM_BYTE_OPENCL)
+#define TEX_START_HALF_OPENCL (TEX_NUM_FLOAT4_OPENCL + TEX_NUM_BYTE4_OPENCL + TEX_NUM_FLOAT_OPENCL + TEX_NUM_BYTE_OPENCL + TEX_NUM_HALF4_OPENCL)
/* Color to use when textures are not found. */
diff --git a/intern/cycles/util/util_thread.cpp b/intern/cycles/util/util_thread.cpp
new file mode 100644
index 00000000000..3db8b4bd197
--- /dev/null
+++ b/intern/cycles/util/util_thread.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2011-2016 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "util_thread.h"
+
+#include "util_system.h"
+#include "util_windows.h"
+
+CCL_NAMESPACE_BEGIN
+
+thread::thread(function<void(void)> run_cb, int group)
+ : run_cb_(run_cb),
+ joined_(false),
+ group_(group)
+{
+ pthread_create(&pthread_id_, NULL, run, (void*)this);
+}
+
+thread::~thread()
+{
+ if(!joined_) {
+ join();
+ }
+}
+
+void *thread::run(void *arg)
+{
+ thread *self = (thread*)(arg);
+ if(self->group_ != -1) {
+#ifdef _WIN32
+ HANDLE thread_handle = GetCurrentThread();
+ GROUP_AFFINITY group_affinity = { 0 };
+ int num_threads = system_cpu_group_thread_count(self->group_);
+ group_affinity.Group = self->group_;
+ group_affinity.Mask = (num_threads == 64)
+ ? -1
+ : (1ull << num_threads) - 1;
+ if(SetThreadGroupAffinity(thread_handle, &group_affinity, NULL) == 0) {
+ fprintf(stderr, "Error setting thread affinity.\n");
+ }
+#endif
+ }
+ self->run_cb_();
+ return NULL;
+}
+
+bool thread::join()
+{
+ joined_ = true;
+ return pthread_join(pthread_id_, NULL) == 0;
+}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_thread.h b/intern/cycles/util/util_thread.h
index 59575f31c13..427c633d2ce 100644
--- a/intern/cycles/util/util_thread.h
+++ b/intern/cycles/util/util_thread.h
@@ -52,37 +52,17 @@ typedef boost::condition_variable thread_condition_variable;
class thread {
public:
- thread(function<void(void)> run_cb_)
+ thread(function<void(void)> run_cb, int group = -1);
+ ~thread();
- {
- joined = false;
- run_cb = run_cb_;
-
- pthread_create(&pthread_id, NULL, run, (void*)this);
- }
-
- ~thread()
- {
- if(!joined)
- join();
- }
-
- static void *run(void *arg)
- {
- ((thread*)arg)->run_cb();
- return NULL;
- }
-
- bool join()
- {
- joined = true;
- return pthread_join(pthread_id, NULL) == 0;
- }
+ static void *run(void *arg);
+ bool join();
protected:
- function<void(void)> run_cb;
- pthread_t pthread_id;
- bool joined;
+ function<void(void)> run_cb_;
+ pthread_t pthread_id_;
+ bool joined_;
+ int group_;
};
/* Own wrapper around pthread's spin lock to make it's use easier. */
diff --git a/intern/cycles/util/util_transform.h b/intern/cycles/util/util_transform.h
index f01db64a79b..6fed18a3db8 100644
--- a/intern/cycles/util/util_transform.h
+++ b/intern/cycles/util/util_transform.h
@@ -127,6 +127,19 @@ ccl_device_inline Transform make_transform(float a, float b, float c, float d,
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,
+ 0.0f, 0.0f, 0.0f, 1.0f);
+}
+
#ifndef __KERNEL_GPU__
ccl_device_inline Transform operator*(const Transform a, const Transform b)
diff --git a/intern/cycles/util/util_types.h b/intern/cycles/util/util_types.h
index 972befa185b..257c6ad7491 100644
--- a/intern/cycles/util/util_types.h
+++ b/intern/cycles/util/util_types.h
@@ -37,6 +37,7 @@
#define ccl_device_noinline static
#define ccl_global
#define ccl_constant
+#define ccl_restrict __restrict
#define __KERNEL_WITH_SSE_ALIGN__
#if defined(_WIN32) && !defined(FREE_WINDOWS)
diff --git a/intern/cycles/util/util_windows.cpp b/intern/cycles/util/util_windows.cpp
new file mode 100644
index 00000000000..ee5b3fd73c0
--- /dev/null
+++ b/intern/cycles/util/util_windows.cpp
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2011-2016 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "util_windows.h"
+
+#ifdef _WIN32
+
+CCL_NAMESPACE_BEGIN
+
+#ifdef _M_X64
+# include <VersionHelpers.h>
+#endif
+
+#if _WIN32_WINNT < 0x0601
+tGetActiveProcessorGroupCount *GetActiveProcessorGroupCount;
+tGetActiveProcessorCount *GetActiveProcessorCount;
+tSetThreadGroupAffinity *SetThreadGroupAffinity;
+#endif
+
+static WORD GetActiveProcessorGroupCount_stub()
+{
+ return 1;
+}
+
+static DWORD GetActiveProcessorCount_stub(WORD /*GroupNumber*/)
+{
+ SYSTEM_INFO info;
+ GetSystemInfo(&info);
+ return info.dwNumberOfProcessors;
+}
+
+static BOOL SetThreadGroupAffinity_stub(
+ HANDLE /*hThread*/,
+ const GROUP_AFFINITY * /*GroupAffinity*/,
+ PGROUP_AFFINITY /*PreviousGroupAffinity*/)
+{
+ return TRUE;
+}
+
+static bool supports_numa()
+{
+#ifndef _M_X64
+ return false;
+#else
+ return IsWindows7OrGreater();
+#endif
+}
+
+void util_windows_init_numa_groups()
+{
+ static bool initialized = false;
+ if(initialized) {
+ return;
+ }
+ initialized = true;
+#if _WIN32_WINNT < 0x0601
+ if(!supports_numa()) {
+ /* Use stubs on platforms which doesn't have rean NUMA/Groups. */
+ GetActiveProcessorGroupCount = GetActiveProcessorGroupCount_stub;
+ GetActiveProcessorCount = GetActiveProcessorCount_stub;
+ SetThreadGroupAffinity = SetThreadGroupAffinity_stub;
+ return;
+ }
+ HMODULE kernel = GetModuleHandleA("kernel32.dll");
+# define READ_SYMBOL(sym) sym = (t##sym*)GetProcAddress(kernel, #sym)
+ READ_SYMBOL(GetActiveProcessorGroupCount);
+ READ_SYMBOL(GetActiveProcessorCount);
+ READ_SYMBOL(SetThreadGroupAffinity);
+# undef READ_SUMBOL
+#endif
+}
+
+CCL_NAMESPACE_END
+
+#endif /* _WIN32 */
diff --git a/intern/cycles/util/util_windows.h b/intern/cycles/util/util_windows.h
index f67e34d0f31..ac61d5348c3 100644
--- a/intern/cycles/util/util_windows.h
+++ b/intern/cycles/util/util_windows.h
@@ -31,6 +31,25 @@
#include <windows.h>
+CCL_NAMESPACE_BEGIN
+
+#if _WIN32_WINNT < 0x0601
+typedef WORD tGetActiveProcessorGroupCount();
+typedef DWORD tGetActiveProcessorCount(WORD GroupNumber);
+typedef BOOL tSetThreadGroupAffinity(HANDLE hThread,
+ const GROUP_AFFINITY *GroupAffinity,
+ PGROUP_AFFINITY PreviousGroupAffinity);
+
+extern tGetActiveProcessorGroupCount *GetActiveProcessorGroupCount;
+extern tGetActiveProcessorCount *GetActiveProcessorCount;
+extern tSetThreadGroupAffinity *SetThreadGroupAffinity;
+#endif
+
+/* Make sure NUMA and processor groups API is initialized. */
+void util_windows_init_numa_groups();
+
+CCL_NAMESPACE_END
+
#endif /* WIN32 */
#endif /* __UTIL_WINDOWS_H__ */
diff --git a/intern/decklink/CMakeLists.txt b/intern/decklink/CMakeLists.txt
new file mode 100644
index 00000000000..fbef65cdba4
--- /dev/null
+++ b/intern/decklink/CMakeLists.txt
@@ -0,0 +1,58 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2015, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Blender Foundation.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(INC
+)
+
+set(INC_SYS
+)
+
+set(SRC
+ DeckLinkAPI.cpp
+ DeckLinkAPI.h
+)
+
+if (WIN32)
+ list(APPEND SRC
+ win/DeckLinkAPI_h.h
+ win/DeckLinkAPI_i.c
+ )
+endif()
+
+if (UNIX AND NOT APPLE)
+ list(APPEND SRC
+ linux/DeckLinkAPI.h
+ linux/DeckLinkAPIConfiguration.h
+ linux/DeckLinkAPIDeckControl.h
+ linux/DeckLinkAPIDiscovery.h
+ linux/DeckLinkAPIDispatch.cpp
+ linux/DeckLinkAPIModes.h
+ linux/DeckLinkAPIVersion.h
+ linux/DeckLinkAPITypes.h
+ linux/LinuxCOM.h
+ )
+endif()
+
+blender_add_lib(bf_intern_decklink "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/intern/decklink/DeckLinkAPI.cpp b/intern/decklink/DeckLinkAPI.cpp
new file mode 100644
index 00000000000..aff25af70eb
--- /dev/null
+++ b/intern/decklink/DeckLinkAPI.cpp
@@ -0,0 +1,50 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2015, Blender Foundation
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Blender Foundation.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file decklink/DeckLinkAPI.cpp
+ * \ingroup decklink
+ */
+
+#include "DeckLinkAPI.h"
+
+#ifdef WIN32
+IDeckLinkIterator* BMD_CreateDeckLinkIterator(void)
+{
+ HRESULT result;
+ IDeckLinkIterator* pDLIterator = NULL;
+
+ result = CoCreateInstance(CLSID_CDeckLinkIterator, NULL, CLSCTX_ALL, IID_IDeckLinkIterator, (void**)&pDLIterator);
+ if (FAILED(result))
+ return NULL;
+ return pDLIterator;
+}
+#else
+IDeckLinkIterator* BMD_CreateDeckLinkIterator(void)
+{
+ return CreateDeckLinkIteratorInstance();
+}
+#endif // WIN32
diff --git a/intern/decklink/DeckLinkAPI.h b/intern/decklink/DeckLinkAPI.h
new file mode 100644
index 00000000000..2a429c18c3c
--- /dev/null
+++ b/intern/decklink/DeckLinkAPI.h
@@ -0,0 +1,56 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2015, Blender Foundation
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Blender Foundation.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file decklink/DeckLinkAPI.h
+ * \ingroup decklink
+ */
+
+#ifndef __DECKLINKAPI_H__
+#define __DECKLINKAPI_H__
+
+/* Include the OS specific Declink headers */
+
+#ifdef WIN32
+# include <windows.h>
+# include <objbase.h>
+# include <comutil.h>
+# include "win/DeckLinkAPI_h.h"
+ typedef unsigned int dl_size_t;
+#elif defined(__APPLE__)
+# error "Decklink not supported in OSX"
+#else
+# include "linux/DeckLinkAPI.h"
+ /* Windows COM API uses BOOL, linux uses bool */
+# define BOOL bool
+ typedef uint32_t dl_size_t;
+#endif
+
+
+/* OS independent function to get the device iterator */
+IDeckLinkIterator* BMD_CreateDeckLinkIterator(void);
+
+#endif /* __DECKLINKAPI_H__ */
diff --git a/intern/decklink/linux/DeckLinkAPI.h b/intern/decklink/linux/DeckLinkAPI.h
new file mode 100644
index 00000000000..08bfba39994
--- /dev/null
+++ b/intern/decklink/linux/DeckLinkAPI.h
@@ -0,0 +1,767 @@
+/* -LICENSE-START-
+** Copyright (c) 2014 Blackmagic Design
+**
+** Permission is hereby granted, free of charge, to any person or organization
+** obtaining a copy of the software and accompanying documentation covered by
+** this license (the "Software") to use, reproduce, display, distribute,
+** execute, and transmit the Software, and to prepare derivative works of the
+** Software, and to permit third-parties to whom the Software is furnished to
+** do so, all subject to the following:
+**
+** The copyright notices in the Software and this entire statement, including
+** the above license grant, this restriction and the following disclaimer,
+** must be included in all copies of the Software, in whole or in part, and
+** all derivative works of the Software, unless such copies or derivative
+** works are solely in the form of machine-executable object code generated by
+** a source language processor.
+**
+** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+** DEALINGS IN THE SOFTWARE.
+** -LICENSE-END-
+*/
+
+#ifndef BMD_DECKLINKAPI_H
+#define BMD_DECKLINKAPI_H
+
+
+#ifndef BMD_CONST
+ #if defined(_MSC_VER)
+ #define BMD_CONST __declspec(selectany) static const
+ #else
+ #define BMD_CONST static const
+ #endif
+#endif
+
+/* DeckLink API */
+
+#include <stdint.h>
+#include "LinuxCOM.h"
+
+#include "DeckLinkAPITypes.h"
+#include "DeckLinkAPIModes.h"
+#include "DeckLinkAPIDiscovery.h"
+#include "DeckLinkAPIConfiguration.h"
+#include "DeckLinkAPIDeckControl.h"
+
+#define BLACKMAGIC_DECKLINK_API_MAGIC 1
+
+// Type Declarations
+
+
+// Interface ID Declarations
+
+BMD_CONST REFIID IID_IDeckLinkVideoOutputCallback = /* 20AA5225-1958-47CB-820B-80A8D521A6EE */ {0x20,0xAA,0x52,0x25,0x19,0x58,0x47,0xCB,0x82,0x0B,0x80,0xA8,0xD5,0x21,0xA6,0xEE};
+BMD_CONST REFIID IID_IDeckLinkInputCallback = /* DD04E5EC-7415-42AB-AE4A-E80C4DFC044A */ {0xDD,0x04,0xE5,0xEC,0x74,0x15,0x42,0xAB,0xAE,0x4A,0xE8,0x0C,0x4D,0xFC,0x04,0x4A};
+BMD_CONST REFIID IID_IDeckLinkMemoryAllocator = /* B36EB6E7-9D29-4AA8-92EF-843B87A289E8 */ {0xB3,0x6E,0xB6,0xE7,0x9D,0x29,0x4A,0xA8,0x92,0xEF,0x84,0x3B,0x87,0xA2,0x89,0xE8};
+BMD_CONST REFIID IID_IDeckLinkAudioOutputCallback = /* 403C681B-7F46-4A12-B993-2BB127084EE6 */ {0x40,0x3C,0x68,0x1B,0x7F,0x46,0x4A,0x12,0xB9,0x93,0x2B,0xB1,0x27,0x08,0x4E,0xE6};
+BMD_CONST REFIID IID_IDeckLinkIterator = /* 50FB36CD-3063-4B73-BDBB-958087F2D8BA */ {0x50,0xFB,0x36,0xCD,0x30,0x63,0x4B,0x73,0xBD,0xBB,0x95,0x80,0x87,0xF2,0xD8,0xBA};
+BMD_CONST REFIID IID_IDeckLinkAPIInformation = /* 7BEA3C68-730D-4322-AF34-8A7152B532A4 */ {0x7B,0xEA,0x3C,0x68,0x73,0x0D,0x43,0x22,0xAF,0x34,0x8A,0x71,0x52,0xB5,0x32,0xA4};
+BMD_CONST REFIID IID_IDeckLinkOutput = /* CC5C8A6E-3F2F-4B3A-87EA-FD78AF300564 */ {0xCC,0x5C,0x8A,0x6E,0x3F,0x2F,0x4B,0x3A,0x87,0xEA,0xFD,0x78,0xAF,0x30,0x05,0x64};
+BMD_CONST REFIID IID_IDeckLinkInput = /* AF22762B-DFAC-4846-AA79-FA8883560995 */ {0xAF,0x22,0x76,0x2B,0xDF,0xAC,0x48,0x46,0xAA,0x79,0xFA,0x88,0x83,0x56,0x09,0x95};
+BMD_CONST REFIID IID_IDeckLinkVideoFrame = /* 3F716FE0-F023-4111-BE5D-EF4414C05B17 */ {0x3F,0x71,0x6F,0xE0,0xF0,0x23,0x41,0x11,0xBE,0x5D,0xEF,0x44,0x14,0xC0,0x5B,0x17};
+BMD_CONST REFIID IID_IDeckLinkMutableVideoFrame = /* 69E2639F-40DA-4E19-B6F2-20ACE815C390 */ {0x69,0xE2,0x63,0x9F,0x40,0xDA,0x4E,0x19,0xB6,0xF2,0x20,0xAC,0xE8,0x15,0xC3,0x90};
+BMD_CONST REFIID IID_IDeckLinkVideoFrame3DExtensions = /* DA0F7E4A-EDC7-48A8-9CDD-2DB51C729CD7 */ {0xDA,0x0F,0x7E,0x4A,0xED,0xC7,0x48,0xA8,0x9C,0xDD,0x2D,0xB5,0x1C,0x72,0x9C,0xD7};
+BMD_CONST REFIID IID_IDeckLinkVideoInputFrame = /* 05CFE374-537C-4094-9A57-680525118F44 */ {0x05,0xCF,0xE3,0x74,0x53,0x7C,0x40,0x94,0x9A,0x57,0x68,0x05,0x25,0x11,0x8F,0x44};
+BMD_CONST REFIID IID_IDeckLinkVideoFrameAncillary = /* 732E723C-D1A4-4E29-9E8E-4A88797A0004 */ {0x73,0x2E,0x72,0x3C,0xD1,0xA4,0x4E,0x29,0x9E,0x8E,0x4A,0x88,0x79,0x7A,0x00,0x04};
+BMD_CONST REFIID IID_IDeckLinkAudioInputPacket = /* E43D5870-2894-11DE-8C30-0800200C9A66 */ {0xE4,0x3D,0x58,0x70,0x28,0x94,0x11,0xDE,0x8C,0x30,0x08,0x00,0x20,0x0C,0x9A,0x66};
+BMD_CONST REFIID IID_IDeckLinkScreenPreviewCallback = /* B1D3F49A-85FE-4C5D-95C8-0B5D5DCCD438 */ {0xB1,0xD3,0xF4,0x9A,0x85,0xFE,0x4C,0x5D,0x95,0xC8,0x0B,0x5D,0x5D,0xCC,0xD4,0x38};
+BMD_CONST REFIID IID_IDeckLinkGLScreenPreviewHelper = /* 504E2209-CAC7-4C1A-9FB4-C5BB6274D22F */ {0x50,0x4E,0x22,0x09,0xCA,0xC7,0x4C,0x1A,0x9F,0xB4,0xC5,0xBB,0x62,0x74,0xD2,0x2F};
+BMD_CONST REFIID IID_IDeckLinkNotificationCallback = /* B002A1EC-070D-4288-8289-BD5D36E5FF0D */ {0xB0,0x02,0xA1,0xEC,0x07,0x0D,0x42,0x88,0x82,0x89,0xBD,0x5D,0x36,0xE5,0xFF,0x0D};
+BMD_CONST REFIID IID_IDeckLinkNotification = /* 0A1FB207-E215-441B-9B19-6FA1575946C5 */ {0x0A,0x1F,0xB2,0x07,0xE2,0x15,0x44,0x1B,0x9B,0x19,0x6F,0xA1,0x57,0x59,0x46,0xC5};
+BMD_CONST REFIID IID_IDeckLinkAttributes = /* ABC11843-D966-44CB-96E2-A1CB5D3135C4 */ {0xAB,0xC1,0x18,0x43,0xD9,0x66,0x44,0xCB,0x96,0xE2,0xA1,0xCB,0x5D,0x31,0x35,0xC4};
+BMD_CONST REFIID IID_IDeckLinkKeyer = /* 89AFCAF5-65F8-421E-98F7-96FE5F5BFBA3 */ {0x89,0xAF,0xCA,0xF5,0x65,0xF8,0x42,0x1E,0x98,0xF7,0x96,0xFE,0x5F,0x5B,0xFB,0xA3};
+BMD_CONST REFIID IID_IDeckLinkVideoConversion = /* 3BBCB8A2-DA2C-42D9-B5D8-88083644E99A */ {0x3B,0xBC,0xB8,0xA2,0xDA,0x2C,0x42,0xD9,0xB5,0xD8,0x88,0x08,0x36,0x44,0xE9,0x9A};
+BMD_CONST REFIID IID_IDeckLinkDeviceNotificationCallback = /* 4997053B-0ADF-4CC8-AC70-7A50C4BE728F */ {0x49,0x97,0x05,0x3B,0x0A,0xDF,0x4C,0xC8,0xAC,0x70,0x7A,0x50,0xC4,0xBE,0x72,0x8F};
+BMD_CONST REFIID IID_IDeckLinkDiscovery = /* CDBF631C-BC76-45FA-B44D-C55059BC6101 */ {0xCD,0xBF,0x63,0x1C,0xBC,0x76,0x45,0xFA,0xB4,0x4D,0xC5,0x50,0x59,0xBC,0x61,0x01};
+
+/* Enum BMDVideoOutputFlags - Flags to control the output of ancillary data along with video. */
+
+typedef uint32_t BMDVideoOutputFlags;
+enum _BMDVideoOutputFlags {
+ bmdVideoOutputFlagDefault = 0,
+ bmdVideoOutputVANC = 1 << 0,
+ bmdVideoOutputVITC = 1 << 1,
+ bmdVideoOutputRP188 = 1 << 2,
+ bmdVideoOutputDualStream3D = 1 << 4
+};
+
+/* Enum BMDFrameFlags - Frame flags */
+
+typedef uint32_t BMDFrameFlags;
+enum _BMDFrameFlags {
+ bmdFrameFlagDefault = 0,
+ bmdFrameFlagFlipVertical = 1 << 0,
+
+ /* Flags that are applicable only to instances of IDeckLinkVideoInputFrame */
+
+ bmdFrameHasNoInputSource = 1 << 31
+};
+
+/* Enum BMDVideoInputFlags - Flags applicable to video input */
+
+typedef uint32_t BMDVideoInputFlags;
+enum _BMDVideoInputFlags {
+ bmdVideoInputFlagDefault = 0,
+ bmdVideoInputEnableFormatDetection = 1 << 0,
+ bmdVideoInputDualStream3D = 1 << 1
+};
+
+/* Enum BMDVideoInputFormatChangedEvents - Bitmask passed to the VideoInputFormatChanged notification to identify the properties of the input signal that have changed */
+
+typedef uint32_t BMDVideoInputFormatChangedEvents;
+enum _BMDVideoInputFormatChangedEvents {
+ bmdVideoInputDisplayModeChanged = 1 << 0,
+ bmdVideoInputFieldDominanceChanged = 1 << 1,
+ bmdVideoInputColorspaceChanged = 1 << 2
+};
+
+/* Enum BMDDetectedVideoInputFormatFlags - Flags passed to the VideoInputFormatChanged notification to describe the detected video input signal */
+
+typedef uint32_t BMDDetectedVideoInputFormatFlags;
+enum _BMDDetectedVideoInputFormatFlags {
+ bmdDetectedVideoInputYCbCr422 = 1 << 0,
+ bmdDetectedVideoInputRGB444 = 1 << 1,
+ bmdDetectedVideoInputDualStream3D = 1 << 2
+};
+
+/* Enum BMDDeckLinkCapturePassthroughMode - Enumerates whether the video output is electrically connected to the video input or if the clean switching mode is enabled */
+
+typedef uint32_t BMDDeckLinkCapturePassthroughMode;
+enum _BMDDeckLinkCapturePassthroughMode {
+ bmdDeckLinkCapturePassthroughModeDirect = /* 'pdir' */ 0x70646972,
+ bmdDeckLinkCapturePassthroughModeCleanSwitch = /* 'pcln' */ 0x70636C6E
+};
+
+/* Enum BMDOutputFrameCompletionResult - Frame Completion Callback */
+
+typedef uint32_t BMDOutputFrameCompletionResult;
+enum _BMDOutputFrameCompletionResult {
+ bmdOutputFrameCompleted,
+ bmdOutputFrameDisplayedLate,
+ bmdOutputFrameDropped,
+ bmdOutputFrameFlushed
+};
+
+/* Enum BMDReferenceStatus - GenLock input status */
+
+typedef uint32_t BMDReferenceStatus;
+enum _BMDReferenceStatus {
+ bmdReferenceNotSupportedByHardware = 1 << 0,
+ bmdReferenceLocked = 1 << 1
+};
+
+/* Enum BMDAudioSampleRate - Audio sample rates supported for output/input */
+
+typedef uint32_t BMDAudioSampleRate;
+enum _BMDAudioSampleRate {
+ bmdAudioSampleRate48kHz = 48000
+};
+
+/* Enum BMDAudioSampleType - Audio sample sizes supported for output/input */
+
+typedef uint32_t BMDAudioSampleType;
+enum _BMDAudioSampleType {
+ bmdAudioSampleType16bitInteger = 16,
+ bmdAudioSampleType32bitInteger = 32
+};
+
+/* Enum BMDAudioOutputStreamType - Audio output stream type */
+
+typedef uint32_t BMDAudioOutputStreamType;
+enum _BMDAudioOutputStreamType {
+ bmdAudioOutputStreamContinuous,
+ bmdAudioOutputStreamContinuousDontResample,
+ bmdAudioOutputStreamTimestamped
+};
+
+/* Enum BMDDisplayModeSupport - Output mode supported flags */
+
+typedef uint32_t BMDDisplayModeSupport;
+enum _BMDDisplayModeSupport {
+ bmdDisplayModeNotSupported = 0,
+ bmdDisplayModeSupported,
+ bmdDisplayModeSupportedWithConversion
+};
+
+/* Enum BMDTimecodeFormat - Timecode formats for frame metadata */
+
+typedef uint32_t BMDTimecodeFormat;
+enum _BMDTimecodeFormat {
+ bmdTimecodeRP188VITC1 = /* 'rpv1' */ 0x72707631, // RP188 timecode where DBB1 equals VITC1 (line 9)
+ bmdTimecodeRP188VITC2 = /* 'rp12' */ 0x72703132, // RP188 timecode where DBB1 equals VITC2 (line 9 for progressive or line 571 for interlaced/PsF)
+ bmdTimecodeRP188LTC = /* 'rplt' */ 0x72706C74, // RP188 timecode where DBB1 equals LTC (line 10)
+ bmdTimecodeRP188Any = /* 'rp18' */ 0x72703138, // For capture: return the first valid timecode in {VITC1, LTC ,VITC2} - For playback: set the timecode as VITC1
+ bmdTimecodeVITC = /* 'vitc' */ 0x76697463,
+ bmdTimecodeVITCField2 = /* 'vit2' */ 0x76697432,
+ bmdTimecodeSerial = /* 'seri' */ 0x73657269
+};
+
+/* Enum BMDAnalogVideoFlags - Analog video display flags */
+
+typedef uint32_t BMDAnalogVideoFlags;
+enum _BMDAnalogVideoFlags {
+ bmdAnalogVideoFlagCompositeSetup75 = 1 << 0,
+ bmdAnalogVideoFlagComponentBetacamLevels = 1 << 1
+};
+
+/* Enum BMDAudioOutputAnalogAESSwitch - Audio output Analog/AESEBU switch */
+
+typedef uint32_t BMDAudioOutputAnalogAESSwitch;
+enum _BMDAudioOutputAnalogAESSwitch {
+ bmdAudioOutputSwitchAESEBU = /* 'aes ' */ 0x61657320,
+ bmdAudioOutputSwitchAnalog = /* 'anlg' */ 0x616E6C67
+};
+
+/* Enum BMDVideoOutputConversionMode - Video/audio conversion mode */
+
+typedef uint32_t BMDVideoOutputConversionMode;
+enum _BMDVideoOutputConversionMode {
+ bmdNoVideoOutputConversion = /* 'none' */ 0x6E6F6E65,
+ bmdVideoOutputLetterboxDownconversion = /* 'ltbx' */ 0x6C746278,
+ bmdVideoOutputAnamorphicDownconversion = /* 'amph' */ 0x616D7068,
+ bmdVideoOutputHD720toHD1080Conversion = /* '720c' */ 0x37323063,
+ bmdVideoOutputHardwareLetterboxDownconversion = /* 'HWlb' */ 0x48576C62,
+ bmdVideoOutputHardwareAnamorphicDownconversion = /* 'HWam' */ 0x4857616D,
+ bmdVideoOutputHardwareCenterCutDownconversion = /* 'HWcc' */ 0x48576363,
+ bmdVideoOutputHardware720p1080pCrossconversion = /* 'xcap' */ 0x78636170,
+ bmdVideoOutputHardwareAnamorphic720pUpconversion = /* 'ua7p' */ 0x75613770,
+ bmdVideoOutputHardwareAnamorphic1080iUpconversion = /* 'ua1i' */ 0x75613169,
+ bmdVideoOutputHardwareAnamorphic149To720pUpconversion = /* 'u47p' */ 0x75343770,
+ bmdVideoOutputHardwareAnamorphic149To1080iUpconversion = /* 'u41i' */ 0x75343169,
+ bmdVideoOutputHardwarePillarbox720pUpconversion = /* 'up7p' */ 0x75703770,
+ bmdVideoOutputHardwarePillarbox1080iUpconversion = /* 'up1i' */ 0x75703169
+};
+
+/* Enum BMDVideoInputConversionMode - Video input conversion mode */
+
+typedef uint32_t BMDVideoInputConversionMode;
+enum _BMDVideoInputConversionMode {
+ bmdNoVideoInputConversion = /* 'none' */ 0x6E6F6E65,
+ bmdVideoInputLetterboxDownconversionFromHD1080 = /* '10lb' */ 0x31306C62,
+ bmdVideoInputAnamorphicDownconversionFromHD1080 = /* '10am' */ 0x3130616D,
+ bmdVideoInputLetterboxDownconversionFromHD720 = /* '72lb' */ 0x37326C62,
+ bmdVideoInputAnamorphicDownconversionFromHD720 = /* '72am' */ 0x3732616D,
+ bmdVideoInputLetterboxUpconversion = /* 'lbup' */ 0x6C627570,
+ bmdVideoInputAnamorphicUpconversion = /* 'amup' */ 0x616D7570
+};
+
+/* Enum BMDVideo3DPackingFormat - Video 3D packing format */
+
+typedef uint32_t BMDVideo3DPackingFormat;
+enum _BMDVideo3DPackingFormat {
+ bmdVideo3DPackingSidebySideHalf = /* 'sbsh' */ 0x73627368,
+ bmdVideo3DPackingLinebyLine = /* 'lbyl' */ 0x6C62796C,
+ bmdVideo3DPackingTopAndBottom = /* 'tabo' */ 0x7461626F,
+ bmdVideo3DPackingFramePacking = /* 'frpk' */ 0x6672706B,
+ bmdVideo3DPackingLeftOnly = /* 'left' */ 0x6C656674,
+ bmdVideo3DPackingRightOnly = /* 'righ' */ 0x72696768
+};
+
+/* Enum BMDIdleVideoOutputOperation - Video output operation when not playing video */
+
+typedef uint32_t BMDIdleVideoOutputOperation;
+enum _BMDIdleVideoOutputOperation {
+ bmdIdleVideoOutputBlack = /* 'blac' */ 0x626C6163,
+ bmdIdleVideoOutputLastFrame = /* 'lafa' */ 0x6C616661,
+ bmdIdleVideoOutputDesktop = /* 'desk' */ 0x6465736B
+};
+
+/* Enum BMDDeckLinkAttributeID - DeckLink Attribute ID */
+
+typedef uint32_t BMDDeckLinkAttributeID;
+enum _BMDDeckLinkAttributeID {
+
+ /* Flags */
+
+ BMDDeckLinkSupportsInternalKeying = /* 'keyi' */ 0x6B657969,
+ BMDDeckLinkSupportsExternalKeying = /* 'keye' */ 0x6B657965,
+ BMDDeckLinkSupportsHDKeying = /* 'keyh' */ 0x6B657968,
+ BMDDeckLinkSupportsInputFormatDetection = /* 'infd' */ 0x696E6664,
+ BMDDeckLinkHasReferenceInput = /* 'hrin' */ 0x6872696E,
+ BMDDeckLinkHasSerialPort = /* 'hspt' */ 0x68737074,
+ BMDDeckLinkHasAnalogVideoOutputGain = /* 'avog' */ 0x61766F67,
+ BMDDeckLinkCanOnlyAdjustOverallVideoOutputGain = /* 'ovog' */ 0x6F766F67,
+ BMDDeckLinkHasVideoInputAntiAliasingFilter = /* 'aafl' */ 0x6161666C,
+ BMDDeckLinkHasBypass = /* 'byps' */ 0x62797073,
+ BMDDeckLinkSupportsDesktopDisplay = /* 'extd' */ 0x65787464,
+ BMDDeckLinkSupportsClockTimingAdjustment = /* 'ctad' */ 0x63746164,
+ BMDDeckLinkSupportsFullDuplex = /* 'fdup' */ 0x66647570,
+ BMDDeckLinkSupportsFullFrameReferenceInputTimingOffset = /* 'frin' */ 0x6672696E,
+ BMDDeckLinkSupportsSMPTELevelAOutput = /* 'lvla' */ 0x6C766C61,
+ BMDDeckLinkSupportsDualLinkSDI = /* 'sdls' */ 0x73646C73,
+ BMDDeckLinkSupportsIdleOutput = /* 'idou' */ 0x69646F75,
+
+ /* Integers */
+
+ BMDDeckLinkMaximumAudioChannels = /* 'mach' */ 0x6D616368,
+ BMDDeckLinkMaximumAnalogAudioChannels = /* 'aach' */ 0x61616368,
+ BMDDeckLinkNumberOfSubDevices = /* 'nsbd' */ 0x6E736264,
+ BMDDeckLinkSubDeviceIndex = /* 'subi' */ 0x73756269,
+ BMDDeckLinkPersistentID = /* 'peid' */ 0x70656964,
+ BMDDeckLinkTopologicalID = /* 'toid' */ 0x746F6964,
+ BMDDeckLinkVideoOutputConnections = /* 'vocn' */ 0x766F636E,
+ BMDDeckLinkVideoInputConnections = /* 'vicn' */ 0x7669636E,
+ BMDDeckLinkAudioOutputConnections = /* 'aocn' */ 0x616F636E,
+ BMDDeckLinkAudioInputConnections = /* 'aicn' */ 0x6169636E,
+ BMDDeckLinkDeviceBusyState = /* 'dbst' */ 0x64627374,
+ BMDDeckLinkVideoIOSupport = /* 'vios' */ 0x76696F73, // Returns a BMDVideoIOSupport bit field
+
+ /* Floats */
+
+ BMDDeckLinkVideoInputGainMinimum = /* 'vigm' */ 0x7669676D,
+ BMDDeckLinkVideoInputGainMaximum = /* 'vigx' */ 0x76696778,
+ BMDDeckLinkVideoOutputGainMinimum = /* 'vogm' */ 0x766F676D,
+ BMDDeckLinkVideoOutputGainMaximum = /* 'vogx' */ 0x766F6778,
+
+ /* Strings */
+
+ BMDDeckLinkSerialPortDeviceName = /* 'slpn' */ 0x736C706E
+};
+
+/* Enum BMDDeckLinkAPIInformationID - DeckLinkAPI information ID */
+
+typedef uint32_t BMDDeckLinkAPIInformationID;
+enum _BMDDeckLinkAPIInformationID {
+ BMDDeckLinkAPIVersion = /* 'vers' */ 0x76657273
+};
+
+/* Enum BMDDeviceBusyState - Current device busy state */
+
+typedef uint32_t BMDDeviceBusyState;
+enum _BMDDeviceBusyState {
+ bmdDeviceCaptureBusy = 1 << 0,
+ bmdDevicePlaybackBusy = 1 << 1,
+ bmdDeviceSerialPortBusy = 1 << 2
+};
+
+/* Enum BMDVideoIOSupport - Device video input/output support */
+
+typedef uint32_t BMDVideoIOSupport;
+enum _BMDVideoIOSupport {
+ bmdDeviceSupportsCapture = 1 << 0,
+ bmdDeviceSupportsPlayback = 1 << 1
+};
+
+/* Enum BMD3DPreviewFormat - Linked Frame preview format */
+
+typedef uint32_t BMD3DPreviewFormat;
+enum _BMD3DPreviewFormat {
+ bmd3DPreviewFormatDefault = /* 'defa' */ 0x64656661,
+ bmd3DPreviewFormatLeftOnly = /* 'left' */ 0x6C656674,
+ bmd3DPreviewFormatRightOnly = /* 'righ' */ 0x72696768,
+ bmd3DPreviewFormatSideBySide = /* 'side' */ 0x73696465,
+ bmd3DPreviewFormatTopBottom = /* 'topb' */ 0x746F7062
+};
+
+/* Enum BMDNotifications - Events that can be subscribed through IDeckLinkNotification */
+
+typedef uint32_t BMDNotifications;
+enum _BMDNotifications {
+ bmdPreferencesChanged = /* 'pref' */ 0x70726566
+};
+
+#if defined(__cplusplus)
+
+// Forward Declarations
+
+class IDeckLinkVideoOutputCallback;
+class IDeckLinkInputCallback;
+class IDeckLinkMemoryAllocator;
+class IDeckLinkAudioOutputCallback;
+class IDeckLinkIterator;
+class IDeckLinkAPIInformation;
+class IDeckLinkOutput;
+class IDeckLinkInput;
+class IDeckLinkVideoFrame;
+class IDeckLinkMutableVideoFrame;
+class IDeckLinkVideoFrame3DExtensions;
+class IDeckLinkVideoInputFrame;
+class IDeckLinkVideoFrameAncillary;
+class IDeckLinkAudioInputPacket;
+class IDeckLinkScreenPreviewCallback;
+class IDeckLinkGLScreenPreviewHelper;
+class IDeckLinkNotificationCallback;
+class IDeckLinkNotification;
+class IDeckLinkAttributes;
+class IDeckLinkKeyer;
+class IDeckLinkVideoConversion;
+class IDeckLinkDeviceNotificationCallback;
+class IDeckLinkDiscovery;
+
+/* Interface IDeckLinkVideoOutputCallback - Frame completion callback. */
+
+class IDeckLinkVideoOutputCallback : public IUnknown
+{
+public:
+ virtual HRESULT ScheduledFrameCompleted (/* in */ IDeckLinkVideoFrame *completedFrame, /* in */ BMDOutputFrameCompletionResult result) = 0;
+ virtual HRESULT ScheduledPlaybackHasStopped (void) = 0;
+
+protected:
+ virtual ~IDeckLinkVideoOutputCallback () {} // call Release method to drop reference count
+};
+
+/* Interface IDeckLinkInputCallback - Frame arrival callback. */
+
+class IDeckLinkInputCallback : public IUnknown
+{
+public:
+ virtual HRESULT VideoInputFormatChanged (/* in */ BMDVideoInputFormatChangedEvents notificationEvents, /* in */ IDeckLinkDisplayMode *newDisplayMode, /* in */ BMDDetectedVideoInputFormatFlags detectedSignalFlags) = 0;
+ virtual HRESULT VideoInputFrameArrived (/* in */ IDeckLinkVideoInputFrame* videoFrame, /* in */ IDeckLinkAudioInputPacket* audioPacket) = 0;
+
+protected:
+ virtual ~IDeckLinkInputCallback () {} // call Release method to drop reference count
+};
+
+/* Interface IDeckLinkMemoryAllocator - Memory allocator for video frames. */
+
+class IDeckLinkMemoryAllocator : public IUnknown
+{
+public:
+ virtual HRESULT AllocateBuffer (/* in */ uint32_t bufferSize, /* out */ void **allocatedBuffer) = 0;
+ virtual HRESULT ReleaseBuffer (/* in */ void *buffer) = 0;
+
+ virtual HRESULT Commit (void) = 0;
+ virtual HRESULT Decommit (void) = 0;
+};
+
+/* Interface IDeckLinkAudioOutputCallback - Optional callback to allow audio samples to be pulled as required. */
+
+class IDeckLinkAudioOutputCallback : public IUnknown
+{
+public:
+ virtual HRESULT RenderAudioSamples (/* in */ bool preroll) = 0;
+};
+
+/* Interface IDeckLinkIterator - enumerates installed DeckLink hardware */
+
+class IDeckLinkIterator : public IUnknown
+{
+public:
+ virtual HRESULT Next (/* out */ IDeckLink **deckLinkInstance) = 0;
+};
+
+/* Interface IDeckLinkAPIInformation - DeckLinkAPI attribute interface */
+
+class IDeckLinkAPIInformation : public IUnknown
+{
+public:
+ virtual HRESULT GetFlag (/* in */ BMDDeckLinkAPIInformationID cfgID, /* out */ bool *value) = 0;
+ virtual HRESULT GetInt (/* in */ BMDDeckLinkAPIInformationID cfgID, /* out */ int64_t *value) = 0;
+ virtual HRESULT GetFloat (/* in */ BMDDeckLinkAPIInformationID cfgID, /* out */ double *value) = 0;
+ virtual HRESULT GetString (/* in */ BMDDeckLinkAPIInformationID cfgID, /* out */ const char **value) = 0;
+
+protected:
+ virtual ~IDeckLinkAPIInformation () {} // call Release method to drop reference count
+};
+
+/* Interface IDeckLinkOutput - Created by QueryInterface from IDeckLink. */
+
+class IDeckLinkOutput : public IUnknown
+{
+public:
+ virtual HRESULT DoesSupportVideoMode (/* in */ BMDDisplayMode displayMode, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDVideoOutputFlags flags, /* out */ BMDDisplayModeSupport *result, /* out */ IDeckLinkDisplayMode **resultDisplayMode) = 0;
+ virtual HRESULT GetDisplayModeIterator (/* out */ IDeckLinkDisplayModeIterator **iterator) = 0;
+
+ virtual HRESULT SetScreenPreviewCallback (/* in */ IDeckLinkScreenPreviewCallback *previewCallback) = 0;
+
+ /* Video Output */
+
+ virtual HRESULT EnableVideoOutput (/* in */ BMDDisplayMode displayMode, /* in */ BMDVideoOutputFlags flags) = 0;
+ virtual HRESULT DisableVideoOutput (void) = 0;
+
+ virtual HRESULT SetVideoOutputFrameMemoryAllocator (/* in */ IDeckLinkMemoryAllocator *theAllocator) = 0;
+ virtual HRESULT CreateVideoFrame (/* in */ int32_t width, /* in */ int32_t height, /* in */ int32_t rowBytes, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDFrameFlags flags, /* out */ IDeckLinkMutableVideoFrame **outFrame) = 0;
+ virtual HRESULT CreateAncillaryData (/* in */ BMDPixelFormat pixelFormat, /* out */ IDeckLinkVideoFrameAncillary **outBuffer) = 0;
+
+ virtual HRESULT DisplayVideoFrameSync (/* in */ IDeckLinkVideoFrame *theFrame) = 0;
+ virtual HRESULT ScheduleVideoFrame (/* in */ IDeckLinkVideoFrame *theFrame, /* in */ BMDTimeValue displayTime, /* in */ BMDTimeValue displayDuration, /* in */ BMDTimeScale timeScale) = 0;
+ virtual HRESULT SetScheduledFrameCompletionCallback (/* in */ IDeckLinkVideoOutputCallback *theCallback) = 0;
+ virtual HRESULT GetBufferedVideoFrameCount (/* out */ uint32_t *bufferedFrameCount) = 0;
+
+ /* Audio Output */
+
+ virtual HRESULT EnableAudioOutput (/* in */ BMDAudioSampleRate sampleRate, /* in */ BMDAudioSampleType sampleType, /* in */ uint32_t channelCount, /* in */ BMDAudioOutputStreamType streamType) = 0;
+ virtual HRESULT DisableAudioOutput (void) = 0;
+
+ virtual HRESULT WriteAudioSamplesSync (/* in */ void *buffer, /* in */ uint32_t sampleFrameCount, /* out */ uint32_t *sampleFramesWritten) = 0;
+
+ virtual HRESULT BeginAudioPreroll (void) = 0;
+ virtual HRESULT EndAudioPreroll (void) = 0;
+ virtual HRESULT ScheduleAudioSamples (/* in */ void *buffer, /* in */ uint32_t sampleFrameCount, /* in */ BMDTimeValue streamTime, /* in */ BMDTimeScale timeScale, /* out */ uint32_t *sampleFramesWritten) = 0;
+
+ virtual HRESULT GetBufferedAudioSampleFrameCount (/* out */ uint32_t *bufferedSampleFrameCount) = 0;
+ virtual HRESULT FlushBufferedAudioSamples (void) = 0;
+
+ virtual HRESULT SetAudioCallback (/* in */ IDeckLinkAudioOutputCallback *theCallback) = 0;
+
+ /* Output Control */
+
+ virtual HRESULT StartScheduledPlayback (/* in */ BMDTimeValue playbackStartTime, /* in */ BMDTimeScale timeScale, /* in */ double playbackSpeed) = 0;
+ virtual HRESULT StopScheduledPlayback (/* in */ BMDTimeValue stopPlaybackAtTime, /* out */ BMDTimeValue *actualStopTime, /* in */ BMDTimeScale timeScale) = 0;
+ virtual HRESULT IsScheduledPlaybackRunning (/* out */ bool *active) = 0;
+ virtual HRESULT GetScheduledStreamTime (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue *streamTime, /* out */ double *playbackSpeed) = 0;
+ virtual HRESULT GetReferenceStatus (/* out */ BMDReferenceStatus *referenceStatus) = 0;
+
+ /* Hardware Timing */
+
+ virtual HRESULT GetHardwareReferenceClock (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue *hardwareTime, /* out */ BMDTimeValue *timeInFrame, /* out */ BMDTimeValue *ticksPerFrame) = 0;
+ virtual HRESULT GetFrameCompletionReferenceTimestamp (/* in */ IDeckLinkVideoFrame *theFrame, /* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue *frameCompletionTimestamp) = 0;
+
+protected:
+ virtual ~IDeckLinkOutput () {} // call Release method to drop reference count
+};
+
+/* Interface IDeckLinkInput - Created by QueryInterface from IDeckLink. */
+
+class IDeckLinkInput : public IUnknown
+{
+public:
+ virtual HRESULT DoesSupportVideoMode (/* in */ BMDDisplayMode displayMode, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDVideoInputFlags flags, /* out */ BMDDisplayModeSupport *result, /* out */ IDeckLinkDisplayMode **resultDisplayMode) = 0;
+ virtual HRESULT GetDisplayModeIterator (/* out */ IDeckLinkDisplayModeIterator **iterator) = 0;
+
+ virtual HRESULT SetScreenPreviewCallback (/* in */ IDeckLinkScreenPreviewCallback *previewCallback) = 0;
+
+ /* Video Input */
+
+ virtual HRESULT EnableVideoInput (/* in */ BMDDisplayMode displayMode, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDVideoInputFlags flags) = 0;
+ virtual HRESULT DisableVideoInput (void) = 0;
+ virtual HRESULT GetAvailableVideoFrameCount (/* out */ uint32_t *availableFrameCount) = 0;
+ virtual HRESULT SetVideoInputFrameMemoryAllocator (/* in */ IDeckLinkMemoryAllocator *theAllocator) = 0;
+
+ /* Audio Input */
+
+ virtual HRESULT EnableAudioInput (/* in */ BMDAudioSampleRate sampleRate, /* in */ BMDAudioSampleType sampleType, /* in */ uint32_t channelCount) = 0;
+ virtual HRESULT DisableAudioInput (void) = 0;
+ virtual HRESULT GetAvailableAudioSampleFrameCount (/* out */ uint32_t *availableSampleFrameCount) = 0;
+
+ /* Input Control */
+
+ virtual HRESULT StartStreams (void) = 0;
+ virtual HRESULT StopStreams (void) = 0;
+ virtual HRESULT PauseStreams (void) = 0;
+ virtual HRESULT FlushStreams (void) = 0;
+ virtual HRESULT SetCallback (/* in */ IDeckLinkInputCallback *theCallback) = 0;
+
+ /* Hardware Timing */
+
+ virtual HRESULT GetHardwareReferenceClock (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue *hardwareTime, /* out */ BMDTimeValue *timeInFrame, /* out */ BMDTimeValue *ticksPerFrame) = 0;
+
+protected:
+ virtual ~IDeckLinkInput () {} // call Release method to drop reference count
+};
+
+/* Interface IDeckLinkVideoFrame - Interface to encapsulate a video frame; can be caller-implemented. */
+
+class IDeckLinkVideoFrame : public IUnknown
+{
+public:
+ virtual long GetWidth (void) = 0;
+ virtual long GetHeight (void) = 0;
+ virtual long GetRowBytes (void) = 0;
+ virtual BMDPixelFormat GetPixelFormat (void) = 0;
+ virtual BMDFrameFlags GetFlags (void) = 0;
+ virtual HRESULT GetBytes (/* out */ void **buffer) = 0;
+
+ virtual HRESULT GetTimecode (/* in */ BMDTimecodeFormat format, /* out */ IDeckLinkTimecode **timecode) = 0;
+ virtual HRESULT GetAncillaryData (/* out */ IDeckLinkVideoFrameAncillary **ancillary) = 0;
+
+protected:
+ virtual ~IDeckLinkVideoFrame () {} // call Release method to drop reference count
+};
+
+/* Interface IDeckLinkMutableVideoFrame - Created by IDeckLinkOutput::CreateVideoFrame. */
+
+class IDeckLinkMutableVideoFrame : public IDeckLinkVideoFrame
+{
+public:
+ virtual HRESULT SetFlags (/* in */ BMDFrameFlags newFlags) = 0;
+
+ virtual HRESULT SetTimecode (/* in */ BMDTimecodeFormat format, /* in */ IDeckLinkTimecode *timecode) = 0;
+ virtual HRESULT SetTimecodeFromComponents (/* in */ BMDTimecodeFormat format, /* in */ uint8_t hours, /* in */ uint8_t minutes, /* in */ uint8_t seconds, /* in */ uint8_t frames, /* in */ BMDTimecodeFlags flags) = 0;
+ virtual HRESULT SetAncillaryData (/* in */ IDeckLinkVideoFrameAncillary *ancillary) = 0;
+ virtual HRESULT SetTimecodeUserBits (/* in */ BMDTimecodeFormat format, /* in */ BMDTimecodeUserBits userBits) = 0;
+
+protected:
+ virtual ~IDeckLinkMutableVideoFrame () {} // call Release method to drop reference count
+};
+
+/* Interface IDeckLinkVideoFrame3DExtensions - Optional interface implemented on IDeckLinkVideoFrame to support 3D frames */
+
+class IDeckLinkVideoFrame3DExtensions : public IUnknown
+{
+public:
+ virtual BMDVideo3DPackingFormat Get3DPackingFormat (void) = 0;
+ virtual HRESULT GetFrameForRightEye (/* out */ IDeckLinkVideoFrame* *rightEyeFrame) = 0;
+
+protected:
+ virtual ~IDeckLinkVideoFrame3DExtensions () {} // call Release method to drop reference count
+};
+
+/* Interface IDeckLinkVideoInputFrame - Provided by the IDeckLinkVideoInput frame arrival callback. */
+
+class IDeckLinkVideoInputFrame : public IDeckLinkVideoFrame
+{
+public:
+ virtual HRESULT GetStreamTime (/* out */ BMDTimeValue *frameTime, /* out */ BMDTimeValue *frameDuration, /* in */ BMDTimeScale timeScale) = 0;
+ virtual HRESULT GetHardwareReferenceTimestamp (/* in */ BMDTimeScale timeScale, /* out */ BMDTimeValue *frameTime, /* out */ BMDTimeValue *frameDuration) = 0;
+
+protected:
+ virtual ~IDeckLinkVideoInputFrame () {} // call Release method to drop reference count
+};
+
+/* Interface IDeckLinkVideoFrameAncillary - Obtained through QueryInterface() on an IDeckLinkVideoFrame object. */
+
+class IDeckLinkVideoFrameAncillary : public IUnknown
+{
+public:
+
+ virtual HRESULT GetBufferForVerticalBlankingLine (/* in */ uint32_t lineNumber, /* out */ void **buffer) = 0;
+ virtual BMDPixelFormat GetPixelFormat (void) = 0;
+ virtual BMDDisplayMode GetDisplayMode (void) = 0;
+
+protected:
+ virtual ~IDeckLinkVideoFrameAncillary () {} // call Release method to drop reference count
+};
+
+/* Interface IDeckLinkAudioInputPacket - Provided by the IDeckLinkInput callback. */
+
+class IDeckLinkAudioInputPacket : public IUnknown
+{
+public:
+ virtual long GetSampleFrameCount (void) = 0;
+ virtual HRESULT GetBytes (/* out */ void **buffer) = 0;
+ virtual HRESULT GetPacketTime (/* out */ BMDTimeValue *packetTime, /* in */ BMDTimeScale timeScale) = 0;
+
+protected:
+ virtual ~IDeckLinkAudioInputPacket () {} // call Release method to drop reference count
+};
+
+/* Interface IDeckLinkScreenPreviewCallback - Screen preview callback */
+
+class IDeckLinkScreenPreviewCallback : public IUnknown
+{
+public:
+ virtual HRESULT DrawFrame (/* in */ IDeckLinkVideoFrame *theFrame) = 0;
+
+protected:
+ virtual ~IDeckLinkScreenPreviewCallback () {} // call Release method to drop reference count
+};
+
+/* Interface IDeckLinkGLScreenPreviewHelper - Created with CoCreateInstance(). */
+
+class IDeckLinkGLScreenPreviewHelper : public IUnknown
+{
+public:
+
+ /* Methods must be called with OpenGL context set */
+
+ virtual HRESULT InitializeGL (void) = 0;
+ virtual HRESULT PaintGL (void) = 0;
+ virtual HRESULT SetFrame (/* in */ IDeckLinkVideoFrame *theFrame) = 0;
+ virtual HRESULT Set3DPreviewFormat (/* in */ BMD3DPreviewFormat previewFormat) = 0;
+
+protected:
+ virtual ~IDeckLinkGLScreenPreviewHelper () {} // call Release method to drop reference count
+};
+
+/* Interface IDeckLinkNotificationCallback - DeckLink Notification Callback Interface */
+
+class IDeckLinkNotificationCallback : public IUnknown
+{
+public:
+ virtual HRESULT Notify (/* in */ BMDNotifications topic, /* in */ uint64_t param1, /* in */ uint64_t param2) = 0;
+};
+
+/* Interface IDeckLinkNotification - DeckLink Notification interface */
+
+class IDeckLinkNotification : public IUnknown
+{
+public:
+ virtual HRESULT Subscribe (/* in */ BMDNotifications topic, /* in */ IDeckLinkNotificationCallback *theCallback) = 0;
+ virtual HRESULT Unsubscribe (/* in */ BMDNotifications topic, /* in */ IDeckLinkNotificationCallback *theCallback) = 0;
+};
+
+/* Interface IDeckLinkAttributes - DeckLink Attribute interface */
+
+class IDeckLinkAttributes : public IUnknown
+{
+public:
+ virtual HRESULT GetFlag (/* in */ BMDDeckLinkAttributeID cfgID, /* out */ bool *value) = 0;
+ virtual HRESULT GetInt (/* in */ BMDDeckLinkAttributeID cfgID, /* out */ int64_t *value) = 0;
+ virtual HRESULT GetFloat (/* in */ BMDDeckLinkAttributeID cfgID, /* out */ double *value) = 0;
+ virtual HRESULT GetString (/* in */ BMDDeckLinkAttributeID cfgID, /* out */ const char **value) = 0;
+
+protected:
+ virtual ~IDeckLinkAttributes () {} // call Release method to drop reference count
+};
+
+/* Interface IDeckLinkKeyer - DeckLink Keyer interface */
+
+class IDeckLinkKeyer : public IUnknown
+{
+public:
+ virtual HRESULT Enable (/* in */ bool isExternal) = 0;
+ virtual HRESULT SetLevel (/* in */ uint8_t level) = 0;
+ virtual HRESULT RampUp (/* in */ uint32_t numberOfFrames) = 0;
+ virtual HRESULT RampDown (/* in */ uint32_t numberOfFrames) = 0;
+ virtual HRESULT Disable (void) = 0;
+
+protected:
+ virtual ~IDeckLinkKeyer () {} // call Release method to drop reference count
+};
+
+/* Interface IDeckLinkVideoConversion - Created with CoCreateInstance(). */
+
+class IDeckLinkVideoConversion : public IUnknown
+{
+public:
+ virtual HRESULT ConvertFrame (/* in */ IDeckLinkVideoFrame* srcFrame, /* in */ IDeckLinkVideoFrame* dstFrame) = 0;
+
+protected:
+ virtual ~IDeckLinkVideoConversion () {} // call Release method to drop reference count
+};
+
+/* Interface IDeckLinkDeviceNotificationCallback - DeckLink device arrival/removal notification callbacks */
+
+class IDeckLinkDeviceNotificationCallback : public IUnknown
+{
+public:
+ virtual HRESULT DeckLinkDeviceArrived (/* in */ IDeckLink* deckLinkDevice) = 0;
+ virtual HRESULT DeckLinkDeviceRemoved (/* in */ IDeckLink* deckLinkDevice) = 0;
+
+protected:
+ virtual ~IDeckLinkDeviceNotificationCallback () {} // call Release method to drop reference count
+};
+
+/* Interface IDeckLinkDiscovery - DeckLink device discovery */
+
+class IDeckLinkDiscovery : public IUnknown
+{
+public:
+ virtual HRESULT InstallDeviceNotifications (/* in */ IDeckLinkDeviceNotificationCallback* deviceNotificationCallback) = 0;
+ virtual HRESULT UninstallDeviceNotifications (void) = 0;
+
+protected:
+ virtual ~IDeckLinkDiscovery () {} // call Release method to drop reference count
+};
+
+/* Functions */
+
+extern "C" {
+
+ IDeckLinkIterator* CreateDeckLinkIteratorInstance (void);
+ IDeckLinkDiscovery* CreateDeckLinkDiscoveryInstance (void);
+ IDeckLinkAPIInformation* CreateDeckLinkAPIInformationInstance (void);
+ IDeckLinkGLScreenPreviewHelper* CreateOpenGLScreenPreviewHelper (void);
+ IDeckLinkVideoConversion* CreateVideoConversionInstance (void);
+ bool IsDeckLinkAPIPresent (void);
+}
+
+
+#endif // defined(__cplusplus)
+#endif /* defined(BMD_DECKLINKAPI_H) */
diff --git a/intern/decklink/linux/DeckLinkAPIConfiguration.h b/intern/decklink/linux/DeckLinkAPIConfiguration.h
new file mode 100644
index 00000000000..9d5bc9a9e1b
--- /dev/null
+++ b/intern/decklink/linux/DeckLinkAPIConfiguration.h
@@ -0,0 +1,192 @@
+/* -LICENSE-START-
+** Copyright (c) 2014 Blackmagic Design
+**
+** Permission is hereby granted, free of charge, to any person or organization
+** obtaining a copy of the software and accompanying documentation covered by
+** this license (the "Software") to use, reproduce, display, distribute,
+** execute, and transmit the Software, and to prepare derivative works of the
+** Software, and to permit third-parties to whom the Software is furnished to
+** do so, all subject to the following:
+**
+** The copyright notices in the Software and this entire statement, including
+** the above license grant, this restriction and the following disclaimer,
+** must be included in all copies of the Software, in whole or in part, and
+** all derivative works of the Software, unless such copies or derivative
+** works are solely in the form of machine-executable object code generated by
+** a source language processor.
+**
+** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+** DEALINGS IN THE SOFTWARE.
+** -LICENSE-END-
+*/
+
+#ifndef BMD_DECKLINKAPICONFIGURATION_H
+#define BMD_DECKLINKAPICONFIGURATION_H
+
+
+#ifndef BMD_CONST
+ #if defined(_MSC_VER)
+ #define BMD_CONST __declspec(selectany) static const
+ #else
+ #define BMD_CONST static const
+ #endif
+#endif
+
+// Type Declarations
+
+
+// Interface ID Declarations
+
+BMD_CONST REFIID IID_IDeckLinkConfiguration = /* 1E69FCF6-4203-4936-8076-2A9F4CFD50CB */ {0x1E,0x69,0xFC,0xF6,0x42,0x03,0x49,0x36,0x80,0x76,0x2A,0x9F,0x4C,0xFD,0x50,0xCB};
+
+/* Enum BMDDeckLinkConfigurationID - DeckLink Configuration ID */
+
+typedef uint32_t BMDDeckLinkConfigurationID;
+enum _BMDDeckLinkConfigurationID {
+
+ /* Serial port Flags */
+
+ bmdDeckLinkConfigSwapSerialRxTx = /* 'ssrt' */ 0x73737274,
+
+ /* Video Input/Output Flags */
+
+ bmdDeckLinkConfigUse1080pNotPsF = /* 'fpro' */ 0x6670726F,
+
+ /* Video Input/Output Integers */
+
+ bmdDeckLinkConfigHDMI3DPackingFormat = /* '3dpf' */ 0x33647066,
+ bmdDeckLinkConfigBypass = /* 'byps' */ 0x62797073,
+ bmdDeckLinkConfigClockTimingAdjustment = /* 'ctad' */ 0x63746164,
+
+ /* Audio Input/Output Flags */
+
+ bmdDeckLinkConfigAnalogAudioConsumerLevels = /* 'aacl' */ 0x6161636C,
+
+ /* Video output flags */
+
+ bmdDeckLinkConfigFieldFlickerRemoval = /* 'fdfr' */ 0x66646672,
+ bmdDeckLinkConfigHD1080p24ToHD1080i5994Conversion = /* 'to59' */ 0x746F3539,
+ bmdDeckLinkConfig444SDIVideoOutput = /* '444o' */ 0x3434346F,
+ bmdDeckLinkConfigSingleLinkVideoOutput = /* 'sglo' */ 0x73676C6F,
+ bmdDeckLinkConfigBlackVideoOutputDuringCapture = /* 'bvoc' */ 0x62766F63,
+ bmdDeckLinkConfigLowLatencyVideoOutput = /* 'llvo' */ 0x6C6C766F,
+ bmdDeckLinkConfigDownConversionOnAllAnalogOutput = /* 'caao' */ 0x6361616F,
+ bmdDeckLinkConfigSMPTELevelAOutput = /* 'smta' */ 0x736D7461,
+
+ /* Video Output Integers */
+
+ bmdDeckLinkConfigVideoOutputConnection = /* 'vocn' */ 0x766F636E,
+ bmdDeckLinkConfigVideoOutputConversionMode = /* 'vocm' */ 0x766F636D,
+ bmdDeckLinkConfigAnalogVideoOutputFlags = /* 'avof' */ 0x61766F66,
+ bmdDeckLinkConfigReferenceInputTimingOffset = /* 'glot' */ 0x676C6F74,
+ bmdDeckLinkConfigVideoOutputIdleOperation = /* 'voio' */ 0x766F696F,
+ bmdDeckLinkConfigDefaultVideoOutputMode = /* 'dvom' */ 0x64766F6D,
+ bmdDeckLinkConfigDefaultVideoOutputModeFlags = /* 'dvof' */ 0x64766F66,
+
+ /* Video Output Floats */
+
+ bmdDeckLinkConfigVideoOutputComponentLumaGain = /* 'oclg' */ 0x6F636C67,
+ bmdDeckLinkConfigVideoOutputComponentChromaBlueGain = /* 'occb' */ 0x6F636362,
+ bmdDeckLinkConfigVideoOutputComponentChromaRedGain = /* 'occr' */ 0x6F636372,
+ bmdDeckLinkConfigVideoOutputCompositeLumaGain = /* 'oilg' */ 0x6F696C67,
+ bmdDeckLinkConfigVideoOutputCompositeChromaGain = /* 'oicg' */ 0x6F696367,
+ bmdDeckLinkConfigVideoOutputSVideoLumaGain = /* 'oslg' */ 0x6F736C67,
+ bmdDeckLinkConfigVideoOutputSVideoChromaGain = /* 'oscg' */ 0x6F736367,
+
+ /* Video Input Flags */
+
+ bmdDeckLinkConfigVideoInputScanning = /* 'visc' */ 0x76697363, // Applicable to H264 Pro Recorder only
+ bmdDeckLinkConfigUseDedicatedLTCInput = /* 'dltc' */ 0x646C7463, // Use timecode from LTC input instead of SDI stream
+
+ /* Video Input Integers */
+
+ bmdDeckLinkConfigVideoInputConnection = /* 'vicn' */ 0x7669636E,
+ bmdDeckLinkConfigAnalogVideoInputFlags = /* 'avif' */ 0x61766966,
+ bmdDeckLinkConfigVideoInputConversionMode = /* 'vicm' */ 0x7669636D,
+ bmdDeckLinkConfig32PulldownSequenceInitialTimecodeFrame = /* 'pdif' */ 0x70646966,
+ bmdDeckLinkConfigVANCSourceLine1Mapping = /* 'vsl1' */ 0x76736C31,
+ bmdDeckLinkConfigVANCSourceLine2Mapping = /* 'vsl2' */ 0x76736C32,
+ bmdDeckLinkConfigVANCSourceLine3Mapping = /* 'vsl3' */ 0x76736C33,
+ bmdDeckLinkConfigCapturePassThroughMode = /* 'cptm' */ 0x6370746D,
+
+ /* Video Input Floats */
+
+ bmdDeckLinkConfigVideoInputComponentLumaGain = /* 'iclg' */ 0x69636C67,
+ bmdDeckLinkConfigVideoInputComponentChromaBlueGain = /* 'iccb' */ 0x69636362,
+ bmdDeckLinkConfigVideoInputComponentChromaRedGain = /* 'iccr' */ 0x69636372,
+ bmdDeckLinkConfigVideoInputCompositeLumaGain = /* 'iilg' */ 0x69696C67,
+ bmdDeckLinkConfigVideoInputCompositeChromaGain = /* 'iicg' */ 0x69696367,
+ bmdDeckLinkConfigVideoInputSVideoLumaGain = /* 'islg' */ 0x69736C67,
+ bmdDeckLinkConfigVideoInputSVideoChromaGain = /* 'iscg' */ 0x69736367,
+
+ /* Audio Input Integers */
+
+ bmdDeckLinkConfigAudioInputConnection = /* 'aicn' */ 0x6169636E,
+
+ /* Audio Input Floats */
+
+ bmdDeckLinkConfigAnalogAudioInputScaleChannel1 = /* 'ais1' */ 0x61697331,
+ bmdDeckLinkConfigAnalogAudioInputScaleChannel2 = /* 'ais2' */ 0x61697332,
+ bmdDeckLinkConfigAnalogAudioInputScaleChannel3 = /* 'ais3' */ 0x61697333,
+ bmdDeckLinkConfigAnalogAudioInputScaleChannel4 = /* 'ais4' */ 0x61697334,
+ bmdDeckLinkConfigDigitalAudioInputScale = /* 'dais' */ 0x64616973,
+
+ /* Audio Output Integers */
+
+ bmdDeckLinkConfigAudioOutputAESAnalogSwitch = /* 'aoaa' */ 0x616F6161,
+
+ /* Audio Output Floats */
+
+ bmdDeckLinkConfigAnalogAudioOutputScaleChannel1 = /* 'aos1' */ 0x616F7331,
+ bmdDeckLinkConfigAnalogAudioOutputScaleChannel2 = /* 'aos2' */ 0x616F7332,
+ bmdDeckLinkConfigAnalogAudioOutputScaleChannel3 = /* 'aos3' */ 0x616F7333,
+ bmdDeckLinkConfigAnalogAudioOutputScaleChannel4 = /* 'aos4' */ 0x616F7334,
+ bmdDeckLinkConfigDigitalAudioOutputScale = /* 'daos' */ 0x64616F73,
+
+ /* Device Information Strings */
+
+ bmdDeckLinkConfigDeviceInformationLabel = /* 'dila' */ 0x64696C61,
+ bmdDeckLinkConfigDeviceInformationSerialNumber = /* 'disn' */ 0x6469736E,
+ bmdDeckLinkConfigDeviceInformationCompany = /* 'dico' */ 0x6469636F,
+ bmdDeckLinkConfigDeviceInformationPhone = /* 'diph' */ 0x64697068,
+ bmdDeckLinkConfigDeviceInformationEmail = /* 'diem' */ 0x6469656D,
+ bmdDeckLinkConfigDeviceInformationDate = /* 'dida' */ 0x64696461
+};
+
+// Forward Declarations
+
+class IDeckLinkConfiguration;
+
+/* Interface IDeckLinkConfiguration - DeckLink Configuration interface */
+
+class IDeckLinkConfiguration : public IUnknown
+{
+public:
+ virtual HRESULT SetFlag (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ bool value) = 0;
+ virtual HRESULT GetFlag (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ bool *value) = 0;
+ virtual HRESULT SetInt (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ int64_t value) = 0;
+ virtual HRESULT GetInt (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ int64_t *value) = 0;
+ virtual HRESULT SetFloat (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ double value) = 0;
+ virtual HRESULT GetFloat (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ double *value) = 0;
+ virtual HRESULT SetString (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ const char *value) = 0;
+ virtual HRESULT GetString (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ const char **value) = 0;
+ virtual HRESULT WriteConfigurationToPreferences (void) = 0;
+
+protected:
+ virtual ~IDeckLinkConfiguration () {} // call Release method to drop reference count
+};
+
+/* Functions */
+
+extern "C" {
+
+
+}
+
+
+#endif /* defined(BMD_DECKLINKAPICONFIGURATION_H) */
diff --git a/intern/decklink/linux/DeckLinkAPIDeckControl.h b/intern/decklink/linux/DeckLinkAPIDeckControl.h
new file mode 100644
index 00000000000..b83d013129e
--- /dev/null
+++ b/intern/decklink/linux/DeckLinkAPIDeckControl.h
@@ -0,0 +1,215 @@
+/* -LICENSE-START-
+** Copyright (c) 2014 Blackmagic Design
+**
+** Permission is hereby granted, free of charge, to any person or organization
+** obtaining a copy of the software and accompanying documentation covered by
+** this license (the "Software") to use, reproduce, display, distribute,
+** execute, and transmit the Software, and to prepare derivative works of the
+** Software, and to permit third-parties to whom the Software is furnished to
+** do so, all subject to the following:
+**
+** The copyright notices in the Software and this entire statement, including
+** the above license grant, this restriction and the following disclaimer,
+** must be included in all copies of the Software, in whole or in part, and
+** all derivative works of the Software, unless such copies or derivative
+** works are solely in the form of machine-executable object code generated by
+** a source language processor.
+**
+** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+** DEALINGS IN THE SOFTWARE.
+** -LICENSE-END-
+*/
+
+#ifndef BMD_DECKLINKAPIDECKCONTROL_H
+#define BMD_DECKLINKAPIDECKCONTROL_H
+
+
+#ifndef BMD_CONST
+ #if defined(_MSC_VER)
+ #define BMD_CONST __declspec(selectany) static const
+ #else
+ #define BMD_CONST static const
+ #endif
+#endif
+
+// Type Declarations
+
+
+// Interface ID Declarations
+
+BMD_CONST REFIID IID_IDeckLinkDeckControlStatusCallback = /* 53436FFB-B434-4906-BADC-AE3060FFE8EF */ {0x53,0x43,0x6F,0xFB,0xB4,0x34,0x49,0x06,0xBA,0xDC,0xAE,0x30,0x60,0xFF,0xE8,0xEF};
+BMD_CONST REFIID IID_IDeckLinkDeckControl = /* 8E1C3ACE-19C7-4E00-8B92-D80431D958BE */ {0x8E,0x1C,0x3A,0xCE,0x19,0xC7,0x4E,0x00,0x8B,0x92,0xD8,0x04,0x31,0xD9,0x58,0xBE};
+
+/* Enum BMDDeckControlMode - DeckControl mode */
+
+typedef uint32_t BMDDeckControlMode;
+enum _BMDDeckControlMode {
+ bmdDeckControlNotOpened = /* 'ntop' */ 0x6E746F70,
+ bmdDeckControlVTRControlMode = /* 'vtrc' */ 0x76747263,
+ bmdDeckControlExportMode = /* 'expm' */ 0x6578706D,
+ bmdDeckControlCaptureMode = /* 'capm' */ 0x6361706D
+};
+
+/* Enum BMDDeckControlEvent - DeckControl event */
+
+typedef uint32_t BMDDeckControlEvent;
+enum _BMDDeckControlEvent {
+ bmdDeckControlAbortedEvent = /* 'abte' */ 0x61627465, // This event is triggered when a capture or edit-to-tape operation is aborted.
+
+ /* Export-To-Tape events */
+
+ bmdDeckControlPrepareForExportEvent = /* 'pfee' */ 0x70666565, // This event is triggered a few frames before reaching the in-point. IDeckLinkInput::StartScheduledPlayback() should be called at this point.
+ bmdDeckControlExportCompleteEvent = /* 'exce' */ 0x65786365, // This event is triggered a few frames after reaching the out-point. At this point, it is safe to stop playback.
+
+ /* Capture events */
+
+ bmdDeckControlPrepareForCaptureEvent = /* 'pfce' */ 0x70666365, // This event is triggered a few frames before reaching the in-point. The serial timecode attached to IDeckLinkVideoInputFrames is now valid.
+ bmdDeckControlCaptureCompleteEvent = /* 'ccev' */ 0x63636576 // This event is triggered a few frames after reaching the out-point.
+};
+
+/* Enum BMDDeckControlVTRControlState - VTR Control state */
+
+typedef uint32_t BMDDeckControlVTRControlState;
+enum _BMDDeckControlVTRControlState {
+ bmdDeckControlNotInVTRControlMode = /* 'nvcm' */ 0x6E76636D,
+ bmdDeckControlVTRControlPlaying = /* 'vtrp' */ 0x76747270,
+ bmdDeckControlVTRControlRecording = /* 'vtrr' */ 0x76747272,
+ bmdDeckControlVTRControlStill = /* 'vtra' */ 0x76747261,
+ bmdDeckControlVTRControlShuttleForward = /* 'vtsf' */ 0x76747366,
+ bmdDeckControlVTRControlShuttleReverse = /* 'vtsr' */ 0x76747372,
+ bmdDeckControlVTRControlJogForward = /* 'vtjf' */ 0x76746A66,
+ bmdDeckControlVTRControlJogReverse = /* 'vtjr' */ 0x76746A72,
+ bmdDeckControlVTRControlStopped = /* 'vtro' */ 0x7674726F
+};
+
+/* Enum BMDDeckControlStatusFlags - Deck Control status flags */
+
+typedef uint32_t BMDDeckControlStatusFlags;
+enum _BMDDeckControlStatusFlags {
+ bmdDeckControlStatusDeckConnected = 1 << 0,
+ bmdDeckControlStatusRemoteMode = 1 << 1,
+ bmdDeckControlStatusRecordInhibited = 1 << 2,
+ bmdDeckControlStatusCassetteOut = 1 << 3
+};
+
+/* Enum BMDDeckControlExportModeOpsFlags - Export mode flags */
+
+typedef uint32_t BMDDeckControlExportModeOpsFlags;
+enum _BMDDeckControlExportModeOpsFlags {
+ bmdDeckControlExportModeInsertVideo = 1 << 0,
+ bmdDeckControlExportModeInsertAudio1 = 1 << 1,
+ bmdDeckControlExportModeInsertAudio2 = 1 << 2,
+ bmdDeckControlExportModeInsertAudio3 = 1 << 3,
+ bmdDeckControlExportModeInsertAudio4 = 1 << 4,
+ bmdDeckControlExportModeInsertAudio5 = 1 << 5,
+ bmdDeckControlExportModeInsertAudio6 = 1 << 6,
+ bmdDeckControlExportModeInsertAudio7 = 1 << 7,
+ bmdDeckControlExportModeInsertAudio8 = 1 << 8,
+ bmdDeckControlExportModeInsertAudio9 = 1 << 9,
+ bmdDeckControlExportModeInsertAudio10 = 1 << 10,
+ bmdDeckControlExportModeInsertAudio11 = 1 << 11,
+ bmdDeckControlExportModeInsertAudio12 = 1 << 12,
+ bmdDeckControlExportModeInsertTimeCode = 1 << 13,
+ bmdDeckControlExportModeInsertAssemble = 1 << 14,
+ bmdDeckControlExportModeInsertPreview = 1 << 15,
+ bmdDeckControlUseManualExport = 1 << 16
+};
+
+/* Enum BMDDeckControlError - Deck Control error */
+
+typedef uint32_t BMDDeckControlError;
+enum _BMDDeckControlError {
+ bmdDeckControlNoError = /* 'noer' */ 0x6E6F6572,
+ bmdDeckControlModeError = /* 'moer' */ 0x6D6F6572,
+ bmdDeckControlMissedInPointError = /* 'mier' */ 0x6D696572,
+ bmdDeckControlDeckTimeoutError = /* 'dter' */ 0x64746572,
+ bmdDeckControlCommandFailedError = /* 'cfer' */ 0x63666572,
+ bmdDeckControlDeviceAlreadyOpenedError = /* 'dalo' */ 0x64616C6F,
+ bmdDeckControlFailedToOpenDeviceError = /* 'fder' */ 0x66646572,
+ bmdDeckControlInLocalModeError = /* 'lmer' */ 0x6C6D6572,
+ bmdDeckControlEndOfTapeError = /* 'eter' */ 0x65746572,
+ bmdDeckControlUserAbortError = /* 'uaer' */ 0x75616572,
+ bmdDeckControlNoTapeInDeckError = /* 'nter' */ 0x6E746572,
+ bmdDeckControlNoVideoFromCardError = /* 'nvfc' */ 0x6E766663,
+ bmdDeckControlNoCommunicationError = /* 'ncom' */ 0x6E636F6D,
+ bmdDeckControlBufferTooSmallError = /* 'btsm' */ 0x6274736D,
+ bmdDeckControlBadChecksumError = /* 'chks' */ 0x63686B73,
+ bmdDeckControlUnknownError = /* 'uner' */ 0x756E6572
+};
+
+// Forward Declarations
+
+class IDeckLinkDeckControlStatusCallback;
+class IDeckLinkDeckControl;
+
+/* Interface IDeckLinkDeckControlStatusCallback - Deck control state change callback. */
+
+class IDeckLinkDeckControlStatusCallback : public IUnknown
+{
+public:
+ virtual HRESULT TimecodeUpdate (/* in */ BMDTimecodeBCD currentTimecode) = 0;
+ virtual HRESULT VTRControlStateChanged (/* in */ BMDDeckControlVTRControlState newState, /* in */ BMDDeckControlError error) = 0;
+ virtual HRESULT DeckControlEventReceived (/* in */ BMDDeckControlEvent event, /* in */ BMDDeckControlError error) = 0;
+ virtual HRESULT DeckControlStatusChanged (/* in */ BMDDeckControlStatusFlags flags, /* in */ uint32_t mask) = 0;
+
+protected:
+ virtual ~IDeckLinkDeckControlStatusCallback () {} // call Release method to drop reference count
+};
+
+/* Interface IDeckLinkDeckControl - Deck Control main interface */
+
+class IDeckLinkDeckControl : public IUnknown
+{
+public:
+ virtual HRESULT Open (/* in */ BMDTimeScale timeScale, /* in */ BMDTimeValue timeValue, /* in */ bool timecodeIsDropFrame, /* out */ BMDDeckControlError *error) = 0;
+ virtual HRESULT Close (/* in */ bool standbyOn) = 0;
+ virtual HRESULT GetCurrentState (/* out */ BMDDeckControlMode *mode, /* out */ BMDDeckControlVTRControlState *vtrControlState, /* out */ BMDDeckControlStatusFlags *flags) = 0;
+ virtual HRESULT SetStandby (/* in */ bool standbyOn) = 0;
+ virtual HRESULT SendCommand (/* in */ uint8_t *inBuffer, /* in */ uint32_t inBufferSize, /* out */ uint8_t *outBuffer, /* out */ uint32_t *outDataSize, /* in */ uint32_t outBufferSize, /* out */ BMDDeckControlError *error) = 0;
+ virtual HRESULT Play (/* out */ BMDDeckControlError *error) = 0;
+ virtual HRESULT Stop (/* out */ BMDDeckControlError *error) = 0;
+ virtual HRESULT TogglePlayStop (/* out */ BMDDeckControlError *error) = 0;
+ virtual HRESULT Eject (/* out */ BMDDeckControlError *error) = 0;
+ virtual HRESULT GoToTimecode (/* in */ BMDTimecodeBCD timecode, /* out */ BMDDeckControlError *error) = 0;
+ virtual HRESULT FastForward (/* in */ bool viewTape, /* out */ BMDDeckControlError *error) = 0;
+ virtual HRESULT Rewind (/* in */ bool viewTape, /* out */ BMDDeckControlError *error) = 0;
+ virtual HRESULT StepForward (/* out */ BMDDeckControlError *error) = 0;
+ virtual HRESULT StepBack (/* out */ BMDDeckControlError *error) = 0;
+ virtual HRESULT Jog (/* in */ double rate, /* out */ BMDDeckControlError *error) = 0;
+ virtual HRESULT Shuttle (/* in */ double rate, /* out */ BMDDeckControlError *error) = 0;
+ virtual HRESULT GetTimecodeString (/* out */ const char **currentTimeCode, /* out */ BMDDeckControlError *error) = 0;
+ virtual HRESULT GetTimecode (/* out */ IDeckLinkTimecode **currentTimecode, /* out */ BMDDeckControlError *error) = 0;
+ virtual HRESULT GetTimecodeBCD (/* out */ BMDTimecodeBCD *currentTimecode, /* out */ BMDDeckControlError *error) = 0;
+ virtual HRESULT SetPreroll (/* in */ uint32_t prerollSeconds) = 0;
+ virtual HRESULT GetPreroll (/* out */ uint32_t *prerollSeconds) = 0;
+ virtual HRESULT SetExportOffset (/* in */ int32_t exportOffsetFields) = 0;
+ virtual HRESULT GetExportOffset (/* out */ int32_t *exportOffsetFields) = 0;
+ virtual HRESULT GetManualExportOffset (/* out */ int32_t *deckManualExportOffsetFields) = 0;
+ virtual HRESULT SetCaptureOffset (/* in */ int32_t captureOffsetFields) = 0;
+ virtual HRESULT GetCaptureOffset (/* out */ int32_t *captureOffsetFields) = 0;
+ virtual HRESULT StartExport (/* in */ BMDTimecodeBCD inTimecode, /* in */ BMDTimecodeBCD outTimecode, /* in */ BMDDeckControlExportModeOpsFlags exportModeOps, /* out */ BMDDeckControlError *error) = 0;
+ virtual HRESULT StartCapture (/* in */ bool useVITC, /* in */ BMDTimecodeBCD inTimecode, /* in */ BMDTimecodeBCD outTimecode, /* out */ BMDDeckControlError *error) = 0;
+ virtual HRESULT GetDeviceID (/* out */ uint16_t *deviceId, /* out */ BMDDeckControlError *error) = 0;
+ virtual HRESULT Abort (void) = 0;
+ virtual HRESULT CrashRecordStart (/* out */ BMDDeckControlError *error) = 0;
+ virtual HRESULT CrashRecordStop (/* out */ BMDDeckControlError *error) = 0;
+ virtual HRESULT SetCallback (/* in */ IDeckLinkDeckControlStatusCallback *callback) = 0;
+
+protected:
+ virtual ~IDeckLinkDeckControl () {} // call Release method to drop reference count
+};
+
+/* Functions */
+
+extern "C" {
+
+
+}
+
+
+#endif /* defined(BMD_DECKLINKAPIDECKCONTROL_H) */
diff --git a/intern/decklink/linux/DeckLinkAPIDiscovery.h b/intern/decklink/linux/DeckLinkAPIDiscovery.h
new file mode 100644
index 00000000000..424d9d54b39
--- /dev/null
+++ b/intern/decklink/linux/DeckLinkAPIDiscovery.h
@@ -0,0 +1,71 @@
+/* -LICENSE-START-
+** Copyright (c) 2014 Blackmagic Design
+**
+** Permission is hereby granted, free of charge, to any person or organization
+** obtaining a copy of the software and accompanying documentation covered by
+** this license (the "Software") to use, reproduce, display, distribute,
+** execute, and transmit the Software, and to prepare derivative works of the
+** Software, and to permit third-parties to whom the Software is furnished to
+** do so, all subject to the following:
+**
+** The copyright notices in the Software and this entire statement, including
+** the above license grant, this restriction and the following disclaimer,
+** must be included in all copies of the Software, in whole or in part, and
+** all derivative works of the Software, unless such copies or derivative
+** works are solely in the form of machine-executable object code generated by
+** a source language processor.
+**
+** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+** DEALINGS IN THE SOFTWARE.
+** -LICENSE-END-
+*/
+
+#ifndef BMD_DECKLINKAPIDISCOVERY_H
+#define BMD_DECKLINKAPIDISCOVERY_H
+
+
+#ifndef BMD_CONST
+ #if defined(_MSC_VER)
+ #define BMD_CONST __declspec(selectany) static const
+ #else
+ #define BMD_CONST static const
+ #endif
+#endif
+
+// Type Declarations
+
+
+// Interface ID Declarations
+
+BMD_CONST REFIID IID_IDeckLink = /* C418FBDD-0587-48ED-8FE5-640F0A14AF91 */ {0xC4,0x18,0xFB,0xDD,0x05,0x87,0x48,0xED,0x8F,0xE5,0x64,0x0F,0x0A,0x14,0xAF,0x91};
+
+// Forward Declarations
+
+class IDeckLink;
+
+/* Interface IDeckLink - represents a DeckLink device */
+
+class IDeckLink : public IUnknown
+{
+public:
+ virtual HRESULT GetModelName (/* out */ const char **modelName) = 0;
+ virtual HRESULT GetDisplayName (/* out */ const char **displayName) = 0;
+
+protected:
+ virtual ~IDeckLink () {} // call Release method to drop reference count
+};
+
+/* Functions */
+
+extern "C" {
+
+
+}
+
+
+#endif /* defined(BMD_DECKLINKAPIDISCOVERY_H) */
diff --git a/intern/decklink/linux/DeckLinkAPIDispatch.cpp b/intern/decklink/linux/DeckLinkAPIDispatch.cpp
new file mode 100644
index 00000000000..3cf53f109ac
--- /dev/null
+++ b/intern/decklink/linux/DeckLinkAPIDispatch.cpp
@@ -0,0 +1,148 @@
+/* -LICENSE-START-
+** Copyright (c) 2009 Blackmagic Design
+**
+** Permission is hereby granted, free of charge, to any person or organization
+** obtaining a copy of the software and accompanying documentation covered by
+** this license (the "Software") to use, reproduce, display, distribute,
+** execute, and transmit the Software, and to prepare derivative works of the
+** Software, and to permit third-parties to whom the Software is furnished to
+** do so, all subject to the following:
+**
+** The copyright notices in the Software and this entire statement, including
+** the above license grant, this restriction and the following disclaimer,
+** must be included in all copies of the Software, in whole or in part, and
+** all derivative works of the Software, unless such copies or derivative
+** works are solely in the form of machine-executable object code generated by
+** a source language processor.
+**
+** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+** DEALINGS IN THE SOFTWARE.
+** -LICENSE-END-
+**/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <pthread.h>
+#include <dlfcn.h>
+#include <ctype.h>
+
+#include "DeckLinkAPI.h"
+
+#define kDeckLinkAPI_Name "libDeckLinkAPI.so"
+#define KDeckLinkPreviewAPI_Name "libDeckLinkPreviewAPI.so"
+
+typedef IDeckLinkIterator* (*CreateIteratorFunc)(void);
+typedef IDeckLinkAPIInformation* (*CreateAPIInformationFunc)(void);
+typedef IDeckLinkGLScreenPreviewHelper* (*CreateOpenGLScreenPreviewHelperFunc)(void);
+typedef IDeckLinkVideoConversion* (*CreateVideoConversionInstanceFunc)(void);
+typedef IDeckLinkDiscovery* (*CreateDeckLinkDiscoveryInstanceFunc)(void);
+
+static pthread_once_t gDeckLinkOnceControl = PTHREAD_ONCE_INIT;
+static pthread_once_t gPreviewOnceControl = PTHREAD_ONCE_INIT;
+
+static bool gLoadedDeckLinkAPI = false;
+
+static CreateIteratorFunc gCreateIteratorFunc = NULL;
+static CreateAPIInformationFunc gCreateAPIInformationFunc = NULL;
+static CreateOpenGLScreenPreviewHelperFunc gCreateOpenGLPreviewFunc = NULL;
+static CreateVideoConversionInstanceFunc gCreateVideoConversionFunc = NULL;
+static CreateDeckLinkDiscoveryInstanceFunc gCreateDeckLinkDiscoveryFunc = NULL;
+
+static void InitDeckLinkAPI (void)
+{
+ void *libraryHandle;
+
+ libraryHandle = dlopen(kDeckLinkAPI_Name, RTLD_NOW|RTLD_GLOBAL);
+ if (!libraryHandle)
+ {
+ fprintf(stderr, "%s\n", dlerror());
+ return;
+ }
+
+ gLoadedDeckLinkAPI = true;
+
+ gCreateIteratorFunc = (CreateIteratorFunc)dlsym(libraryHandle, "CreateDeckLinkIteratorInstance_0002");
+ if (!gCreateIteratorFunc)
+ fprintf(stderr, "%s\n", dlerror());
+ gCreateAPIInformationFunc = (CreateAPIInformationFunc)dlsym(libraryHandle, "CreateDeckLinkAPIInformationInstance_0001");
+ if (!gCreateAPIInformationFunc)
+ fprintf(stderr, "%s\n", dlerror());
+ gCreateVideoConversionFunc = (CreateVideoConversionInstanceFunc)dlsym(libraryHandle, "CreateVideoConversionInstance_0001");
+ if (!gCreateVideoConversionFunc)
+ fprintf(stderr, "%s\n", dlerror());
+ gCreateDeckLinkDiscoveryFunc = (CreateDeckLinkDiscoveryInstanceFunc)dlsym(libraryHandle, "CreateDeckLinkDiscoveryInstance_0001");
+ if (!gCreateDeckLinkDiscoveryFunc)
+ fprintf(stderr, "%s\n", dlerror());
+}
+
+static void InitDeckLinkPreviewAPI (void)
+{
+ void *libraryHandle;
+
+ libraryHandle = dlopen(KDeckLinkPreviewAPI_Name, RTLD_NOW|RTLD_GLOBAL);
+ if (!libraryHandle)
+ {
+ fprintf(stderr, "%s\n", dlerror());
+ return;
+ }
+ gCreateOpenGLPreviewFunc = (CreateOpenGLScreenPreviewHelperFunc)dlsym(libraryHandle, "CreateOpenGLScreenPreviewHelper_0001");
+ if (!gCreateOpenGLPreviewFunc)
+ fprintf(stderr, "%s\n", dlerror());
+}
+
+bool IsDeckLinkAPIPresent (void)
+{
+ // If the DeckLink API dynamic library was successfully loaded, return this knowledge to the caller
+ return gLoadedDeckLinkAPI;
+}
+
+IDeckLinkIterator* CreateDeckLinkIteratorInstance (void)
+{
+ pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI);
+
+ if (gCreateIteratorFunc == NULL)
+ return NULL;
+ return gCreateIteratorFunc();
+}
+
+IDeckLinkAPIInformation* CreateDeckLinkAPIInformationInstance (void)
+{
+ pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI);
+
+ if (gCreateAPIInformationFunc == NULL)
+ return NULL;
+ return gCreateAPIInformationFunc();
+}
+
+IDeckLinkGLScreenPreviewHelper* CreateOpenGLScreenPreviewHelper (void)
+{
+ pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI);
+ pthread_once(&gPreviewOnceControl, InitDeckLinkPreviewAPI);
+
+ if (gCreateOpenGLPreviewFunc == NULL)
+ return NULL;
+ return gCreateOpenGLPreviewFunc();
+}
+
+IDeckLinkVideoConversion* CreateVideoConversionInstance (void)
+{
+ pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI);
+
+ if (gCreateVideoConversionFunc == NULL)
+ return NULL;
+ return gCreateVideoConversionFunc();
+}
+
+IDeckLinkDiscovery* CreateDeckLinkDiscoveryInstance (void)
+{
+ pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI);
+
+ if (gCreateDeckLinkDiscoveryFunc == NULL)
+ return NULL;
+ return gCreateDeckLinkDiscoveryFunc();
+}
diff --git a/intern/decklink/linux/DeckLinkAPIModes.h b/intern/decklink/linux/DeckLinkAPIModes.h
new file mode 100644
index 00000000000..394d68c3078
--- /dev/null
+++ b/intern/decklink/linux/DeckLinkAPIModes.h
@@ -0,0 +1,191 @@
+/* -LICENSE-START-
+** Copyright (c) 2014 Blackmagic Design
+**
+** Permission is hereby granted, free of charge, to any person or organization
+** obtaining a copy of the software and accompanying documentation covered by
+** this license (the "Software") to use, reproduce, display, distribute,
+** execute, and transmit the Software, and to prepare derivative works of the
+** Software, and to permit third-parties to whom the Software is furnished to
+** do so, all subject to the following:
+**
+** The copyright notices in the Software and this entire statement, including
+** the above license grant, this restriction and the following disclaimer,
+** must be included in all copies of the Software, in whole or in part, and
+** all derivative works of the Software, unless such copies or derivative
+** works are solely in the form of machine-executable object code generated by
+** a source language processor.
+**
+** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+** DEALINGS IN THE SOFTWARE.
+** -LICENSE-END-
+*/
+
+#ifndef BMD_DECKLINKAPIMODES_H
+#define BMD_DECKLINKAPIMODES_H
+
+
+#ifndef BMD_CONST
+ #if defined(_MSC_VER)
+ #define BMD_CONST __declspec(selectany) static const
+ #else
+ #define BMD_CONST static const
+ #endif
+#endif
+
+// Type Declarations
+
+
+// Interface ID Declarations
+
+BMD_CONST REFIID IID_IDeckLinkDisplayModeIterator = /* 9C88499F-F601-4021-B80B-032E4EB41C35 */ {0x9C,0x88,0x49,0x9F,0xF6,0x01,0x40,0x21,0xB8,0x0B,0x03,0x2E,0x4E,0xB4,0x1C,0x35};
+BMD_CONST REFIID IID_IDeckLinkDisplayMode = /* 3EB2C1AB-0A3D-4523-A3AD-F40D7FB14E78 */ {0x3E,0xB2,0xC1,0xAB,0x0A,0x3D,0x45,0x23,0xA3,0xAD,0xF4,0x0D,0x7F,0xB1,0x4E,0x78};
+
+/* Enum BMDDisplayMode - Video display modes */
+
+typedef uint32_t BMDDisplayMode;
+enum _BMDDisplayMode {
+
+ /* SD Modes */
+
+ bmdModeNTSC = /* 'ntsc' */ 0x6E747363,
+ bmdModeNTSC2398 = /* 'nt23' */ 0x6E743233, // 3:2 pulldown
+ bmdModePAL = /* 'pal ' */ 0x70616C20,
+ bmdModeNTSCp = /* 'ntsp' */ 0x6E747370,
+ bmdModePALp = /* 'palp' */ 0x70616C70,
+
+ /* HD 1080 Modes */
+
+ bmdModeHD1080p2398 = /* '23ps' */ 0x32337073,
+ bmdModeHD1080p24 = /* '24ps' */ 0x32347073,
+ bmdModeHD1080p25 = /* 'Hp25' */ 0x48703235,
+ bmdModeHD1080p2997 = /* 'Hp29' */ 0x48703239,
+ bmdModeHD1080p30 = /* 'Hp30' */ 0x48703330,
+ bmdModeHD1080i50 = /* 'Hi50' */ 0x48693530,
+ bmdModeHD1080i5994 = /* 'Hi59' */ 0x48693539,
+ bmdModeHD1080i6000 = /* 'Hi60' */ 0x48693630, // N.B. This _really_ is 60.00 Hz.
+ bmdModeHD1080p50 = /* 'Hp50' */ 0x48703530,
+ bmdModeHD1080p5994 = /* 'Hp59' */ 0x48703539,
+ bmdModeHD1080p6000 = /* 'Hp60' */ 0x48703630, // N.B. This _really_ is 60.00 Hz.
+
+ /* HD 720 Modes */
+
+ bmdModeHD720p50 = /* 'hp50' */ 0x68703530,
+ bmdModeHD720p5994 = /* 'hp59' */ 0x68703539,
+ bmdModeHD720p60 = /* 'hp60' */ 0x68703630,
+
+ /* 2k Modes */
+
+ bmdMode2k2398 = /* '2k23' */ 0x326B3233,
+ bmdMode2k24 = /* '2k24' */ 0x326B3234,
+ bmdMode2k25 = /* '2k25' */ 0x326B3235,
+
+ /* DCI Modes (output only) */
+
+ bmdMode2kDCI2398 = /* '2d23' */ 0x32643233,
+ bmdMode2kDCI24 = /* '2d24' */ 0x32643234,
+ bmdMode2kDCI25 = /* '2d25' */ 0x32643235,
+
+ /* 4k Modes */
+
+ bmdMode4K2160p2398 = /* '4k23' */ 0x346B3233,
+ bmdMode4K2160p24 = /* '4k24' */ 0x346B3234,
+ bmdMode4K2160p25 = /* '4k25' */ 0x346B3235,
+ bmdMode4K2160p2997 = /* '4k29' */ 0x346B3239,
+ bmdMode4K2160p30 = /* '4k30' */ 0x346B3330,
+ bmdMode4K2160p50 = /* '4k50' */ 0x346B3530,
+ bmdMode4K2160p5994 = /* '4k59' */ 0x346B3539,
+ bmdMode4K2160p60 = /* '4k60' */ 0x346B3630,
+
+ /* DCI Modes (output only) */
+
+ bmdMode4kDCI2398 = /* '4d23' */ 0x34643233,
+ bmdMode4kDCI24 = /* '4d24' */ 0x34643234,
+ bmdMode4kDCI25 = /* '4d25' */ 0x34643235,
+
+ /* Special Modes */
+
+ bmdModeUnknown = /* 'iunk' */ 0x69756E6B
+};
+
+/* Enum BMDFieldDominance - Video field dominance */
+
+typedef uint32_t BMDFieldDominance;
+enum _BMDFieldDominance {
+ bmdUnknownFieldDominance = 0,
+ bmdLowerFieldFirst = /* 'lowr' */ 0x6C6F7772,
+ bmdUpperFieldFirst = /* 'uppr' */ 0x75707072,
+ bmdProgressiveFrame = /* 'prog' */ 0x70726F67,
+ bmdProgressiveSegmentedFrame = /* 'psf ' */ 0x70736620
+};
+
+/* Enum BMDPixelFormat - Video pixel formats supported for output/input */
+
+typedef uint32_t BMDPixelFormat;
+enum _BMDPixelFormat {
+ bmdFormat8BitYUV = /* '2vuy' */ 0x32767579,
+ bmdFormat10BitYUV = /* 'v210' */ 0x76323130,
+ bmdFormat8BitARGB = 32,
+ bmdFormat8BitBGRA = /* 'BGRA' */ 0x42475241,
+ bmdFormat10BitRGB = /* 'r210' */ 0x72323130, // Big-endian RGB 10-bit per component with SMPTE video levels (64-960). Packed as 2:10:10:10
+ bmdFormat12BitRGB = /* 'R12B' */ 0x52313242, // Big-endian RGB 12-bit per component with full range (0-4095). Packed as 12-bit per component
+ bmdFormat12BitRGBLE = /* 'R12L' */ 0x5231324C, // Little-endian RGB 12-bit per component with full range (0-4095). Packed as 12-bit per component
+ bmdFormat10BitRGBXLE = /* 'R10l' */ 0x5231306C, // Little-endian 10-bit RGB with SMPTE video levels (64-940)
+ bmdFormat10BitRGBX = /* 'R10b' */ 0x52313062 // Big-endian 10-bit RGB with SMPTE video levels (64-940)
+};
+
+/* Enum BMDDisplayModeFlags - Flags to describe the characteristics of an IDeckLinkDisplayMode. */
+
+typedef uint32_t BMDDisplayModeFlags;
+enum _BMDDisplayModeFlags {
+ bmdDisplayModeSupports3D = 1 << 0,
+ bmdDisplayModeColorspaceRec601 = 1 << 1,
+ bmdDisplayModeColorspaceRec709 = 1 << 2
+};
+
+// Forward Declarations
+
+class IDeckLinkDisplayModeIterator;
+class IDeckLinkDisplayMode;
+
+/* Interface IDeckLinkDisplayModeIterator - enumerates over supported input/output display modes. */
+
+class IDeckLinkDisplayModeIterator : public IUnknown
+{
+public:
+ virtual HRESULT Next (/* out */ IDeckLinkDisplayMode **deckLinkDisplayMode) = 0;
+
+protected:
+ virtual ~IDeckLinkDisplayModeIterator () {} // call Release method to drop reference count
+};
+
+/* Interface IDeckLinkDisplayMode - represents a display mode */
+
+class IDeckLinkDisplayMode : public IUnknown
+{
+public:
+ virtual HRESULT GetName (/* out */ const char **name) = 0;
+ virtual BMDDisplayMode GetDisplayMode (void) = 0;
+ virtual long GetWidth (void) = 0;
+ virtual long GetHeight (void) = 0;
+ virtual HRESULT GetFrameRate (/* out */ BMDTimeValue *frameDuration, /* out */ BMDTimeScale *timeScale) = 0;
+ virtual BMDFieldDominance GetFieldDominance (void) = 0;
+ virtual BMDDisplayModeFlags GetFlags (void) = 0;
+
+protected:
+ virtual ~IDeckLinkDisplayMode () {} // call Release method to drop reference count
+};
+
+/* Functions */
+
+extern "C" {
+
+
+}
+
+
+#endif /* defined(BMD_DECKLINKAPIMODES_H) */
diff --git a/intern/decklink/linux/DeckLinkAPITypes.h b/intern/decklink/linux/DeckLinkAPITypes.h
new file mode 100644
index 00000000000..55e015f2a3c
--- /dev/null
+++ b/intern/decklink/linux/DeckLinkAPITypes.h
@@ -0,0 +1,110 @@
+/* -LICENSE-START-
+** Copyright (c) 2014 Blackmagic Design
+**
+** Permission is hereby granted, free of charge, to any person or organization
+** obtaining a copy of the software and accompanying documentation covered by
+** this license (the "Software") to use, reproduce, display, distribute,
+** execute, and transmit the Software, and to prepare derivative works of the
+** Software, and to permit third-parties to whom the Software is furnished to
+** do so, all subject to the following:
+**
+** The copyright notices in the Software and this entire statement, including
+** the above license grant, this restriction and the following disclaimer,
+** must be included in all copies of the Software, in whole or in part, and
+** all derivative works of the Software, unless such copies or derivative
+** works are solely in the form of machine-executable object code generated by
+** a source language processor.
+**
+** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+** DEALINGS IN THE SOFTWARE.
+** -LICENSE-END-
+*/
+
+#ifndef BMD_DECKLINKAPITYPES_H
+#define BMD_DECKLINKAPITYPES_H
+
+
+#ifndef BMD_CONST
+ #if defined(_MSC_VER)
+ #define BMD_CONST __declspec(selectany) static const
+ #else
+ #define BMD_CONST static const
+ #endif
+#endif
+
+// Type Declarations
+
+typedef int64_t BMDTimeValue;
+typedef int64_t BMDTimeScale;
+typedef uint32_t BMDTimecodeBCD;
+typedef uint32_t BMDTimecodeUserBits;
+
+// Interface ID Declarations
+
+BMD_CONST REFIID IID_IDeckLinkTimecode = /* BC6CFBD3-8317-4325-AC1C-1216391E9340 */ {0xBC,0x6C,0xFB,0xD3,0x83,0x17,0x43,0x25,0xAC,0x1C,0x12,0x16,0x39,0x1E,0x93,0x40};
+
+/* Enum BMDTimecodeFlags - Timecode flags */
+
+typedef uint32_t BMDTimecodeFlags;
+enum _BMDTimecodeFlags {
+ bmdTimecodeFlagDefault = 0,
+ bmdTimecodeIsDropFrame = 1 << 0,
+ bmdTimecodeFieldMark = 1 << 1
+};
+
+/* Enum BMDVideoConnection - Video connection types */
+
+typedef uint32_t BMDVideoConnection;
+enum _BMDVideoConnection {
+ bmdVideoConnectionSDI = 1 << 0,
+ bmdVideoConnectionHDMI = 1 << 1,
+ bmdVideoConnectionOpticalSDI = 1 << 2,
+ bmdVideoConnectionComponent = 1 << 3,
+ bmdVideoConnectionComposite = 1 << 4,
+ bmdVideoConnectionSVideo = 1 << 5
+};
+
+/* Enum BMDAudioConnection - Audio connection types */
+
+typedef uint32_t BMDAudioConnection;
+enum _BMDAudioConnection {
+ bmdAudioConnectionEmbedded = 1 << 0,
+ bmdAudioConnectionAESEBU = 1 << 1,
+ bmdAudioConnectionAnalog = 1 << 2,
+ bmdAudioConnectionAnalogXLR = 1 << 3,
+ bmdAudioConnectionAnalogRCA = 1 << 4
+};
+
+// Forward Declarations
+
+class IDeckLinkTimecode;
+
+/* Interface IDeckLinkTimecode - Used for video frame timecode representation. */
+
+class IDeckLinkTimecode : public IUnknown
+{
+public:
+ virtual BMDTimecodeBCD GetBCD (void) = 0;
+ virtual HRESULT GetComponents (/* out */ uint8_t *hours, /* out */ uint8_t *minutes, /* out */ uint8_t *seconds, /* out */ uint8_t *frames) = 0;
+ virtual HRESULT GetString (/* out */ const char **timecode) = 0;
+ virtual BMDTimecodeFlags GetFlags (void) = 0;
+ virtual HRESULT GetTimecodeUserBits (/* out */ BMDTimecodeUserBits *userBits) = 0;
+
+protected:
+ virtual ~IDeckLinkTimecode () {} // call Release method to drop reference count
+};
+
+/* Functions */
+
+extern "C" {
+
+
+}
+
+
+#endif /* defined(BMD_DECKLINKAPITYPES_H) */
diff --git a/intern/decklink/linux/DeckLinkAPIVersion.h b/intern/decklink/linux/DeckLinkAPIVersion.h
new file mode 100644
index 00000000000..cfcc701c427
--- /dev/null
+++ b/intern/decklink/linux/DeckLinkAPIVersion.h
@@ -0,0 +1,37 @@
+/* -LICENSE-START-
+ * ** Copyright (c) 2014 Blackmagic Design
+ * **
+ * ** Permission is hereby granted, free of charge, to any person or organization
+ * ** obtaining a copy of the software and accompanying documentation covered by
+ * ** this license (the "Software") to use, reproduce, display, distribute,
+ * ** execute, and transmit the Software, and to prepare derivative works of the
+ * ** Software, and to permit third-parties to whom the Software is furnished to
+ * ** do so, all subject to the following:
+ * **
+ * ** The copyright notices in the Software and this entire statement, including
+ * ** the above license grant, this restriction and the following disclaimer,
+ * ** must be included in all copies of the Software, in whole or in part, and
+ * ** all derivative works of the Software, unless such copies or derivative
+ * ** works are solely in the form of machine-executable object code generated by
+ * ** a source language processor.
+ * **
+ * ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * ** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+ * ** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+ * ** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ * ** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * ** DEALINGS IN THE SOFTWARE.
+ * ** -LICENSE-END-
+ * */
+
+/* DeckLinkAPIVersion.h */
+
+#ifndef __DeckLink_API_Version_h__
+#define __DeckLink_API_Version_h__
+
+#define BLACKMAGIC_DECKLINK_API_VERSION 0x0a040000
+#define BLACKMAGIC_DECKLINK_API_VERSION_STRING "10.4"
+
+#endif // __DeckLink_API_Version_h__
+
diff --git a/intern/decklink/linux/LinuxCOM.h b/intern/decklink/linux/LinuxCOM.h
new file mode 100644
index 00000000000..ee783bbd58f
--- /dev/null
+++ b/intern/decklink/linux/LinuxCOM.h
@@ -0,0 +1,100 @@
+/* -LICENSE-START-
+** Copyright (c) 2009 Blackmagic Design
+**
+** Permission is hereby granted, free of charge, to any person or organization
+** obtaining a copy of the software and accompanying documentation covered by
+** this license (the "Software") to use, reproduce, display, distribute,
+** execute, and transmit the Software, and to prepare derivative works of the
+** Software, and to permit third-parties to whom the Software is furnished to
+** do so, all subject to the following:
+**
+** The copyright notices in the Software and this entire statement, including
+** the above license grant, this restriction and the following disclaimer,
+** must be included in all copies of the Software, in whole or in part, and
+** all derivative works of the Software, unless such copies or derivative
+** works are solely in the form of machine-executable object code generated by
+** a source language processor.
+**
+** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+** DEALINGS IN THE SOFTWARE.
+** -LICENSE-END-
+*/
+
+#ifndef __LINUX_COM_H_
+#define __LINUX_COM_H_
+
+struct REFIID
+{
+ unsigned char byte0;
+ unsigned char byte1;
+ unsigned char byte2;
+ unsigned char byte3;
+ unsigned char byte4;
+ unsigned char byte5;
+ unsigned char byte6;
+ unsigned char byte7;
+ unsigned char byte8;
+ unsigned char byte9;
+ unsigned char byte10;
+ unsigned char byte11;
+ unsigned char byte12;
+ unsigned char byte13;
+ unsigned char byte14;
+ unsigned char byte15;
+};
+
+typedef REFIID CFUUIDBytes;
+#define CFUUIDGetUUIDBytes(x) x
+
+#define _HRESULT_DEFINED
+typedef int HRESULT;
+typedef unsigned long ULONG;
+typedef void *LPVOID;
+
+#define SUCCEEDED(Status) ((HRESULT)(Status) >= 0)
+#define FAILED(Status) ((HRESULT)(Status)<0)
+
+#define IS_ERROR(Status) ((unsigned long)(Status) >> 31 == SEVERITY_ERROR)
+#define HRESULT_CODE(hr) ((hr) & 0xFFFF)
+#define HRESULT_FACILITY(hr) (((hr) >> 16) & 0x1fff)
+#define HRESULT_SEVERITY(hr) (((hr) >> 31) & 0x1)
+#define SEVERITY_SUCCESS 0
+#define SEVERITY_ERROR 1
+
+#define MAKE_HRESULT(sev,fac,code) ((HRESULT) (((unsigned long)(sev)<<31) | ((unsigned long)(fac)<<16) | ((unsigned long)(code))) )
+
+#define S_OK ((HRESULT)0x00000000L)
+#define S_FALSE ((HRESULT)0x00000001L)
+#define E_UNEXPECTED ((HRESULT)0x8000FFFFL)
+#define E_NOTIMPL ((HRESULT)0x80000001L)
+#define E_OUTOFMEMORY ((HRESULT)0x80000002L)
+#define E_INVALIDARG ((HRESULT)0x80000003L)
+#define E_NOINTERFACE ((HRESULT)0x80000004L)
+#define E_POINTER ((HRESULT)0x80000005L)
+#define E_HANDLE ((HRESULT)0x80000006L)
+#define E_ABORT ((HRESULT)0x80000007L)
+#define E_FAIL ((HRESULT)0x80000008L)
+#define E_ACCESSDENIED ((HRESULT)0x80000009L)
+
+#define STDMETHODCALLTYPE
+
+#define IID_IUnknown (REFIID){0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}
+#define IUnknownUUID IID_IUnknown
+
+#ifdef __cplusplus
+class IUnknown
+{
+ public:
+ virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, LPVOID *ppv) = 0;
+ virtual ULONG STDMETHODCALLTYPE AddRef(void) = 0;
+ virtual ULONG STDMETHODCALLTYPE Release(void) = 0;
+};
+#endif
+
+#endif
+
diff --git a/intern/decklink/win/DeckLinkAPI_h.h b/intern/decklink/win/DeckLinkAPI_h.h
new file mode 100644
index 00000000000..1bd80b6dc95
--- /dev/null
+++ b/intern/decklink/win/DeckLinkAPI_h.h
@@ -0,0 +1,13323 @@
+
+
+/* this ALWAYS GENERATED file contains the definitions for the interfaces */
+
+
+ /* File created by MIDL compiler version 8.00.0603 */
+/* at Mon Apr 13 20:57:05 2015
+ */
+/* Compiler settings for ..\..\include\DeckLinkAPI.idl:
+ Oicf, W1, Zp8, env=Win64 (32b run), target_arch=AMD64 8.00.0603
+ protocol : dce , ms_ext, c_ext, robust
+ error checks: allocation ref bounds_check enum stub_data
+ VC __declspec() decoration level:
+ __declspec(uuid()), __declspec(selectany), __declspec(novtable)
+ DECLSPEC_UUID(), MIDL_INTERFACE()
+*/
+/* @@MIDL_FILE_HEADING( ) */
+
+#pragma warning( disable: 4049 ) /* more than 64k source lines */
+
+
+/* verify that the <rpcndr.h> version is high enough to compile this file*/
+#ifndef __REQUIRED_RPCNDR_H_VERSION__
+#define __REQUIRED_RPCNDR_H_VERSION__ 475
+#endif
+
+#include "rpc.h"
+#include "rpcndr.h"
+
+#ifndef __RPCNDR_H_VERSION__
+#error this stub requires an updated version of <rpcndr.h>
+#endif // __RPCNDR_H_VERSION__
+
+
+#ifndef __DeckLinkAPI_h_h__
+#define __DeckLinkAPI_h_h__
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+/* Forward Declarations */
+
+#ifndef __IDeckLinkTimecode_FWD_DEFINED__
+#define __IDeckLinkTimecode_FWD_DEFINED__
+typedef interface IDeckLinkTimecode IDeckLinkTimecode;
+
+#endif /* __IDeckLinkTimecode_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkDisplayModeIterator_FWD_DEFINED__
+#define __IDeckLinkDisplayModeIterator_FWD_DEFINED__
+typedef interface IDeckLinkDisplayModeIterator IDeckLinkDisplayModeIterator;
+
+#endif /* __IDeckLinkDisplayModeIterator_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkDisplayMode_FWD_DEFINED__
+#define __IDeckLinkDisplayMode_FWD_DEFINED__
+typedef interface IDeckLinkDisplayMode IDeckLinkDisplayMode;
+
+#endif /* __IDeckLinkDisplayMode_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLink_FWD_DEFINED__
+#define __IDeckLink_FWD_DEFINED__
+typedef interface IDeckLink IDeckLink;
+
+#endif /* __IDeckLink_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkConfiguration_FWD_DEFINED__
+#define __IDeckLinkConfiguration_FWD_DEFINED__
+typedef interface IDeckLinkConfiguration IDeckLinkConfiguration;
+
+#endif /* __IDeckLinkConfiguration_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkDeckControlStatusCallback_FWD_DEFINED__
+#define __IDeckLinkDeckControlStatusCallback_FWD_DEFINED__
+typedef interface IDeckLinkDeckControlStatusCallback IDeckLinkDeckControlStatusCallback;
+
+#endif /* __IDeckLinkDeckControlStatusCallback_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkDeckControl_FWD_DEFINED__
+#define __IDeckLinkDeckControl_FWD_DEFINED__
+typedef interface IDeckLinkDeckControl IDeckLinkDeckControl;
+
+#endif /* __IDeckLinkDeckControl_FWD_DEFINED__ */
+
+
+#ifndef __IBMDStreamingDeviceNotificationCallback_FWD_DEFINED__
+#define __IBMDStreamingDeviceNotificationCallback_FWD_DEFINED__
+typedef interface IBMDStreamingDeviceNotificationCallback IBMDStreamingDeviceNotificationCallback;
+
+#endif /* __IBMDStreamingDeviceNotificationCallback_FWD_DEFINED__ */
+
+
+#ifndef __IBMDStreamingH264InputCallback_FWD_DEFINED__
+#define __IBMDStreamingH264InputCallback_FWD_DEFINED__
+typedef interface IBMDStreamingH264InputCallback IBMDStreamingH264InputCallback;
+
+#endif /* __IBMDStreamingH264InputCallback_FWD_DEFINED__ */
+
+
+#ifndef __IBMDStreamingDiscovery_FWD_DEFINED__
+#define __IBMDStreamingDiscovery_FWD_DEFINED__
+typedef interface IBMDStreamingDiscovery IBMDStreamingDiscovery;
+
+#endif /* __IBMDStreamingDiscovery_FWD_DEFINED__ */
+
+
+#ifndef __IBMDStreamingVideoEncodingMode_FWD_DEFINED__
+#define __IBMDStreamingVideoEncodingMode_FWD_DEFINED__
+typedef interface IBMDStreamingVideoEncodingMode IBMDStreamingVideoEncodingMode;
+
+#endif /* __IBMDStreamingVideoEncodingMode_FWD_DEFINED__ */
+
+
+#ifndef __IBMDStreamingMutableVideoEncodingMode_FWD_DEFINED__
+#define __IBMDStreamingMutableVideoEncodingMode_FWD_DEFINED__
+typedef interface IBMDStreamingMutableVideoEncodingMode IBMDStreamingMutableVideoEncodingMode;
+
+#endif /* __IBMDStreamingMutableVideoEncodingMode_FWD_DEFINED__ */
+
+
+#ifndef __IBMDStreamingVideoEncodingModePresetIterator_FWD_DEFINED__
+#define __IBMDStreamingVideoEncodingModePresetIterator_FWD_DEFINED__
+typedef interface IBMDStreamingVideoEncodingModePresetIterator IBMDStreamingVideoEncodingModePresetIterator;
+
+#endif /* __IBMDStreamingVideoEncodingModePresetIterator_FWD_DEFINED__ */
+
+
+#ifndef __IBMDStreamingDeviceInput_FWD_DEFINED__
+#define __IBMDStreamingDeviceInput_FWD_DEFINED__
+typedef interface IBMDStreamingDeviceInput IBMDStreamingDeviceInput;
+
+#endif /* __IBMDStreamingDeviceInput_FWD_DEFINED__ */
+
+
+#ifndef __IBMDStreamingH264NALPacket_FWD_DEFINED__
+#define __IBMDStreamingH264NALPacket_FWD_DEFINED__
+typedef interface IBMDStreamingH264NALPacket IBMDStreamingH264NALPacket;
+
+#endif /* __IBMDStreamingH264NALPacket_FWD_DEFINED__ */
+
+
+#ifndef __IBMDStreamingAudioPacket_FWD_DEFINED__
+#define __IBMDStreamingAudioPacket_FWD_DEFINED__
+typedef interface IBMDStreamingAudioPacket IBMDStreamingAudioPacket;
+
+#endif /* __IBMDStreamingAudioPacket_FWD_DEFINED__ */
+
+
+#ifndef __IBMDStreamingMPEG2TSPacket_FWD_DEFINED__
+#define __IBMDStreamingMPEG2TSPacket_FWD_DEFINED__
+typedef interface IBMDStreamingMPEG2TSPacket IBMDStreamingMPEG2TSPacket;
+
+#endif /* __IBMDStreamingMPEG2TSPacket_FWD_DEFINED__ */
+
+
+#ifndef __IBMDStreamingH264NALParser_FWD_DEFINED__
+#define __IBMDStreamingH264NALParser_FWD_DEFINED__
+typedef interface IBMDStreamingH264NALParser IBMDStreamingH264NALParser;
+
+#endif /* __IBMDStreamingH264NALParser_FWD_DEFINED__ */
+
+
+#ifndef __CBMDStreamingDiscovery_FWD_DEFINED__
+#define __CBMDStreamingDiscovery_FWD_DEFINED__
+
+#ifdef __cplusplus
+typedef class CBMDStreamingDiscovery CBMDStreamingDiscovery;
+#else
+typedef struct CBMDStreamingDiscovery CBMDStreamingDiscovery;
+#endif /* __cplusplus */
+
+#endif /* __CBMDStreamingDiscovery_FWD_DEFINED__ */
+
+
+#ifndef __CBMDStreamingH264NALParser_FWD_DEFINED__
+#define __CBMDStreamingH264NALParser_FWD_DEFINED__
+
+#ifdef __cplusplus
+typedef class CBMDStreamingH264NALParser CBMDStreamingH264NALParser;
+#else
+typedef struct CBMDStreamingH264NALParser CBMDStreamingH264NALParser;
+#endif /* __cplusplus */
+
+#endif /* __CBMDStreamingH264NALParser_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkVideoOutputCallback_FWD_DEFINED__
+#define __IDeckLinkVideoOutputCallback_FWD_DEFINED__
+typedef interface IDeckLinkVideoOutputCallback IDeckLinkVideoOutputCallback;
+
+#endif /* __IDeckLinkVideoOutputCallback_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkInputCallback_FWD_DEFINED__
+#define __IDeckLinkInputCallback_FWD_DEFINED__
+typedef interface IDeckLinkInputCallback IDeckLinkInputCallback;
+
+#endif /* __IDeckLinkInputCallback_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkMemoryAllocator_FWD_DEFINED__
+#define __IDeckLinkMemoryAllocator_FWD_DEFINED__
+typedef interface IDeckLinkMemoryAllocator IDeckLinkMemoryAllocator;
+
+#endif /* __IDeckLinkMemoryAllocator_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkAudioOutputCallback_FWD_DEFINED__
+#define __IDeckLinkAudioOutputCallback_FWD_DEFINED__
+typedef interface IDeckLinkAudioOutputCallback IDeckLinkAudioOutputCallback;
+
+#endif /* __IDeckLinkAudioOutputCallback_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkIterator_FWD_DEFINED__
+#define __IDeckLinkIterator_FWD_DEFINED__
+typedef interface IDeckLinkIterator IDeckLinkIterator;
+
+#endif /* __IDeckLinkIterator_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkAPIInformation_FWD_DEFINED__
+#define __IDeckLinkAPIInformation_FWD_DEFINED__
+typedef interface IDeckLinkAPIInformation IDeckLinkAPIInformation;
+
+#endif /* __IDeckLinkAPIInformation_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkOutput_FWD_DEFINED__
+#define __IDeckLinkOutput_FWD_DEFINED__
+typedef interface IDeckLinkOutput IDeckLinkOutput;
+
+#endif /* __IDeckLinkOutput_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkInput_FWD_DEFINED__
+#define __IDeckLinkInput_FWD_DEFINED__
+typedef interface IDeckLinkInput IDeckLinkInput;
+
+#endif /* __IDeckLinkInput_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkVideoFrame_FWD_DEFINED__
+#define __IDeckLinkVideoFrame_FWD_DEFINED__
+typedef interface IDeckLinkVideoFrame IDeckLinkVideoFrame;
+
+#endif /* __IDeckLinkVideoFrame_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkMutableVideoFrame_FWD_DEFINED__
+#define __IDeckLinkMutableVideoFrame_FWD_DEFINED__
+typedef interface IDeckLinkMutableVideoFrame IDeckLinkMutableVideoFrame;
+
+#endif /* __IDeckLinkMutableVideoFrame_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkVideoFrame3DExtensions_FWD_DEFINED__
+#define __IDeckLinkVideoFrame3DExtensions_FWD_DEFINED__
+typedef interface IDeckLinkVideoFrame3DExtensions IDeckLinkVideoFrame3DExtensions;
+
+#endif /* __IDeckLinkVideoFrame3DExtensions_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkVideoInputFrame_FWD_DEFINED__
+#define __IDeckLinkVideoInputFrame_FWD_DEFINED__
+typedef interface IDeckLinkVideoInputFrame IDeckLinkVideoInputFrame;
+
+#endif /* __IDeckLinkVideoInputFrame_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkVideoFrameAncillary_FWD_DEFINED__
+#define __IDeckLinkVideoFrameAncillary_FWD_DEFINED__
+typedef interface IDeckLinkVideoFrameAncillary IDeckLinkVideoFrameAncillary;
+
+#endif /* __IDeckLinkVideoFrameAncillary_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkAudioInputPacket_FWD_DEFINED__
+#define __IDeckLinkAudioInputPacket_FWD_DEFINED__
+typedef interface IDeckLinkAudioInputPacket IDeckLinkAudioInputPacket;
+
+#endif /* __IDeckLinkAudioInputPacket_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkScreenPreviewCallback_FWD_DEFINED__
+#define __IDeckLinkScreenPreviewCallback_FWD_DEFINED__
+typedef interface IDeckLinkScreenPreviewCallback IDeckLinkScreenPreviewCallback;
+
+#endif /* __IDeckLinkScreenPreviewCallback_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkGLScreenPreviewHelper_FWD_DEFINED__
+#define __IDeckLinkGLScreenPreviewHelper_FWD_DEFINED__
+typedef interface IDeckLinkGLScreenPreviewHelper IDeckLinkGLScreenPreviewHelper;
+
+#endif /* __IDeckLinkGLScreenPreviewHelper_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkDX9ScreenPreviewHelper_FWD_DEFINED__
+#define __IDeckLinkDX9ScreenPreviewHelper_FWD_DEFINED__
+typedef interface IDeckLinkDX9ScreenPreviewHelper IDeckLinkDX9ScreenPreviewHelper;
+
+#endif /* __IDeckLinkDX9ScreenPreviewHelper_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkNotificationCallback_FWD_DEFINED__
+#define __IDeckLinkNotificationCallback_FWD_DEFINED__
+typedef interface IDeckLinkNotificationCallback IDeckLinkNotificationCallback;
+
+#endif /* __IDeckLinkNotificationCallback_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkNotification_FWD_DEFINED__
+#define __IDeckLinkNotification_FWD_DEFINED__
+typedef interface IDeckLinkNotification IDeckLinkNotification;
+
+#endif /* __IDeckLinkNotification_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkAttributes_FWD_DEFINED__
+#define __IDeckLinkAttributes_FWD_DEFINED__
+typedef interface IDeckLinkAttributes IDeckLinkAttributes;
+
+#endif /* __IDeckLinkAttributes_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkKeyer_FWD_DEFINED__
+#define __IDeckLinkKeyer_FWD_DEFINED__
+typedef interface IDeckLinkKeyer IDeckLinkKeyer;
+
+#endif /* __IDeckLinkKeyer_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkVideoConversion_FWD_DEFINED__
+#define __IDeckLinkVideoConversion_FWD_DEFINED__
+typedef interface IDeckLinkVideoConversion IDeckLinkVideoConversion;
+
+#endif /* __IDeckLinkVideoConversion_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkDeviceNotificationCallback_FWD_DEFINED__
+#define __IDeckLinkDeviceNotificationCallback_FWD_DEFINED__
+typedef interface IDeckLinkDeviceNotificationCallback IDeckLinkDeviceNotificationCallback;
+
+#endif /* __IDeckLinkDeviceNotificationCallback_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkDiscovery_FWD_DEFINED__
+#define __IDeckLinkDiscovery_FWD_DEFINED__
+typedef interface IDeckLinkDiscovery IDeckLinkDiscovery;
+
+#endif /* __IDeckLinkDiscovery_FWD_DEFINED__ */
+
+
+#ifndef __CDeckLinkIterator_FWD_DEFINED__
+#define __CDeckLinkIterator_FWD_DEFINED__
+
+#ifdef __cplusplus
+typedef class CDeckLinkIterator CDeckLinkIterator;
+#else
+typedef struct CDeckLinkIterator CDeckLinkIterator;
+#endif /* __cplusplus */
+
+#endif /* __CDeckLinkIterator_FWD_DEFINED__ */
+
+
+#ifndef __CDeckLinkAPIInformation_FWD_DEFINED__
+#define __CDeckLinkAPIInformation_FWD_DEFINED__
+
+#ifdef __cplusplus
+typedef class CDeckLinkAPIInformation CDeckLinkAPIInformation;
+#else
+typedef struct CDeckLinkAPIInformation CDeckLinkAPIInformation;
+#endif /* __cplusplus */
+
+#endif /* __CDeckLinkAPIInformation_FWD_DEFINED__ */
+
+
+#ifndef __CDeckLinkGLScreenPreviewHelper_FWD_DEFINED__
+#define __CDeckLinkGLScreenPreviewHelper_FWD_DEFINED__
+
+#ifdef __cplusplus
+typedef class CDeckLinkGLScreenPreviewHelper CDeckLinkGLScreenPreviewHelper;
+#else
+typedef struct CDeckLinkGLScreenPreviewHelper CDeckLinkGLScreenPreviewHelper;
+#endif /* __cplusplus */
+
+#endif /* __CDeckLinkGLScreenPreviewHelper_FWD_DEFINED__ */
+
+
+#ifndef __CDeckLinkDX9ScreenPreviewHelper_FWD_DEFINED__
+#define __CDeckLinkDX9ScreenPreviewHelper_FWD_DEFINED__
+
+#ifdef __cplusplus
+typedef class CDeckLinkDX9ScreenPreviewHelper CDeckLinkDX9ScreenPreviewHelper;
+#else
+typedef struct CDeckLinkDX9ScreenPreviewHelper CDeckLinkDX9ScreenPreviewHelper;
+#endif /* __cplusplus */
+
+#endif /* __CDeckLinkDX9ScreenPreviewHelper_FWD_DEFINED__ */
+
+
+#ifndef __CDeckLinkVideoConversion_FWD_DEFINED__
+#define __CDeckLinkVideoConversion_FWD_DEFINED__
+
+#ifdef __cplusplus
+typedef class CDeckLinkVideoConversion CDeckLinkVideoConversion;
+#else
+typedef struct CDeckLinkVideoConversion CDeckLinkVideoConversion;
+#endif /* __cplusplus */
+
+#endif /* __CDeckLinkVideoConversion_FWD_DEFINED__ */
+
+
+#ifndef __CDeckLinkDiscovery_FWD_DEFINED__
+#define __CDeckLinkDiscovery_FWD_DEFINED__
+
+#ifdef __cplusplus
+typedef class CDeckLinkDiscovery CDeckLinkDiscovery;
+#else
+typedef struct CDeckLinkDiscovery CDeckLinkDiscovery;
+#endif /* __cplusplus */
+
+#endif /* __CDeckLinkDiscovery_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkConfiguration_v10_2_FWD_DEFINED__
+#define __IDeckLinkConfiguration_v10_2_FWD_DEFINED__
+typedef interface IDeckLinkConfiguration_v10_2 IDeckLinkConfiguration_v10_2;
+
+#endif /* __IDeckLinkConfiguration_v10_2_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkOutput_v9_9_FWD_DEFINED__
+#define __IDeckLinkOutput_v9_9_FWD_DEFINED__
+typedef interface IDeckLinkOutput_v9_9 IDeckLinkOutput_v9_9;
+
+#endif /* __IDeckLinkOutput_v9_9_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkInput_v9_2_FWD_DEFINED__
+#define __IDeckLinkInput_v9_2_FWD_DEFINED__
+typedef interface IDeckLinkInput_v9_2 IDeckLinkInput_v9_2;
+
+#endif /* __IDeckLinkInput_v9_2_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkDeckControlStatusCallback_v8_1_FWD_DEFINED__
+#define __IDeckLinkDeckControlStatusCallback_v8_1_FWD_DEFINED__
+typedef interface IDeckLinkDeckControlStatusCallback_v8_1 IDeckLinkDeckControlStatusCallback_v8_1;
+
+#endif /* __IDeckLinkDeckControlStatusCallback_v8_1_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkDeckControl_v8_1_FWD_DEFINED__
+#define __IDeckLinkDeckControl_v8_1_FWD_DEFINED__
+typedef interface IDeckLinkDeckControl_v8_1 IDeckLinkDeckControl_v8_1;
+
+#endif /* __IDeckLinkDeckControl_v8_1_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLink_v8_0_FWD_DEFINED__
+#define __IDeckLink_v8_0_FWD_DEFINED__
+typedef interface IDeckLink_v8_0 IDeckLink_v8_0;
+
+#endif /* __IDeckLink_v8_0_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkIterator_v8_0_FWD_DEFINED__
+#define __IDeckLinkIterator_v8_0_FWD_DEFINED__
+typedef interface IDeckLinkIterator_v8_0 IDeckLinkIterator_v8_0;
+
+#endif /* __IDeckLinkIterator_v8_0_FWD_DEFINED__ */
+
+
+#ifndef __CDeckLinkIterator_v8_0_FWD_DEFINED__
+#define __CDeckLinkIterator_v8_0_FWD_DEFINED__
+
+#ifdef __cplusplus
+typedef class CDeckLinkIterator_v8_0 CDeckLinkIterator_v8_0;
+#else
+typedef struct CDeckLinkIterator_v8_0 CDeckLinkIterator_v8_0;
+#endif /* __cplusplus */
+
+#endif /* __CDeckLinkIterator_v8_0_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkDeckControl_v7_9_FWD_DEFINED__
+#define __IDeckLinkDeckControl_v7_9_FWD_DEFINED__
+typedef interface IDeckLinkDeckControl_v7_9 IDeckLinkDeckControl_v7_9;
+
+#endif /* __IDeckLinkDeckControl_v7_9_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkDisplayModeIterator_v7_6_FWD_DEFINED__
+#define __IDeckLinkDisplayModeIterator_v7_6_FWD_DEFINED__
+typedef interface IDeckLinkDisplayModeIterator_v7_6 IDeckLinkDisplayModeIterator_v7_6;
+
+#endif /* __IDeckLinkDisplayModeIterator_v7_6_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkDisplayMode_v7_6_FWD_DEFINED__
+#define __IDeckLinkDisplayMode_v7_6_FWD_DEFINED__
+typedef interface IDeckLinkDisplayMode_v7_6 IDeckLinkDisplayMode_v7_6;
+
+#endif /* __IDeckLinkDisplayMode_v7_6_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkOutput_v7_6_FWD_DEFINED__
+#define __IDeckLinkOutput_v7_6_FWD_DEFINED__
+typedef interface IDeckLinkOutput_v7_6 IDeckLinkOutput_v7_6;
+
+#endif /* __IDeckLinkOutput_v7_6_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkInput_v7_6_FWD_DEFINED__
+#define __IDeckLinkInput_v7_6_FWD_DEFINED__
+typedef interface IDeckLinkInput_v7_6 IDeckLinkInput_v7_6;
+
+#endif /* __IDeckLinkInput_v7_6_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkTimecode_v7_6_FWD_DEFINED__
+#define __IDeckLinkTimecode_v7_6_FWD_DEFINED__
+typedef interface IDeckLinkTimecode_v7_6 IDeckLinkTimecode_v7_6;
+
+#endif /* __IDeckLinkTimecode_v7_6_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkVideoFrame_v7_6_FWD_DEFINED__
+#define __IDeckLinkVideoFrame_v7_6_FWD_DEFINED__
+typedef interface IDeckLinkVideoFrame_v7_6 IDeckLinkVideoFrame_v7_6;
+
+#endif /* __IDeckLinkVideoFrame_v7_6_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkMutableVideoFrame_v7_6_FWD_DEFINED__
+#define __IDeckLinkMutableVideoFrame_v7_6_FWD_DEFINED__
+typedef interface IDeckLinkMutableVideoFrame_v7_6 IDeckLinkMutableVideoFrame_v7_6;
+
+#endif /* __IDeckLinkMutableVideoFrame_v7_6_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkVideoInputFrame_v7_6_FWD_DEFINED__
+#define __IDeckLinkVideoInputFrame_v7_6_FWD_DEFINED__
+typedef interface IDeckLinkVideoInputFrame_v7_6 IDeckLinkVideoInputFrame_v7_6;
+
+#endif /* __IDeckLinkVideoInputFrame_v7_6_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkScreenPreviewCallback_v7_6_FWD_DEFINED__
+#define __IDeckLinkScreenPreviewCallback_v7_6_FWD_DEFINED__
+typedef interface IDeckLinkScreenPreviewCallback_v7_6 IDeckLinkScreenPreviewCallback_v7_6;
+
+#endif /* __IDeckLinkScreenPreviewCallback_v7_6_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkGLScreenPreviewHelper_v7_6_FWD_DEFINED__
+#define __IDeckLinkGLScreenPreviewHelper_v7_6_FWD_DEFINED__
+typedef interface IDeckLinkGLScreenPreviewHelper_v7_6 IDeckLinkGLScreenPreviewHelper_v7_6;
+
+#endif /* __IDeckLinkGLScreenPreviewHelper_v7_6_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkVideoConversion_v7_6_FWD_DEFINED__
+#define __IDeckLinkVideoConversion_v7_6_FWD_DEFINED__
+typedef interface IDeckLinkVideoConversion_v7_6 IDeckLinkVideoConversion_v7_6;
+
+#endif /* __IDeckLinkVideoConversion_v7_6_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkConfiguration_v7_6_FWD_DEFINED__
+#define __IDeckLinkConfiguration_v7_6_FWD_DEFINED__
+typedef interface IDeckLinkConfiguration_v7_6 IDeckLinkConfiguration_v7_6;
+
+#endif /* __IDeckLinkConfiguration_v7_6_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkVideoOutputCallback_v7_6_FWD_DEFINED__
+#define __IDeckLinkVideoOutputCallback_v7_6_FWD_DEFINED__
+typedef interface IDeckLinkVideoOutputCallback_v7_6 IDeckLinkVideoOutputCallback_v7_6;
+
+#endif /* __IDeckLinkVideoOutputCallback_v7_6_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkInputCallback_v7_6_FWD_DEFINED__
+#define __IDeckLinkInputCallback_v7_6_FWD_DEFINED__
+typedef interface IDeckLinkInputCallback_v7_6 IDeckLinkInputCallback_v7_6;
+
+#endif /* __IDeckLinkInputCallback_v7_6_FWD_DEFINED__ */
+
+
+#ifndef __CDeckLinkGLScreenPreviewHelper_v7_6_FWD_DEFINED__
+#define __CDeckLinkGLScreenPreviewHelper_v7_6_FWD_DEFINED__
+
+#ifdef __cplusplus
+typedef class CDeckLinkGLScreenPreviewHelper_v7_6 CDeckLinkGLScreenPreviewHelper_v7_6;
+#else
+typedef struct CDeckLinkGLScreenPreviewHelper_v7_6 CDeckLinkGLScreenPreviewHelper_v7_6;
+#endif /* __cplusplus */
+
+#endif /* __CDeckLinkGLScreenPreviewHelper_v7_6_FWD_DEFINED__ */
+
+
+#ifndef __CDeckLinkVideoConversion_v7_6_FWD_DEFINED__
+#define __CDeckLinkVideoConversion_v7_6_FWD_DEFINED__
+
+#ifdef __cplusplus
+typedef class CDeckLinkVideoConversion_v7_6 CDeckLinkVideoConversion_v7_6;
+#else
+typedef struct CDeckLinkVideoConversion_v7_6 CDeckLinkVideoConversion_v7_6;
+#endif /* __cplusplus */
+
+#endif /* __CDeckLinkVideoConversion_v7_6_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkInputCallback_v7_3_FWD_DEFINED__
+#define __IDeckLinkInputCallback_v7_3_FWD_DEFINED__
+typedef interface IDeckLinkInputCallback_v7_3 IDeckLinkInputCallback_v7_3;
+
+#endif /* __IDeckLinkInputCallback_v7_3_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkOutput_v7_3_FWD_DEFINED__
+#define __IDeckLinkOutput_v7_3_FWD_DEFINED__
+typedef interface IDeckLinkOutput_v7_3 IDeckLinkOutput_v7_3;
+
+#endif /* __IDeckLinkOutput_v7_3_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkInput_v7_3_FWD_DEFINED__
+#define __IDeckLinkInput_v7_3_FWD_DEFINED__
+typedef interface IDeckLinkInput_v7_3 IDeckLinkInput_v7_3;
+
+#endif /* __IDeckLinkInput_v7_3_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkVideoInputFrame_v7_3_FWD_DEFINED__
+#define __IDeckLinkVideoInputFrame_v7_3_FWD_DEFINED__
+typedef interface IDeckLinkVideoInputFrame_v7_3 IDeckLinkVideoInputFrame_v7_3;
+
+#endif /* __IDeckLinkVideoInputFrame_v7_3_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkDisplayModeIterator_v7_1_FWD_DEFINED__
+#define __IDeckLinkDisplayModeIterator_v7_1_FWD_DEFINED__
+typedef interface IDeckLinkDisplayModeIterator_v7_1 IDeckLinkDisplayModeIterator_v7_1;
+
+#endif /* __IDeckLinkDisplayModeIterator_v7_1_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkDisplayMode_v7_1_FWD_DEFINED__
+#define __IDeckLinkDisplayMode_v7_1_FWD_DEFINED__
+typedef interface IDeckLinkDisplayMode_v7_1 IDeckLinkDisplayMode_v7_1;
+
+#endif /* __IDeckLinkDisplayMode_v7_1_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkVideoFrame_v7_1_FWD_DEFINED__
+#define __IDeckLinkVideoFrame_v7_1_FWD_DEFINED__
+typedef interface IDeckLinkVideoFrame_v7_1 IDeckLinkVideoFrame_v7_1;
+
+#endif /* __IDeckLinkVideoFrame_v7_1_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkVideoInputFrame_v7_1_FWD_DEFINED__
+#define __IDeckLinkVideoInputFrame_v7_1_FWD_DEFINED__
+typedef interface IDeckLinkVideoInputFrame_v7_1 IDeckLinkVideoInputFrame_v7_1;
+
+#endif /* __IDeckLinkVideoInputFrame_v7_1_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkAudioInputPacket_v7_1_FWD_DEFINED__
+#define __IDeckLinkAudioInputPacket_v7_1_FWD_DEFINED__
+typedef interface IDeckLinkAudioInputPacket_v7_1 IDeckLinkAudioInputPacket_v7_1;
+
+#endif /* __IDeckLinkAudioInputPacket_v7_1_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkVideoOutputCallback_v7_1_FWD_DEFINED__
+#define __IDeckLinkVideoOutputCallback_v7_1_FWD_DEFINED__
+typedef interface IDeckLinkVideoOutputCallback_v7_1 IDeckLinkVideoOutputCallback_v7_1;
+
+#endif /* __IDeckLinkVideoOutputCallback_v7_1_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkInputCallback_v7_1_FWD_DEFINED__
+#define __IDeckLinkInputCallback_v7_1_FWD_DEFINED__
+typedef interface IDeckLinkInputCallback_v7_1 IDeckLinkInputCallback_v7_1;
+
+#endif /* __IDeckLinkInputCallback_v7_1_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkOutput_v7_1_FWD_DEFINED__
+#define __IDeckLinkOutput_v7_1_FWD_DEFINED__
+typedef interface IDeckLinkOutput_v7_1 IDeckLinkOutput_v7_1;
+
+#endif /* __IDeckLinkOutput_v7_1_FWD_DEFINED__ */
+
+
+#ifndef __IDeckLinkInput_v7_1_FWD_DEFINED__
+#define __IDeckLinkInput_v7_1_FWD_DEFINED__
+typedef interface IDeckLinkInput_v7_1 IDeckLinkInput_v7_1;
+
+#endif /* __IDeckLinkInput_v7_1_FWD_DEFINED__ */
+
+
+/* header files for imported files */
+#include "unknwn.h"
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+
+
+#ifndef __DeckLinkAPI_LIBRARY_DEFINED__
+#define __DeckLinkAPI_LIBRARY_DEFINED__
+
+/* library DeckLinkAPI */
+/* [helpstring][version][uuid] */
+
+typedef LONGLONG BMDTimeValue;
+
+typedef LONGLONG BMDTimeScale;
+
+typedef unsigned int BMDTimecodeBCD;
+
+typedef unsigned int BMDTimecodeUserBits;
+
+typedef unsigned int BMDTimecodeFlags;
+#if 0
+typedef enum _BMDTimecodeFlags BMDTimecodeFlags;
+
+#endif
+/* [v1_enum] */
+enum _BMDTimecodeFlags
+ {
+ bmdTimecodeFlagDefault = 0,
+ bmdTimecodeIsDropFrame = ( 1 << 0 ) ,
+ bmdTimecodeFieldMark = ( 1 << 1 )
+ } ;
+typedef /* [v1_enum] */
+enum _BMDVideoConnection
+ {
+ bmdVideoConnectionSDI = ( 1 << 0 ) ,
+ bmdVideoConnectionHDMI = ( 1 << 1 ) ,
+ bmdVideoConnectionOpticalSDI = ( 1 << 2 ) ,
+ bmdVideoConnectionComponent = ( 1 << 3 ) ,
+ bmdVideoConnectionComposite = ( 1 << 4 ) ,
+ bmdVideoConnectionSVideo = ( 1 << 5 )
+ } BMDVideoConnection;
+
+typedef /* [v1_enum] */
+enum _BMDAudioConnection
+ {
+ bmdAudioConnectionEmbedded = ( 1 << 0 ) ,
+ bmdAudioConnectionAESEBU = ( 1 << 1 ) ,
+ bmdAudioConnectionAnalog = ( 1 << 2 ) ,
+ bmdAudioConnectionAnalogXLR = ( 1 << 3 ) ,
+ bmdAudioConnectionAnalogRCA = ( 1 << 4 )
+ } BMDAudioConnection;
+
+
+typedef unsigned int BMDDisplayModeFlags;
+#if 0
+typedef enum _BMDDisplayModeFlags BMDDisplayModeFlags;
+
+#endif
+typedef /* [v1_enum] */
+enum _BMDDisplayMode
+ {
+ bmdModeNTSC = 0x6e747363,
+ bmdModeNTSC2398 = 0x6e743233,
+ bmdModePAL = 0x70616c20,
+ bmdModeNTSCp = 0x6e747370,
+ bmdModePALp = 0x70616c70,
+ bmdModeHD1080p2398 = 0x32337073,
+ bmdModeHD1080p24 = 0x32347073,
+ bmdModeHD1080p25 = 0x48703235,
+ bmdModeHD1080p2997 = 0x48703239,
+ bmdModeHD1080p30 = 0x48703330,
+ bmdModeHD1080i50 = 0x48693530,
+ bmdModeHD1080i5994 = 0x48693539,
+ bmdModeHD1080i6000 = 0x48693630,
+ bmdModeHD1080p50 = 0x48703530,
+ bmdModeHD1080p5994 = 0x48703539,
+ bmdModeHD1080p6000 = 0x48703630,
+ bmdModeHD720p50 = 0x68703530,
+ bmdModeHD720p5994 = 0x68703539,
+ bmdModeHD720p60 = 0x68703630,
+ bmdMode2k2398 = 0x326b3233,
+ bmdMode2k24 = 0x326b3234,
+ bmdMode2k25 = 0x326b3235,
+ bmdMode2kDCI2398 = 0x32643233,
+ bmdMode2kDCI24 = 0x32643234,
+ bmdMode2kDCI25 = 0x32643235,
+ bmdMode4K2160p2398 = 0x346b3233,
+ bmdMode4K2160p24 = 0x346b3234,
+ bmdMode4K2160p25 = 0x346b3235,
+ bmdMode4K2160p2997 = 0x346b3239,
+ bmdMode4K2160p30 = 0x346b3330,
+ bmdMode4K2160p50 = 0x346b3530,
+ bmdMode4K2160p5994 = 0x346b3539,
+ bmdMode4K2160p60 = 0x346b3630,
+ bmdMode4kDCI2398 = 0x34643233,
+ bmdMode4kDCI24 = 0x34643234,
+ bmdMode4kDCI25 = 0x34643235,
+ bmdModeUnknown = 0x69756e6b
+ } BMDDisplayMode;
+
+typedef /* [v1_enum] */
+enum _BMDFieldDominance
+ {
+ bmdUnknownFieldDominance = 0,
+ bmdLowerFieldFirst = 0x6c6f7772,
+ bmdUpperFieldFirst = 0x75707072,
+ bmdProgressiveFrame = 0x70726f67,
+ bmdProgressiveSegmentedFrame = 0x70736620
+ } BMDFieldDominance;
+
+typedef /* [v1_enum] */
+enum _BMDPixelFormat
+ {
+ bmdFormat8BitYUV = 0x32767579,
+ bmdFormat10BitYUV = 0x76323130,
+ bmdFormat8BitARGB = 32,
+ bmdFormat8BitBGRA = 0x42475241,
+ bmdFormat10BitRGB = 0x72323130,
+ bmdFormat12BitRGB = 0x52313242,
+ bmdFormat12BitRGBLE = 0x5231324c,
+ bmdFormat10BitRGBXLE = 0x5231306c,
+ bmdFormat10BitRGBX = 0x52313062
+ } BMDPixelFormat;
+
+/* [v1_enum] */
+enum _BMDDisplayModeFlags
+ {
+ bmdDisplayModeSupports3D = ( 1 << 0 ) ,
+ bmdDisplayModeColorspaceRec601 = ( 1 << 1 ) ,
+ bmdDisplayModeColorspaceRec709 = ( 1 << 2 )
+ } ;
+
+
+#if 0
+#endif
+
+#if 0
+#endif
+typedef /* [v1_enum] */
+enum _BMDDeckLinkConfigurationID
+ {
+ bmdDeckLinkConfigSwapSerialRxTx = 0x73737274,
+ bmdDeckLinkConfigUse1080pNotPsF = 0x6670726f,
+ bmdDeckLinkConfigHDMI3DPackingFormat = 0x33647066,
+ bmdDeckLinkConfigBypass = 0x62797073,
+ bmdDeckLinkConfigClockTimingAdjustment = 0x63746164,
+ bmdDeckLinkConfigAnalogAudioConsumerLevels = 0x6161636c,
+ bmdDeckLinkConfigFieldFlickerRemoval = 0x66646672,
+ bmdDeckLinkConfigHD1080p24ToHD1080i5994Conversion = 0x746f3539,
+ bmdDeckLinkConfig444SDIVideoOutput = 0x3434346f,
+ bmdDeckLinkConfigSingleLinkVideoOutput = 0x73676c6f,
+ bmdDeckLinkConfigBlackVideoOutputDuringCapture = 0x62766f63,
+ bmdDeckLinkConfigLowLatencyVideoOutput = 0x6c6c766f,
+ bmdDeckLinkConfigDownConversionOnAllAnalogOutput = 0x6361616f,
+ bmdDeckLinkConfigSMPTELevelAOutput = 0x736d7461,
+ bmdDeckLinkConfigVideoOutputConnection = 0x766f636e,
+ bmdDeckLinkConfigVideoOutputConversionMode = 0x766f636d,
+ bmdDeckLinkConfigAnalogVideoOutputFlags = 0x61766f66,
+ bmdDeckLinkConfigReferenceInputTimingOffset = 0x676c6f74,
+ bmdDeckLinkConfigVideoOutputIdleOperation = 0x766f696f,
+ bmdDeckLinkConfigDefaultVideoOutputMode = 0x64766f6d,
+ bmdDeckLinkConfigDefaultVideoOutputModeFlags = 0x64766f66,
+ bmdDeckLinkConfigVideoOutputComponentLumaGain = 0x6f636c67,
+ bmdDeckLinkConfigVideoOutputComponentChromaBlueGain = 0x6f636362,
+ bmdDeckLinkConfigVideoOutputComponentChromaRedGain = 0x6f636372,
+ bmdDeckLinkConfigVideoOutputCompositeLumaGain = 0x6f696c67,
+ bmdDeckLinkConfigVideoOutputCompositeChromaGain = 0x6f696367,
+ bmdDeckLinkConfigVideoOutputSVideoLumaGain = 0x6f736c67,
+ bmdDeckLinkConfigVideoOutputSVideoChromaGain = 0x6f736367,
+ bmdDeckLinkConfigVideoInputScanning = 0x76697363,
+ bmdDeckLinkConfigUseDedicatedLTCInput = 0x646c7463,
+ bmdDeckLinkConfigVideoInputConnection = 0x7669636e,
+ bmdDeckLinkConfigAnalogVideoInputFlags = 0x61766966,
+ bmdDeckLinkConfigVideoInputConversionMode = 0x7669636d,
+ bmdDeckLinkConfig32PulldownSequenceInitialTimecodeFrame = 0x70646966,
+ bmdDeckLinkConfigVANCSourceLine1Mapping = 0x76736c31,
+ bmdDeckLinkConfigVANCSourceLine2Mapping = 0x76736c32,
+ bmdDeckLinkConfigVANCSourceLine3Mapping = 0x76736c33,
+ bmdDeckLinkConfigCapturePassThroughMode = 0x6370746d,
+ bmdDeckLinkConfigVideoInputComponentLumaGain = 0x69636c67,
+ bmdDeckLinkConfigVideoInputComponentChromaBlueGain = 0x69636362,
+ bmdDeckLinkConfigVideoInputComponentChromaRedGain = 0x69636372,
+ bmdDeckLinkConfigVideoInputCompositeLumaGain = 0x69696c67,
+ bmdDeckLinkConfigVideoInputCompositeChromaGain = 0x69696367,
+ bmdDeckLinkConfigVideoInputSVideoLumaGain = 0x69736c67,
+ bmdDeckLinkConfigVideoInputSVideoChromaGain = 0x69736367,
+ bmdDeckLinkConfigAudioInputConnection = 0x6169636e,
+ bmdDeckLinkConfigAnalogAudioInputScaleChannel1 = 0x61697331,
+ bmdDeckLinkConfigAnalogAudioInputScaleChannel2 = 0x61697332,
+ bmdDeckLinkConfigAnalogAudioInputScaleChannel3 = 0x61697333,
+ bmdDeckLinkConfigAnalogAudioInputScaleChannel4 = 0x61697334,
+ bmdDeckLinkConfigDigitalAudioInputScale = 0x64616973,
+ bmdDeckLinkConfigAudioOutputAESAnalogSwitch = 0x616f6161,
+ bmdDeckLinkConfigAnalogAudioOutputScaleChannel1 = 0x616f7331,
+ bmdDeckLinkConfigAnalogAudioOutputScaleChannel2 = 0x616f7332,
+ bmdDeckLinkConfigAnalogAudioOutputScaleChannel3 = 0x616f7333,
+ bmdDeckLinkConfigAnalogAudioOutputScaleChannel4 = 0x616f7334,
+ bmdDeckLinkConfigDigitalAudioOutputScale = 0x64616f73,
+ bmdDeckLinkConfigDeviceInformationLabel = 0x64696c61,
+ bmdDeckLinkConfigDeviceInformationSerialNumber = 0x6469736e,
+ bmdDeckLinkConfigDeviceInformationCompany = 0x6469636f,
+ bmdDeckLinkConfigDeviceInformationPhone = 0x64697068,
+ bmdDeckLinkConfigDeviceInformationEmail = 0x6469656d,
+ bmdDeckLinkConfigDeviceInformationDate = 0x64696461
+ } BMDDeckLinkConfigurationID;
+
+
+typedef unsigned int BMDDeckControlStatusFlags;
+typedef unsigned int BMDDeckControlExportModeOpsFlags;
+#if 0
+typedef enum _BMDDeckControlStatusFlags BMDDeckControlStatusFlags;
+
+typedef enum _BMDDeckControlExportModeOpsFlags BMDDeckControlExportModeOpsFlags;
+
+#endif
+typedef /* [v1_enum] */
+enum _BMDDeckControlMode
+ {
+ bmdDeckControlNotOpened = 0x6e746f70,
+ bmdDeckControlVTRControlMode = 0x76747263,
+ bmdDeckControlExportMode = 0x6578706d,
+ bmdDeckControlCaptureMode = 0x6361706d
+ } BMDDeckControlMode;
+
+typedef /* [v1_enum] */
+enum _BMDDeckControlEvent
+ {
+ bmdDeckControlAbortedEvent = 0x61627465,
+ bmdDeckControlPrepareForExportEvent = 0x70666565,
+ bmdDeckControlExportCompleteEvent = 0x65786365,
+ bmdDeckControlPrepareForCaptureEvent = 0x70666365,
+ bmdDeckControlCaptureCompleteEvent = 0x63636576
+ } BMDDeckControlEvent;
+
+typedef /* [v1_enum] */
+enum _BMDDeckControlVTRControlState
+ {
+ bmdDeckControlNotInVTRControlMode = 0x6e76636d,
+ bmdDeckControlVTRControlPlaying = 0x76747270,
+ bmdDeckControlVTRControlRecording = 0x76747272,
+ bmdDeckControlVTRControlStill = 0x76747261,
+ bmdDeckControlVTRControlShuttleForward = 0x76747366,
+ bmdDeckControlVTRControlShuttleReverse = 0x76747372,
+ bmdDeckControlVTRControlJogForward = 0x76746a66,
+ bmdDeckControlVTRControlJogReverse = 0x76746a72,
+ bmdDeckControlVTRControlStopped = 0x7674726f
+ } BMDDeckControlVTRControlState;
+
+/* [v1_enum] */
+enum _BMDDeckControlStatusFlags
+ {
+ bmdDeckControlStatusDeckConnected = ( 1 << 0 ) ,
+ bmdDeckControlStatusRemoteMode = ( 1 << 1 ) ,
+ bmdDeckControlStatusRecordInhibited = ( 1 << 2 ) ,
+ bmdDeckControlStatusCassetteOut = ( 1 << 3 )
+ } ;
+/* [v1_enum] */
+enum _BMDDeckControlExportModeOpsFlags
+ {
+ bmdDeckControlExportModeInsertVideo = ( 1 << 0 ) ,
+ bmdDeckControlExportModeInsertAudio1 = ( 1 << 1 ) ,
+ bmdDeckControlExportModeInsertAudio2 = ( 1 << 2 ) ,
+ bmdDeckControlExportModeInsertAudio3 = ( 1 << 3 ) ,
+ bmdDeckControlExportModeInsertAudio4 = ( 1 << 4 ) ,
+ bmdDeckControlExportModeInsertAudio5 = ( 1 << 5 ) ,
+ bmdDeckControlExportModeInsertAudio6 = ( 1 << 6 ) ,
+ bmdDeckControlExportModeInsertAudio7 = ( 1 << 7 ) ,
+ bmdDeckControlExportModeInsertAudio8 = ( 1 << 8 ) ,
+ bmdDeckControlExportModeInsertAudio9 = ( 1 << 9 ) ,
+ bmdDeckControlExportModeInsertAudio10 = ( 1 << 10 ) ,
+ bmdDeckControlExportModeInsertAudio11 = ( 1 << 11 ) ,
+ bmdDeckControlExportModeInsertAudio12 = ( 1 << 12 ) ,
+ bmdDeckControlExportModeInsertTimeCode = ( 1 << 13 ) ,
+ bmdDeckControlExportModeInsertAssemble = ( 1 << 14 ) ,
+ bmdDeckControlExportModeInsertPreview = ( 1 << 15 ) ,
+ bmdDeckControlUseManualExport = ( 1 << 16 )
+ } ;
+typedef /* [v1_enum] */
+enum _BMDDeckControlError
+ {
+ bmdDeckControlNoError = 0x6e6f6572,
+ bmdDeckControlModeError = 0x6d6f6572,
+ bmdDeckControlMissedInPointError = 0x6d696572,
+ bmdDeckControlDeckTimeoutError = 0x64746572,
+ bmdDeckControlCommandFailedError = 0x63666572,
+ bmdDeckControlDeviceAlreadyOpenedError = 0x64616c6f,
+ bmdDeckControlFailedToOpenDeviceError = 0x66646572,
+ bmdDeckControlInLocalModeError = 0x6c6d6572,
+ bmdDeckControlEndOfTapeError = 0x65746572,
+ bmdDeckControlUserAbortError = 0x75616572,
+ bmdDeckControlNoTapeInDeckError = 0x6e746572,
+ bmdDeckControlNoVideoFromCardError = 0x6e766663,
+ bmdDeckControlNoCommunicationError = 0x6e636f6d,
+ bmdDeckControlBufferTooSmallError = 0x6274736d,
+ bmdDeckControlBadChecksumError = 0x63686b73,
+ bmdDeckControlUnknownError = 0x756e6572
+ } BMDDeckControlError;
+
+
+
+#if 0
+#endif
+typedef /* [v1_enum] */
+enum _BMDStreamingDeviceMode
+ {
+ bmdStreamingDeviceIdle = 0x69646c65,
+ bmdStreamingDeviceEncoding = 0x656e636f,
+ bmdStreamingDeviceStopping = 0x73746f70,
+ bmdStreamingDeviceUnknown = 0x6d756e6b
+ } BMDStreamingDeviceMode;
+
+typedef /* [v1_enum] */
+enum _BMDStreamingEncodingFrameRate
+ {
+ bmdStreamingEncodedFrameRate50i = 0x65353069,
+ bmdStreamingEncodedFrameRate5994i = 0x65353969,
+ bmdStreamingEncodedFrameRate60i = 0x65363069,
+ bmdStreamingEncodedFrameRate2398p = 0x65323370,
+ bmdStreamingEncodedFrameRate24p = 0x65323470,
+ bmdStreamingEncodedFrameRate25p = 0x65323570,
+ bmdStreamingEncodedFrameRate2997p = 0x65323970,
+ bmdStreamingEncodedFrameRate30p = 0x65333070,
+ bmdStreamingEncodedFrameRate50p = 0x65353070,
+ bmdStreamingEncodedFrameRate5994p = 0x65353970,
+ bmdStreamingEncodedFrameRate60p = 0x65363070
+ } BMDStreamingEncodingFrameRate;
+
+typedef /* [v1_enum] */
+enum _BMDStreamingEncodingSupport
+ {
+ bmdStreamingEncodingModeNotSupported = 0,
+ bmdStreamingEncodingModeSupported = ( bmdStreamingEncodingModeNotSupported + 1 ) ,
+ bmdStreamingEncodingModeSupportedWithChanges = ( bmdStreamingEncodingModeSupported + 1 )
+ } BMDStreamingEncodingSupport;
+
+typedef /* [v1_enum] */
+enum _BMDStreamingVideoCodec
+ {
+ bmdStreamingVideoCodecH264 = 0x48323634
+ } BMDStreamingVideoCodec;
+
+typedef /* [v1_enum] */
+enum _BMDStreamingH264Profile
+ {
+ bmdStreamingH264ProfileHigh = 0x68696768,
+ bmdStreamingH264ProfileMain = 0x6d61696e,
+ bmdStreamingH264ProfileBaseline = 0x62617365
+ } BMDStreamingH264Profile;
+
+typedef /* [v1_enum] */
+enum _BMDStreamingH264Level
+ {
+ bmdStreamingH264Level12 = 0x6c763132,
+ bmdStreamingH264Level13 = 0x6c763133,
+ bmdStreamingH264Level2 = 0x6c763220,
+ bmdStreamingH264Level21 = 0x6c763231,
+ bmdStreamingH264Level22 = 0x6c763232,
+ bmdStreamingH264Level3 = 0x6c763320,
+ bmdStreamingH264Level31 = 0x6c763331,
+ bmdStreamingH264Level32 = 0x6c763332,
+ bmdStreamingH264Level4 = 0x6c763420,
+ bmdStreamingH264Level41 = 0x6c763431,
+ bmdStreamingH264Level42 = 0x6c763432
+ } BMDStreamingH264Level;
+
+typedef /* [v1_enum] */
+enum _BMDStreamingH264EntropyCoding
+ {
+ bmdStreamingH264EntropyCodingCAVLC = 0x45564c43,
+ bmdStreamingH264EntropyCodingCABAC = 0x45424143
+ } BMDStreamingH264EntropyCoding;
+
+typedef /* [v1_enum] */
+enum _BMDStreamingAudioCodec
+ {
+ bmdStreamingAudioCodecAAC = 0x41414320
+ } BMDStreamingAudioCodec;
+
+typedef /* [v1_enum] */
+enum _BMDStreamingEncodingModePropertyID
+ {
+ bmdStreamingEncodingPropertyVideoFrameRate = 0x76667274,
+ bmdStreamingEncodingPropertyVideoBitRateKbps = 0x76627274,
+ bmdStreamingEncodingPropertyH264Profile = 0x68707266,
+ bmdStreamingEncodingPropertyH264Level = 0x686c766c,
+ bmdStreamingEncodingPropertyH264EntropyCoding = 0x68656e74,
+ bmdStreamingEncodingPropertyH264HasBFrames = 0x68426672,
+ bmdStreamingEncodingPropertyAudioCodec = 0x61636463,
+ bmdStreamingEncodingPropertyAudioSampleRate = 0x61737274,
+ bmdStreamingEncodingPropertyAudioChannelCount = 0x61636863,
+ bmdStreamingEncodingPropertyAudioBitRateKbps = 0x61627274
+ } BMDStreamingEncodingModePropertyID;
+
+
+
+
+
+
+
+
+
+
+
+
+typedef unsigned int BMDFrameFlags;
+typedef unsigned int BMDVideoInputFlags;
+typedef unsigned int BMDVideoInputFormatChangedEvents;
+typedef unsigned int BMDDetectedVideoInputFormatFlags;
+typedef unsigned int BMDDeckLinkCapturePassthroughMode;
+typedef unsigned int BMDAnalogVideoFlags;
+typedef unsigned int BMDDeviceBusyState;
+#if 0
+typedef enum _BMDFrameFlags BMDFrameFlags;
+
+typedef enum _BMDVideoInputFlags BMDVideoInputFlags;
+
+typedef enum _BMDVideoInputFormatChangedEvents BMDVideoInputFormatChangedEvents;
+
+typedef enum _BMDDetectedVideoInputFormatFlags BMDDetectedVideoInputFormatFlags;
+
+typedef enum _BMDDeckLinkCapturePassthroughMode BMDDeckLinkCapturePassthroughMode;
+
+typedef enum _BMDAnalogVideoFlags BMDAnalogVideoFlags;
+
+typedef enum _BMDDeviceBusyState BMDDeviceBusyState;
+
+#endif
+typedef /* [v1_enum] */
+enum _BMDVideoOutputFlags
+ {
+ bmdVideoOutputFlagDefault = 0,
+ bmdVideoOutputVANC = ( 1 << 0 ) ,
+ bmdVideoOutputVITC = ( 1 << 1 ) ,
+ bmdVideoOutputRP188 = ( 1 << 2 ) ,
+ bmdVideoOutputDualStream3D = ( 1 << 4 )
+ } BMDVideoOutputFlags;
+
+/* [v1_enum] */
+enum _BMDFrameFlags
+ {
+ bmdFrameFlagDefault = 0,
+ bmdFrameFlagFlipVertical = ( 1 << 0 ) ,
+ bmdFrameHasNoInputSource = ( 1 << 31 )
+ } ;
+/* [v1_enum] */
+enum _BMDVideoInputFlags
+ {
+ bmdVideoInputFlagDefault = 0,
+ bmdVideoInputEnableFormatDetection = ( 1 << 0 ) ,
+ bmdVideoInputDualStream3D = ( 1 << 1 )
+ } ;
+/* [v1_enum] */
+enum _BMDVideoInputFormatChangedEvents
+ {
+ bmdVideoInputDisplayModeChanged = ( 1 << 0 ) ,
+ bmdVideoInputFieldDominanceChanged = ( 1 << 1 ) ,
+ bmdVideoInputColorspaceChanged = ( 1 << 2 )
+ } ;
+/* [v1_enum] */
+enum _BMDDetectedVideoInputFormatFlags
+ {
+ bmdDetectedVideoInputYCbCr422 = ( 1 << 0 ) ,
+ bmdDetectedVideoInputRGB444 = ( 1 << 1 ) ,
+ bmdDetectedVideoInputDualStream3D = ( 1 << 2 )
+ } ;
+/* [v1_enum] */
+enum _BMDDeckLinkCapturePassthroughMode
+ {
+ bmdDeckLinkCapturePassthroughModeDirect = 0x70646972,
+ bmdDeckLinkCapturePassthroughModeCleanSwitch = 0x70636c6e
+ } ;
+typedef /* [v1_enum] */
+enum _BMDOutputFrameCompletionResult
+ {
+ bmdOutputFrameCompleted = 0,
+ bmdOutputFrameDisplayedLate = ( bmdOutputFrameCompleted + 1 ) ,
+ bmdOutputFrameDropped = ( bmdOutputFrameDisplayedLate + 1 ) ,
+ bmdOutputFrameFlushed = ( bmdOutputFrameDropped + 1 )
+ } BMDOutputFrameCompletionResult;
+
+typedef /* [v1_enum] */
+enum _BMDReferenceStatus
+ {
+ bmdReferenceNotSupportedByHardware = ( 1 << 0 ) ,
+ bmdReferenceLocked = ( 1 << 1 )
+ } BMDReferenceStatus;
+
+typedef /* [v1_enum] */
+enum _BMDAudioSampleRate
+ {
+ bmdAudioSampleRate48kHz = 48000
+ } BMDAudioSampleRate;
+
+typedef /* [v1_enum] */
+enum _BMDAudioSampleType
+ {
+ bmdAudioSampleType16bitInteger = 16,
+ bmdAudioSampleType32bitInteger = 32
+ } BMDAudioSampleType;
+
+typedef /* [v1_enum] */
+enum _BMDAudioOutputStreamType
+ {
+ bmdAudioOutputStreamContinuous = 0,
+ bmdAudioOutputStreamContinuousDontResample = ( bmdAudioOutputStreamContinuous + 1 ) ,
+ bmdAudioOutputStreamTimestamped = ( bmdAudioOutputStreamContinuousDontResample + 1 )
+ } BMDAudioOutputStreamType;
+
+typedef /* [v1_enum] */
+enum _BMDDisplayModeSupport
+ {
+ bmdDisplayModeNotSupported = 0,
+ bmdDisplayModeSupported = ( bmdDisplayModeNotSupported + 1 ) ,
+ bmdDisplayModeSupportedWithConversion = ( bmdDisplayModeSupported + 1 )
+ } BMDDisplayModeSupport;
+
+typedef /* [v1_enum] */
+enum _BMDTimecodeFormat
+ {
+ bmdTimecodeRP188VITC1 = 0x72707631,
+ bmdTimecodeRP188VITC2 = 0x72703132,
+ bmdTimecodeRP188LTC = 0x72706c74,
+ bmdTimecodeRP188Any = 0x72703138,
+ bmdTimecodeVITC = 0x76697463,
+ bmdTimecodeVITCField2 = 0x76697432,
+ bmdTimecodeSerial = 0x73657269
+ } BMDTimecodeFormat;
+
+/* [v1_enum] */
+enum _BMDAnalogVideoFlags
+ {
+ bmdAnalogVideoFlagCompositeSetup75 = ( 1 << 0 ) ,
+ bmdAnalogVideoFlagComponentBetacamLevels = ( 1 << 1 )
+ } ;
+typedef /* [v1_enum] */
+enum _BMDAudioOutputAnalogAESSwitch
+ {
+ bmdAudioOutputSwitchAESEBU = 0x61657320,
+ bmdAudioOutputSwitchAnalog = 0x616e6c67
+ } BMDAudioOutputAnalogAESSwitch;
+
+typedef /* [v1_enum] */
+enum _BMDVideoOutputConversionMode
+ {
+ bmdNoVideoOutputConversion = 0x6e6f6e65,
+ bmdVideoOutputLetterboxDownconversion = 0x6c746278,
+ bmdVideoOutputAnamorphicDownconversion = 0x616d7068,
+ bmdVideoOutputHD720toHD1080Conversion = 0x37323063,
+ bmdVideoOutputHardwareLetterboxDownconversion = 0x48576c62,
+ bmdVideoOutputHardwareAnamorphicDownconversion = 0x4857616d,
+ bmdVideoOutputHardwareCenterCutDownconversion = 0x48576363,
+ bmdVideoOutputHardware720p1080pCrossconversion = 0x78636170,
+ bmdVideoOutputHardwareAnamorphic720pUpconversion = 0x75613770,
+ bmdVideoOutputHardwareAnamorphic1080iUpconversion = 0x75613169,
+ bmdVideoOutputHardwareAnamorphic149To720pUpconversion = 0x75343770,
+ bmdVideoOutputHardwareAnamorphic149To1080iUpconversion = 0x75343169,
+ bmdVideoOutputHardwarePillarbox720pUpconversion = 0x75703770,
+ bmdVideoOutputHardwarePillarbox1080iUpconversion = 0x75703169
+ } BMDVideoOutputConversionMode;
+
+typedef /* [v1_enum] */
+enum _BMDVideoInputConversionMode
+ {
+ bmdNoVideoInputConversion = 0x6e6f6e65,
+ bmdVideoInputLetterboxDownconversionFromHD1080 = 0x31306c62,
+ bmdVideoInputAnamorphicDownconversionFromHD1080 = 0x3130616d,
+ bmdVideoInputLetterboxDownconversionFromHD720 = 0x37326c62,
+ bmdVideoInputAnamorphicDownconversionFromHD720 = 0x3732616d,
+ bmdVideoInputLetterboxUpconversion = 0x6c627570,
+ bmdVideoInputAnamorphicUpconversion = 0x616d7570
+ } BMDVideoInputConversionMode;
+
+typedef /* [v1_enum] */
+enum _BMDVideo3DPackingFormat
+ {
+ bmdVideo3DPackingSidebySideHalf = 0x73627368,
+ bmdVideo3DPackingLinebyLine = 0x6c62796c,
+ bmdVideo3DPackingTopAndBottom = 0x7461626f,
+ bmdVideo3DPackingFramePacking = 0x6672706b,
+ bmdVideo3DPackingLeftOnly = 0x6c656674,
+ bmdVideo3DPackingRightOnly = 0x72696768
+ } BMDVideo3DPackingFormat;
+
+typedef /* [v1_enum] */
+enum _BMDIdleVideoOutputOperation
+ {
+ bmdIdleVideoOutputBlack = 0x626c6163,
+ bmdIdleVideoOutputLastFrame = 0x6c616661,
+ bmdIdleVideoOutputDesktop = 0x6465736b
+ } BMDIdleVideoOutputOperation;
+
+typedef /* [v1_enum] */
+enum _BMDDeckLinkAttributeID
+ {
+ BMDDeckLinkSupportsInternalKeying = 0x6b657969,
+ BMDDeckLinkSupportsExternalKeying = 0x6b657965,
+ BMDDeckLinkSupportsHDKeying = 0x6b657968,
+ BMDDeckLinkSupportsInputFormatDetection = 0x696e6664,
+ BMDDeckLinkHasReferenceInput = 0x6872696e,
+ BMDDeckLinkHasSerialPort = 0x68737074,
+ BMDDeckLinkHasAnalogVideoOutputGain = 0x61766f67,
+ BMDDeckLinkCanOnlyAdjustOverallVideoOutputGain = 0x6f766f67,
+ BMDDeckLinkHasVideoInputAntiAliasingFilter = 0x6161666c,
+ BMDDeckLinkHasBypass = 0x62797073,
+ BMDDeckLinkSupportsDesktopDisplay = 0x65787464,
+ BMDDeckLinkSupportsClockTimingAdjustment = 0x63746164,
+ BMDDeckLinkSupportsFullDuplex = 0x66647570,
+ BMDDeckLinkSupportsFullFrameReferenceInputTimingOffset = 0x6672696e,
+ BMDDeckLinkSupportsSMPTELevelAOutput = 0x6c766c61,
+ BMDDeckLinkSupportsDualLinkSDI = 0x73646c73,
+ BMDDeckLinkSupportsIdleOutput = 0x69646f75,
+ BMDDeckLinkMaximumAudioChannels = 0x6d616368,
+ BMDDeckLinkMaximumAnalogAudioChannels = 0x61616368,
+ BMDDeckLinkNumberOfSubDevices = 0x6e736264,
+ BMDDeckLinkSubDeviceIndex = 0x73756269,
+ BMDDeckLinkPersistentID = 0x70656964,
+ BMDDeckLinkTopologicalID = 0x746f6964,
+ BMDDeckLinkVideoOutputConnections = 0x766f636e,
+ BMDDeckLinkVideoInputConnections = 0x7669636e,
+ BMDDeckLinkAudioOutputConnections = 0x616f636e,
+ BMDDeckLinkAudioInputConnections = 0x6169636e,
+ BMDDeckLinkDeviceBusyState = 0x64627374,
+ BMDDeckLinkVideoIOSupport = 0x76696f73,
+ BMDDeckLinkVideoInputGainMinimum = 0x7669676d,
+ BMDDeckLinkVideoInputGainMaximum = 0x76696778,
+ BMDDeckLinkVideoOutputGainMinimum = 0x766f676d,
+ BMDDeckLinkVideoOutputGainMaximum = 0x766f6778,
+ BMDDeckLinkSerialPortDeviceName = 0x736c706e
+ } BMDDeckLinkAttributeID;
+
+typedef /* [v1_enum] */
+enum _BMDDeckLinkAPIInformationID
+ {
+ BMDDeckLinkAPIVersion = 0x76657273
+ } BMDDeckLinkAPIInformationID;
+
+/* [v1_enum] */
+enum _BMDDeviceBusyState
+ {
+ bmdDeviceCaptureBusy = ( 1 << 0 ) ,
+ bmdDevicePlaybackBusy = ( 1 << 1 ) ,
+ bmdDeviceSerialPortBusy = ( 1 << 2 )
+ } ;
+typedef /* [v1_enum] */
+enum _BMDVideoIOSupport
+ {
+ bmdDeviceSupportsCapture = ( 1 << 0 ) ,
+ bmdDeviceSupportsPlayback = ( 1 << 1 )
+ } BMDVideoIOSupport;
+
+typedef /* [v1_enum] */
+enum _BMD3DPreviewFormat
+ {
+ bmd3DPreviewFormatDefault = 0x64656661,
+ bmd3DPreviewFormatLeftOnly = 0x6c656674,
+ bmd3DPreviewFormatRightOnly = 0x72696768,
+ bmd3DPreviewFormatSideBySide = 0x73696465,
+ bmd3DPreviewFormatTopBottom = 0x746f7062
+ } BMD3DPreviewFormat;
+
+typedef /* [v1_enum] */
+enum _BMDNotifications
+ {
+ bmdPreferencesChanged = 0x70726566
+ } BMDNotifications;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+typedef /* [v1_enum] */
+enum _BMDDeckLinkConfigurationID_v10_2
+ {
+ bmdDeckLinkConfig3GBpsVideoOutput_v10_2 = 0x33676273
+ } BMDDeckLinkConfigurationID_v10_2;
+
+typedef /* [v1_enum] */
+enum _BMDAudioConnection_v10_2
+ {
+ bmdAudioConnectionEmbedded_v10_2 = 0x656d6264,
+ bmdAudioConnectionAESEBU_v10_2 = 0x61657320,
+ bmdAudioConnectionAnalog_v10_2 = 0x616e6c67,
+ bmdAudioConnectionAnalogXLR_v10_2 = 0x61786c72,
+ bmdAudioConnectionAnalogRCA_v10_2 = 0x61726361
+ } BMDAudioConnection_v10_2;
+
+
+typedef /* [v1_enum] */
+enum _BMDDeckControlVTRControlState_v8_1
+ {
+ bmdDeckControlNotInVTRControlMode_v8_1 = 0x6e76636d,
+ bmdDeckControlVTRControlPlaying_v8_1 = 0x76747270,
+ bmdDeckControlVTRControlRecording_v8_1 = 0x76747272,
+ bmdDeckControlVTRControlStill_v8_1 = 0x76747261,
+ bmdDeckControlVTRControlSeeking_v8_1 = 0x76747273,
+ bmdDeckControlVTRControlStopped_v8_1 = 0x7674726f
+ } BMDDeckControlVTRControlState_v8_1;
+
+
+
+typedef /* [v1_enum] */
+enum _BMDVideoConnection_v7_6
+ {
+ bmdVideoConnectionSDI_v7_6 = 0x73646920,
+ bmdVideoConnectionHDMI_v7_6 = 0x68646d69,
+ bmdVideoConnectionOpticalSDI_v7_6 = 0x6f707469,
+ bmdVideoConnectionComponent_v7_6 = 0x63706e74,
+ bmdVideoConnectionComposite_v7_6 = 0x636d7374,
+ bmdVideoConnectionSVideo_v7_6 = 0x73766964
+ } BMDVideoConnection_v7_6;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+EXTERN_C const IID LIBID_DeckLinkAPI;
+
+#ifndef __IDeckLinkTimecode_INTERFACE_DEFINED__
+#define __IDeckLinkTimecode_INTERFACE_DEFINED__
+
+/* interface IDeckLinkTimecode */
+/* [helpstring][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkTimecode;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("BC6CFBD3-8317-4325-AC1C-1216391E9340")
+ IDeckLinkTimecode : public IUnknown
+ {
+ public:
+ virtual BMDTimecodeBCD STDMETHODCALLTYPE GetBCD( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetComponents(
+ /* [out] */ unsigned char *hours,
+ /* [out] */ unsigned char *minutes,
+ /* [out] */ unsigned char *seconds,
+ /* [out] */ unsigned char *frames) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetString(
+ /* [out] */ BSTR *timecode) = 0;
+
+ virtual BMDTimecodeFlags STDMETHODCALLTYPE GetFlags( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetTimecodeUserBits(
+ /* [out] */ BMDTimecodeUserBits *userBits) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkTimecodeVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkTimecode * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkTimecode * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkTimecode * This);
+
+ BMDTimecodeBCD ( STDMETHODCALLTYPE *GetBCD )(
+ IDeckLinkTimecode * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetComponents )(
+ IDeckLinkTimecode * This,
+ /* [out] */ unsigned char *hours,
+ /* [out] */ unsigned char *minutes,
+ /* [out] */ unsigned char *seconds,
+ /* [out] */ unsigned char *frames);
+
+ HRESULT ( STDMETHODCALLTYPE *GetString )(
+ IDeckLinkTimecode * This,
+ /* [out] */ BSTR *timecode);
+
+ BMDTimecodeFlags ( STDMETHODCALLTYPE *GetFlags )(
+ IDeckLinkTimecode * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetTimecodeUserBits )(
+ IDeckLinkTimecode * This,
+ /* [out] */ BMDTimecodeUserBits *userBits);
+
+ END_INTERFACE
+ } IDeckLinkTimecodeVtbl;
+
+ interface IDeckLinkTimecode
+ {
+ CONST_VTBL struct IDeckLinkTimecodeVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkTimecode_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkTimecode_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkTimecode_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkTimecode_GetBCD(This) \
+ ( (This)->lpVtbl -> GetBCD(This) )
+
+#define IDeckLinkTimecode_GetComponents(This,hours,minutes,seconds,frames) \
+ ( (This)->lpVtbl -> GetComponents(This,hours,minutes,seconds,frames) )
+
+#define IDeckLinkTimecode_GetString(This,timecode) \
+ ( (This)->lpVtbl -> GetString(This,timecode) )
+
+#define IDeckLinkTimecode_GetFlags(This) \
+ ( (This)->lpVtbl -> GetFlags(This) )
+
+#define IDeckLinkTimecode_GetTimecodeUserBits(This,userBits) \
+ ( (This)->lpVtbl -> GetTimecodeUserBits(This,userBits) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkTimecode_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkDisplayModeIterator_INTERFACE_DEFINED__
+#define __IDeckLinkDisplayModeIterator_INTERFACE_DEFINED__
+
+/* interface IDeckLinkDisplayModeIterator */
+/* [helpstring][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkDisplayModeIterator;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("9C88499F-F601-4021-B80B-032E4EB41C35")
+ IDeckLinkDisplayModeIterator : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Next(
+ /* [out] */ IDeckLinkDisplayMode **deckLinkDisplayMode) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkDisplayModeIteratorVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkDisplayModeIterator * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkDisplayModeIterator * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkDisplayModeIterator * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Next )(
+ IDeckLinkDisplayModeIterator * This,
+ /* [out] */ IDeckLinkDisplayMode **deckLinkDisplayMode);
+
+ END_INTERFACE
+ } IDeckLinkDisplayModeIteratorVtbl;
+
+ interface IDeckLinkDisplayModeIterator
+ {
+ CONST_VTBL struct IDeckLinkDisplayModeIteratorVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkDisplayModeIterator_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkDisplayModeIterator_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkDisplayModeIterator_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkDisplayModeIterator_Next(This,deckLinkDisplayMode) \
+ ( (This)->lpVtbl -> Next(This,deckLinkDisplayMode) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkDisplayModeIterator_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkDisplayMode_INTERFACE_DEFINED__
+#define __IDeckLinkDisplayMode_INTERFACE_DEFINED__
+
+/* interface IDeckLinkDisplayMode */
+/* [helpstring][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkDisplayMode;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("3EB2C1AB-0A3D-4523-A3AD-F40D7FB14E78")
+ IDeckLinkDisplayMode : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE GetName(
+ /* [out] */ BSTR *name) = 0;
+
+ virtual BMDDisplayMode STDMETHODCALLTYPE GetDisplayMode( void) = 0;
+
+ virtual long STDMETHODCALLTYPE GetWidth( void) = 0;
+
+ virtual long STDMETHODCALLTYPE GetHeight( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetFrameRate(
+ /* [out] */ BMDTimeValue *frameDuration,
+ /* [out] */ BMDTimeScale *timeScale) = 0;
+
+ virtual BMDFieldDominance STDMETHODCALLTYPE GetFieldDominance( void) = 0;
+
+ virtual BMDDisplayModeFlags STDMETHODCALLTYPE GetFlags( void) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkDisplayModeVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkDisplayMode * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkDisplayMode * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkDisplayMode * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetName )(
+ IDeckLinkDisplayMode * This,
+ /* [out] */ BSTR *name);
+
+ BMDDisplayMode ( STDMETHODCALLTYPE *GetDisplayMode )(
+ IDeckLinkDisplayMode * This);
+
+ long ( STDMETHODCALLTYPE *GetWidth )(
+ IDeckLinkDisplayMode * This);
+
+ long ( STDMETHODCALLTYPE *GetHeight )(
+ IDeckLinkDisplayMode * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetFrameRate )(
+ IDeckLinkDisplayMode * This,
+ /* [out] */ BMDTimeValue *frameDuration,
+ /* [out] */ BMDTimeScale *timeScale);
+
+ BMDFieldDominance ( STDMETHODCALLTYPE *GetFieldDominance )(
+ IDeckLinkDisplayMode * This);
+
+ BMDDisplayModeFlags ( STDMETHODCALLTYPE *GetFlags )(
+ IDeckLinkDisplayMode * This);
+
+ END_INTERFACE
+ } IDeckLinkDisplayModeVtbl;
+
+ interface IDeckLinkDisplayMode
+ {
+ CONST_VTBL struct IDeckLinkDisplayModeVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkDisplayMode_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkDisplayMode_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkDisplayMode_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkDisplayMode_GetName(This,name) \
+ ( (This)->lpVtbl -> GetName(This,name) )
+
+#define IDeckLinkDisplayMode_GetDisplayMode(This) \
+ ( (This)->lpVtbl -> GetDisplayMode(This) )
+
+#define IDeckLinkDisplayMode_GetWidth(This) \
+ ( (This)->lpVtbl -> GetWidth(This) )
+
+#define IDeckLinkDisplayMode_GetHeight(This) \
+ ( (This)->lpVtbl -> GetHeight(This) )
+
+#define IDeckLinkDisplayMode_GetFrameRate(This,frameDuration,timeScale) \
+ ( (This)->lpVtbl -> GetFrameRate(This,frameDuration,timeScale) )
+
+#define IDeckLinkDisplayMode_GetFieldDominance(This) \
+ ( (This)->lpVtbl -> GetFieldDominance(This) )
+
+#define IDeckLinkDisplayMode_GetFlags(This) \
+ ( (This)->lpVtbl -> GetFlags(This) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkDisplayMode_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLink_INTERFACE_DEFINED__
+#define __IDeckLink_INTERFACE_DEFINED__
+
+/* interface IDeckLink */
+/* [helpstring][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLink;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("C418FBDD-0587-48ED-8FE5-640F0A14AF91")
+ IDeckLink : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE GetModelName(
+ /* [out] */ BSTR *modelName) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetDisplayName(
+ /* [out] */ BSTR *displayName) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLink * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLink * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLink * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetModelName )(
+ IDeckLink * This,
+ /* [out] */ BSTR *modelName);
+
+ HRESULT ( STDMETHODCALLTYPE *GetDisplayName )(
+ IDeckLink * This,
+ /* [out] */ BSTR *displayName);
+
+ END_INTERFACE
+ } IDeckLinkVtbl;
+
+ interface IDeckLink
+ {
+ CONST_VTBL struct IDeckLinkVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLink_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLink_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLink_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLink_GetModelName(This,modelName) \
+ ( (This)->lpVtbl -> GetModelName(This,modelName) )
+
+#define IDeckLink_GetDisplayName(This,displayName) \
+ ( (This)->lpVtbl -> GetDisplayName(This,displayName) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLink_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkConfiguration_INTERFACE_DEFINED__
+#define __IDeckLinkConfiguration_INTERFACE_DEFINED__
+
+/* interface IDeckLinkConfiguration */
+/* [helpstring][local][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkConfiguration;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("1E69FCF6-4203-4936-8076-2A9F4CFD50CB")
+ IDeckLinkConfiguration : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE SetFlag(
+ /* [in] */ BMDDeckLinkConfigurationID cfgID,
+ /* [in] */ BOOL value) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetFlag(
+ /* [in] */ BMDDeckLinkConfigurationID cfgID,
+ /* [out] */ BOOL *value) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetInt(
+ /* [in] */ BMDDeckLinkConfigurationID cfgID,
+ /* [in] */ LONGLONG value) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetInt(
+ /* [in] */ BMDDeckLinkConfigurationID cfgID,
+ /* [out] */ LONGLONG *value) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetFloat(
+ /* [in] */ BMDDeckLinkConfigurationID cfgID,
+ /* [in] */ double value) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetFloat(
+ /* [in] */ BMDDeckLinkConfigurationID cfgID,
+ /* [out] */ double *value) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetString(
+ /* [in] */ BMDDeckLinkConfigurationID cfgID,
+ /* [in] */ BSTR value) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetString(
+ /* [in] */ BMDDeckLinkConfigurationID cfgID,
+ /* [out] */ BSTR *value) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE WriteConfigurationToPreferences( void) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkConfigurationVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkConfiguration * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkConfiguration * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkConfiguration * This);
+
+ HRESULT ( STDMETHODCALLTYPE *SetFlag )(
+ IDeckLinkConfiguration * This,
+ /* [in] */ BMDDeckLinkConfigurationID cfgID,
+ /* [in] */ BOOL value);
+
+ HRESULT ( STDMETHODCALLTYPE *GetFlag )(
+ IDeckLinkConfiguration * This,
+ /* [in] */ BMDDeckLinkConfigurationID cfgID,
+ /* [out] */ BOOL *value);
+
+ HRESULT ( STDMETHODCALLTYPE *SetInt )(
+ IDeckLinkConfiguration * This,
+ /* [in] */ BMDDeckLinkConfigurationID cfgID,
+ /* [in] */ LONGLONG value);
+
+ HRESULT ( STDMETHODCALLTYPE *GetInt )(
+ IDeckLinkConfiguration * This,
+ /* [in] */ BMDDeckLinkConfigurationID cfgID,
+ /* [out] */ LONGLONG *value);
+
+ HRESULT ( STDMETHODCALLTYPE *SetFloat )(
+ IDeckLinkConfiguration * This,
+ /* [in] */ BMDDeckLinkConfigurationID cfgID,
+ /* [in] */ double value);
+
+ HRESULT ( STDMETHODCALLTYPE *GetFloat )(
+ IDeckLinkConfiguration * This,
+ /* [in] */ BMDDeckLinkConfigurationID cfgID,
+ /* [out] */ double *value);
+
+ HRESULT ( STDMETHODCALLTYPE *SetString )(
+ IDeckLinkConfiguration * This,
+ /* [in] */ BMDDeckLinkConfigurationID cfgID,
+ /* [in] */ BSTR value);
+
+ HRESULT ( STDMETHODCALLTYPE *GetString )(
+ IDeckLinkConfiguration * This,
+ /* [in] */ BMDDeckLinkConfigurationID cfgID,
+ /* [out] */ BSTR *value);
+
+ HRESULT ( STDMETHODCALLTYPE *WriteConfigurationToPreferences )(
+ IDeckLinkConfiguration * This);
+
+ END_INTERFACE
+ } IDeckLinkConfigurationVtbl;
+
+ interface IDeckLinkConfiguration
+ {
+ CONST_VTBL struct IDeckLinkConfigurationVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkConfiguration_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkConfiguration_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkConfiguration_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkConfiguration_SetFlag(This,cfgID,value) \
+ ( (This)->lpVtbl -> SetFlag(This,cfgID,value) )
+
+#define IDeckLinkConfiguration_GetFlag(This,cfgID,value) \
+ ( (This)->lpVtbl -> GetFlag(This,cfgID,value) )
+
+#define IDeckLinkConfiguration_SetInt(This,cfgID,value) \
+ ( (This)->lpVtbl -> SetInt(This,cfgID,value) )
+
+#define IDeckLinkConfiguration_GetInt(This,cfgID,value) \
+ ( (This)->lpVtbl -> GetInt(This,cfgID,value) )
+
+#define IDeckLinkConfiguration_SetFloat(This,cfgID,value) \
+ ( (This)->lpVtbl -> SetFloat(This,cfgID,value) )
+
+#define IDeckLinkConfiguration_GetFloat(This,cfgID,value) \
+ ( (This)->lpVtbl -> GetFloat(This,cfgID,value) )
+
+#define IDeckLinkConfiguration_SetString(This,cfgID,value) \
+ ( (This)->lpVtbl -> SetString(This,cfgID,value) )
+
+#define IDeckLinkConfiguration_GetString(This,cfgID,value) \
+ ( (This)->lpVtbl -> GetString(This,cfgID,value) )
+
+#define IDeckLinkConfiguration_WriteConfigurationToPreferences(This) \
+ ( (This)->lpVtbl -> WriteConfigurationToPreferences(This) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkConfiguration_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkDeckControlStatusCallback_INTERFACE_DEFINED__
+#define __IDeckLinkDeckControlStatusCallback_INTERFACE_DEFINED__
+
+/* interface IDeckLinkDeckControlStatusCallback */
+/* [helpstring][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkDeckControlStatusCallback;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("53436FFB-B434-4906-BADC-AE3060FFE8EF")
+ IDeckLinkDeckControlStatusCallback : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE TimecodeUpdate(
+ /* [in] */ BMDTimecodeBCD currentTimecode) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE VTRControlStateChanged(
+ /* [in] */ BMDDeckControlVTRControlState newState,
+ /* [in] */ BMDDeckControlError error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE DeckControlEventReceived(
+ /* [in] */ BMDDeckControlEvent event,
+ /* [in] */ BMDDeckControlError error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE DeckControlStatusChanged(
+ /* [in] */ BMDDeckControlStatusFlags flags,
+ /* [in] */ unsigned int mask) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkDeckControlStatusCallbackVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkDeckControlStatusCallback * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkDeckControlStatusCallback * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkDeckControlStatusCallback * This);
+
+ HRESULT ( STDMETHODCALLTYPE *TimecodeUpdate )(
+ IDeckLinkDeckControlStatusCallback * This,
+ /* [in] */ BMDTimecodeBCD currentTimecode);
+
+ HRESULT ( STDMETHODCALLTYPE *VTRControlStateChanged )(
+ IDeckLinkDeckControlStatusCallback * This,
+ /* [in] */ BMDDeckControlVTRControlState newState,
+ /* [in] */ BMDDeckControlError error);
+
+ HRESULT ( STDMETHODCALLTYPE *DeckControlEventReceived )(
+ IDeckLinkDeckControlStatusCallback * This,
+ /* [in] */ BMDDeckControlEvent event,
+ /* [in] */ BMDDeckControlError error);
+
+ HRESULT ( STDMETHODCALLTYPE *DeckControlStatusChanged )(
+ IDeckLinkDeckControlStatusCallback * This,
+ /* [in] */ BMDDeckControlStatusFlags flags,
+ /* [in] */ unsigned int mask);
+
+ END_INTERFACE
+ } IDeckLinkDeckControlStatusCallbackVtbl;
+
+ interface IDeckLinkDeckControlStatusCallback
+ {
+ CONST_VTBL struct IDeckLinkDeckControlStatusCallbackVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkDeckControlStatusCallback_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkDeckControlStatusCallback_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkDeckControlStatusCallback_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkDeckControlStatusCallback_TimecodeUpdate(This,currentTimecode) \
+ ( (This)->lpVtbl -> TimecodeUpdate(This,currentTimecode) )
+
+#define IDeckLinkDeckControlStatusCallback_VTRControlStateChanged(This,newState,error) \
+ ( (This)->lpVtbl -> VTRControlStateChanged(This,newState,error) )
+
+#define IDeckLinkDeckControlStatusCallback_DeckControlEventReceived(This,event,error) \
+ ( (This)->lpVtbl -> DeckControlEventReceived(This,event,error) )
+
+#define IDeckLinkDeckControlStatusCallback_DeckControlStatusChanged(This,flags,mask) \
+ ( (This)->lpVtbl -> DeckControlStatusChanged(This,flags,mask) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkDeckControlStatusCallback_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkDeckControl_INTERFACE_DEFINED__
+#define __IDeckLinkDeckControl_INTERFACE_DEFINED__
+
+/* interface IDeckLinkDeckControl */
+/* [helpstring][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkDeckControl;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("8E1C3ACE-19C7-4E00-8B92-D80431D958BE")
+ IDeckLinkDeckControl : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Open(
+ /* [in] */ BMDTimeScale timeScale,
+ /* [in] */ BMDTimeValue timeValue,
+ /* [in] */ BOOL timecodeIsDropFrame,
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Close(
+ /* [in] */ BOOL standbyOn) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetCurrentState(
+ /* [out] */ BMDDeckControlMode *mode,
+ /* [out] */ BMDDeckControlVTRControlState *vtrControlState,
+ /* [out] */ BMDDeckControlStatusFlags *flags) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetStandby(
+ /* [in] */ BOOL standbyOn) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SendCommand(
+ /* [in] */ unsigned char *inBuffer,
+ /* [in] */ unsigned int inBufferSize,
+ /* [out] */ unsigned char *outBuffer,
+ /* [out] */ unsigned int *outDataSize,
+ /* [in] */ unsigned int outBufferSize,
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Play(
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Stop(
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE TogglePlayStop(
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Eject(
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GoToTimecode(
+ /* [in] */ BMDTimecodeBCD timecode,
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE FastForward(
+ /* [in] */ BOOL viewTape,
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Rewind(
+ /* [in] */ BOOL viewTape,
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE StepForward(
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE StepBack(
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Jog(
+ /* [in] */ double rate,
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Shuttle(
+ /* [in] */ double rate,
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetTimecodeString(
+ /* [out] */ BSTR *currentTimeCode,
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetTimecode(
+ /* [out] */ IDeckLinkTimecode **currentTimecode,
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetTimecodeBCD(
+ /* [out] */ BMDTimecodeBCD *currentTimecode,
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetPreroll(
+ /* [in] */ unsigned int prerollSeconds) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetPreroll(
+ /* [out] */ unsigned int *prerollSeconds) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetExportOffset(
+ /* [in] */ int exportOffsetFields) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetExportOffset(
+ /* [out] */ int *exportOffsetFields) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetManualExportOffset(
+ /* [out] */ int *deckManualExportOffsetFields) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetCaptureOffset(
+ /* [in] */ int captureOffsetFields) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetCaptureOffset(
+ /* [out] */ int *captureOffsetFields) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE StartExport(
+ /* [in] */ BMDTimecodeBCD inTimecode,
+ /* [in] */ BMDTimecodeBCD outTimecode,
+ /* [in] */ BMDDeckControlExportModeOpsFlags exportModeOps,
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE StartCapture(
+ /* [in] */ BOOL useVITC,
+ /* [in] */ BMDTimecodeBCD inTimecode,
+ /* [in] */ BMDTimecodeBCD outTimecode,
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetDeviceID(
+ /* [out] */ unsigned short *deviceId,
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Abort( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE CrashRecordStart(
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE CrashRecordStop(
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetCallback(
+ /* [in] */ IDeckLinkDeckControlStatusCallback *callback) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkDeckControlVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkDeckControl * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkDeckControl * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkDeckControl * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Open )(
+ IDeckLinkDeckControl * This,
+ /* [in] */ BMDTimeScale timeScale,
+ /* [in] */ BMDTimeValue timeValue,
+ /* [in] */ BOOL timecodeIsDropFrame,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *Close )(
+ IDeckLinkDeckControl * This,
+ /* [in] */ BOOL standbyOn);
+
+ HRESULT ( STDMETHODCALLTYPE *GetCurrentState )(
+ IDeckLinkDeckControl * This,
+ /* [out] */ BMDDeckControlMode *mode,
+ /* [out] */ BMDDeckControlVTRControlState *vtrControlState,
+ /* [out] */ BMDDeckControlStatusFlags *flags);
+
+ HRESULT ( STDMETHODCALLTYPE *SetStandby )(
+ IDeckLinkDeckControl * This,
+ /* [in] */ BOOL standbyOn);
+
+ HRESULT ( STDMETHODCALLTYPE *SendCommand )(
+ IDeckLinkDeckControl * This,
+ /* [in] */ unsigned char *inBuffer,
+ /* [in] */ unsigned int inBufferSize,
+ /* [out] */ unsigned char *outBuffer,
+ /* [out] */ unsigned int *outDataSize,
+ /* [in] */ unsigned int outBufferSize,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *Play )(
+ IDeckLinkDeckControl * This,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *Stop )(
+ IDeckLinkDeckControl * This,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *TogglePlayStop )(
+ IDeckLinkDeckControl * This,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *Eject )(
+ IDeckLinkDeckControl * This,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *GoToTimecode )(
+ IDeckLinkDeckControl * This,
+ /* [in] */ BMDTimecodeBCD timecode,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *FastForward )(
+ IDeckLinkDeckControl * This,
+ /* [in] */ BOOL viewTape,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *Rewind )(
+ IDeckLinkDeckControl * This,
+ /* [in] */ BOOL viewTape,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *StepForward )(
+ IDeckLinkDeckControl * This,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *StepBack )(
+ IDeckLinkDeckControl * This,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *Jog )(
+ IDeckLinkDeckControl * This,
+ /* [in] */ double rate,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *Shuttle )(
+ IDeckLinkDeckControl * This,
+ /* [in] */ double rate,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *GetTimecodeString )(
+ IDeckLinkDeckControl * This,
+ /* [out] */ BSTR *currentTimeCode,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *GetTimecode )(
+ IDeckLinkDeckControl * This,
+ /* [out] */ IDeckLinkTimecode **currentTimecode,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *GetTimecodeBCD )(
+ IDeckLinkDeckControl * This,
+ /* [out] */ BMDTimecodeBCD *currentTimecode,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *SetPreroll )(
+ IDeckLinkDeckControl * This,
+ /* [in] */ unsigned int prerollSeconds);
+
+ HRESULT ( STDMETHODCALLTYPE *GetPreroll )(
+ IDeckLinkDeckControl * This,
+ /* [out] */ unsigned int *prerollSeconds);
+
+ HRESULT ( STDMETHODCALLTYPE *SetExportOffset )(
+ IDeckLinkDeckControl * This,
+ /* [in] */ int exportOffsetFields);
+
+ HRESULT ( STDMETHODCALLTYPE *GetExportOffset )(
+ IDeckLinkDeckControl * This,
+ /* [out] */ int *exportOffsetFields);
+
+ HRESULT ( STDMETHODCALLTYPE *GetManualExportOffset )(
+ IDeckLinkDeckControl * This,
+ /* [out] */ int *deckManualExportOffsetFields);
+
+ HRESULT ( STDMETHODCALLTYPE *SetCaptureOffset )(
+ IDeckLinkDeckControl * This,
+ /* [in] */ int captureOffsetFields);
+
+ HRESULT ( STDMETHODCALLTYPE *GetCaptureOffset )(
+ IDeckLinkDeckControl * This,
+ /* [out] */ int *captureOffsetFields);
+
+ HRESULT ( STDMETHODCALLTYPE *StartExport )(
+ IDeckLinkDeckControl * This,
+ /* [in] */ BMDTimecodeBCD inTimecode,
+ /* [in] */ BMDTimecodeBCD outTimecode,
+ /* [in] */ BMDDeckControlExportModeOpsFlags exportModeOps,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *StartCapture )(
+ IDeckLinkDeckControl * This,
+ /* [in] */ BOOL useVITC,
+ /* [in] */ BMDTimecodeBCD inTimecode,
+ /* [in] */ BMDTimecodeBCD outTimecode,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *GetDeviceID )(
+ IDeckLinkDeckControl * This,
+ /* [out] */ unsigned short *deviceId,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *Abort )(
+ IDeckLinkDeckControl * This);
+
+ HRESULT ( STDMETHODCALLTYPE *CrashRecordStart )(
+ IDeckLinkDeckControl * This,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *CrashRecordStop )(
+ IDeckLinkDeckControl * This,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *SetCallback )(
+ IDeckLinkDeckControl * This,
+ /* [in] */ IDeckLinkDeckControlStatusCallback *callback);
+
+ END_INTERFACE
+ } IDeckLinkDeckControlVtbl;
+
+ interface IDeckLinkDeckControl
+ {
+ CONST_VTBL struct IDeckLinkDeckControlVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkDeckControl_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkDeckControl_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkDeckControl_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkDeckControl_Open(This,timeScale,timeValue,timecodeIsDropFrame,error) \
+ ( (This)->lpVtbl -> Open(This,timeScale,timeValue,timecodeIsDropFrame,error) )
+
+#define IDeckLinkDeckControl_Close(This,standbyOn) \
+ ( (This)->lpVtbl -> Close(This,standbyOn) )
+
+#define IDeckLinkDeckControl_GetCurrentState(This,mode,vtrControlState,flags) \
+ ( (This)->lpVtbl -> GetCurrentState(This,mode,vtrControlState,flags) )
+
+#define IDeckLinkDeckControl_SetStandby(This,standbyOn) \
+ ( (This)->lpVtbl -> SetStandby(This,standbyOn) )
+
+#define IDeckLinkDeckControl_SendCommand(This,inBuffer,inBufferSize,outBuffer,outDataSize,outBufferSize,error) \
+ ( (This)->lpVtbl -> SendCommand(This,inBuffer,inBufferSize,outBuffer,outDataSize,outBufferSize,error) )
+
+#define IDeckLinkDeckControl_Play(This,error) \
+ ( (This)->lpVtbl -> Play(This,error) )
+
+#define IDeckLinkDeckControl_Stop(This,error) \
+ ( (This)->lpVtbl -> Stop(This,error) )
+
+#define IDeckLinkDeckControl_TogglePlayStop(This,error) \
+ ( (This)->lpVtbl -> TogglePlayStop(This,error) )
+
+#define IDeckLinkDeckControl_Eject(This,error) \
+ ( (This)->lpVtbl -> Eject(This,error) )
+
+#define IDeckLinkDeckControl_GoToTimecode(This,timecode,error) \
+ ( (This)->lpVtbl -> GoToTimecode(This,timecode,error) )
+
+#define IDeckLinkDeckControl_FastForward(This,viewTape,error) \
+ ( (This)->lpVtbl -> FastForward(This,viewTape,error) )
+
+#define IDeckLinkDeckControl_Rewind(This,viewTape,error) \
+ ( (This)->lpVtbl -> Rewind(This,viewTape,error) )
+
+#define IDeckLinkDeckControl_StepForward(This,error) \
+ ( (This)->lpVtbl -> StepForward(This,error) )
+
+#define IDeckLinkDeckControl_StepBack(This,error) \
+ ( (This)->lpVtbl -> StepBack(This,error) )
+
+#define IDeckLinkDeckControl_Jog(This,rate,error) \
+ ( (This)->lpVtbl -> Jog(This,rate,error) )
+
+#define IDeckLinkDeckControl_Shuttle(This,rate,error) \
+ ( (This)->lpVtbl -> Shuttle(This,rate,error) )
+
+#define IDeckLinkDeckControl_GetTimecodeString(This,currentTimeCode,error) \
+ ( (This)->lpVtbl -> GetTimecodeString(This,currentTimeCode,error) )
+
+#define IDeckLinkDeckControl_GetTimecode(This,currentTimecode,error) \
+ ( (This)->lpVtbl -> GetTimecode(This,currentTimecode,error) )
+
+#define IDeckLinkDeckControl_GetTimecodeBCD(This,currentTimecode,error) \
+ ( (This)->lpVtbl -> GetTimecodeBCD(This,currentTimecode,error) )
+
+#define IDeckLinkDeckControl_SetPreroll(This,prerollSeconds) \
+ ( (This)->lpVtbl -> SetPreroll(This,prerollSeconds) )
+
+#define IDeckLinkDeckControl_GetPreroll(This,prerollSeconds) \
+ ( (This)->lpVtbl -> GetPreroll(This,prerollSeconds) )
+
+#define IDeckLinkDeckControl_SetExportOffset(This,exportOffsetFields) \
+ ( (This)->lpVtbl -> SetExportOffset(This,exportOffsetFields) )
+
+#define IDeckLinkDeckControl_GetExportOffset(This,exportOffsetFields) \
+ ( (This)->lpVtbl -> GetExportOffset(This,exportOffsetFields) )
+
+#define IDeckLinkDeckControl_GetManualExportOffset(This,deckManualExportOffsetFields) \
+ ( (This)->lpVtbl -> GetManualExportOffset(This,deckManualExportOffsetFields) )
+
+#define IDeckLinkDeckControl_SetCaptureOffset(This,captureOffsetFields) \
+ ( (This)->lpVtbl -> SetCaptureOffset(This,captureOffsetFields) )
+
+#define IDeckLinkDeckControl_GetCaptureOffset(This,captureOffsetFields) \
+ ( (This)->lpVtbl -> GetCaptureOffset(This,captureOffsetFields) )
+
+#define IDeckLinkDeckControl_StartExport(This,inTimecode,outTimecode,exportModeOps,error) \
+ ( (This)->lpVtbl -> StartExport(This,inTimecode,outTimecode,exportModeOps,error) )
+
+#define IDeckLinkDeckControl_StartCapture(This,useVITC,inTimecode,outTimecode,error) \
+ ( (This)->lpVtbl -> StartCapture(This,useVITC,inTimecode,outTimecode,error) )
+
+#define IDeckLinkDeckControl_GetDeviceID(This,deviceId,error) \
+ ( (This)->lpVtbl -> GetDeviceID(This,deviceId,error) )
+
+#define IDeckLinkDeckControl_Abort(This) \
+ ( (This)->lpVtbl -> Abort(This) )
+
+#define IDeckLinkDeckControl_CrashRecordStart(This,error) \
+ ( (This)->lpVtbl -> CrashRecordStart(This,error) )
+
+#define IDeckLinkDeckControl_CrashRecordStop(This,error) \
+ ( (This)->lpVtbl -> CrashRecordStop(This,error) )
+
+#define IDeckLinkDeckControl_SetCallback(This,callback) \
+ ( (This)->lpVtbl -> SetCallback(This,callback) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkDeckControl_INTERFACE_DEFINED__ */
+
+
+#ifndef __IBMDStreamingDeviceNotificationCallback_INTERFACE_DEFINED__
+#define __IBMDStreamingDeviceNotificationCallback_INTERFACE_DEFINED__
+
+/* interface IBMDStreamingDeviceNotificationCallback */
+/* [helpstring][uuid][object] */
+
+
+EXTERN_C const IID IID_IBMDStreamingDeviceNotificationCallback;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("F9531D64-3305-4B29-A387-7F74BB0D0E84")
+ IBMDStreamingDeviceNotificationCallback : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE StreamingDeviceArrived(
+ /* [in] */ IDeckLink *device) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE StreamingDeviceRemoved(
+ /* [in] */ IDeckLink *device) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE StreamingDeviceModeChanged(
+ /* [in] */ IDeckLink *device,
+ /* [in] */ BMDStreamingDeviceMode mode) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IBMDStreamingDeviceNotificationCallbackVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IBMDStreamingDeviceNotificationCallback * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IBMDStreamingDeviceNotificationCallback * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IBMDStreamingDeviceNotificationCallback * This);
+
+ HRESULT ( STDMETHODCALLTYPE *StreamingDeviceArrived )(
+ IBMDStreamingDeviceNotificationCallback * This,
+ /* [in] */ IDeckLink *device);
+
+ HRESULT ( STDMETHODCALLTYPE *StreamingDeviceRemoved )(
+ IBMDStreamingDeviceNotificationCallback * This,
+ /* [in] */ IDeckLink *device);
+
+ HRESULT ( STDMETHODCALLTYPE *StreamingDeviceModeChanged )(
+ IBMDStreamingDeviceNotificationCallback * This,
+ /* [in] */ IDeckLink *device,
+ /* [in] */ BMDStreamingDeviceMode mode);
+
+ END_INTERFACE
+ } IBMDStreamingDeviceNotificationCallbackVtbl;
+
+ interface IBMDStreamingDeviceNotificationCallback
+ {
+ CONST_VTBL struct IBMDStreamingDeviceNotificationCallbackVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IBMDStreamingDeviceNotificationCallback_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IBMDStreamingDeviceNotificationCallback_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IBMDStreamingDeviceNotificationCallback_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IBMDStreamingDeviceNotificationCallback_StreamingDeviceArrived(This,device) \
+ ( (This)->lpVtbl -> StreamingDeviceArrived(This,device) )
+
+#define IBMDStreamingDeviceNotificationCallback_StreamingDeviceRemoved(This,device) \
+ ( (This)->lpVtbl -> StreamingDeviceRemoved(This,device) )
+
+#define IBMDStreamingDeviceNotificationCallback_StreamingDeviceModeChanged(This,device,mode) \
+ ( (This)->lpVtbl -> StreamingDeviceModeChanged(This,device,mode) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IBMDStreamingDeviceNotificationCallback_INTERFACE_DEFINED__ */
+
+
+#ifndef __IBMDStreamingH264InputCallback_INTERFACE_DEFINED__
+#define __IBMDStreamingH264InputCallback_INTERFACE_DEFINED__
+
+/* interface IBMDStreamingH264InputCallback */
+/* [helpstring][uuid][object] */
+
+
+EXTERN_C const IID IID_IBMDStreamingH264InputCallback;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("823C475F-55AE-46F9-890C-537CC5CEDCCA")
+ IBMDStreamingH264InputCallback : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE H264NALPacketArrived(
+ /* [in] */ IBMDStreamingH264NALPacket *nalPacket) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE H264AudioPacketArrived(
+ /* [in] */ IBMDStreamingAudioPacket *audioPacket) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE MPEG2TSPacketArrived(
+ /* [in] */ IBMDStreamingMPEG2TSPacket *tsPacket) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE H264VideoInputConnectorScanningChanged( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE H264VideoInputConnectorChanged( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE H264VideoInputModeChanged( void) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IBMDStreamingH264InputCallbackVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IBMDStreamingH264InputCallback * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IBMDStreamingH264InputCallback * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IBMDStreamingH264InputCallback * This);
+
+ HRESULT ( STDMETHODCALLTYPE *H264NALPacketArrived )(
+ IBMDStreamingH264InputCallback * This,
+ /* [in] */ IBMDStreamingH264NALPacket *nalPacket);
+
+ HRESULT ( STDMETHODCALLTYPE *H264AudioPacketArrived )(
+ IBMDStreamingH264InputCallback * This,
+ /* [in] */ IBMDStreamingAudioPacket *audioPacket);
+
+ HRESULT ( STDMETHODCALLTYPE *MPEG2TSPacketArrived )(
+ IBMDStreamingH264InputCallback * This,
+ /* [in] */ IBMDStreamingMPEG2TSPacket *tsPacket);
+
+ HRESULT ( STDMETHODCALLTYPE *H264VideoInputConnectorScanningChanged )(
+ IBMDStreamingH264InputCallback * This);
+
+ HRESULT ( STDMETHODCALLTYPE *H264VideoInputConnectorChanged )(
+ IBMDStreamingH264InputCallback * This);
+
+ HRESULT ( STDMETHODCALLTYPE *H264VideoInputModeChanged )(
+ IBMDStreamingH264InputCallback * This);
+
+ END_INTERFACE
+ } IBMDStreamingH264InputCallbackVtbl;
+
+ interface IBMDStreamingH264InputCallback
+ {
+ CONST_VTBL struct IBMDStreamingH264InputCallbackVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IBMDStreamingH264InputCallback_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IBMDStreamingH264InputCallback_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IBMDStreamingH264InputCallback_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IBMDStreamingH264InputCallback_H264NALPacketArrived(This,nalPacket) \
+ ( (This)->lpVtbl -> H264NALPacketArrived(This,nalPacket) )
+
+#define IBMDStreamingH264InputCallback_H264AudioPacketArrived(This,audioPacket) \
+ ( (This)->lpVtbl -> H264AudioPacketArrived(This,audioPacket) )
+
+#define IBMDStreamingH264InputCallback_MPEG2TSPacketArrived(This,tsPacket) \
+ ( (This)->lpVtbl -> MPEG2TSPacketArrived(This,tsPacket) )
+
+#define IBMDStreamingH264InputCallback_H264VideoInputConnectorScanningChanged(This) \
+ ( (This)->lpVtbl -> H264VideoInputConnectorScanningChanged(This) )
+
+#define IBMDStreamingH264InputCallback_H264VideoInputConnectorChanged(This) \
+ ( (This)->lpVtbl -> H264VideoInputConnectorChanged(This) )
+
+#define IBMDStreamingH264InputCallback_H264VideoInputModeChanged(This) \
+ ( (This)->lpVtbl -> H264VideoInputModeChanged(This) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IBMDStreamingH264InputCallback_INTERFACE_DEFINED__ */
+
+
+#ifndef __IBMDStreamingDiscovery_INTERFACE_DEFINED__
+#define __IBMDStreamingDiscovery_INTERFACE_DEFINED__
+
+/* interface IBMDStreamingDiscovery */
+/* [helpstring][uuid][object] */
+
+
+EXTERN_C const IID IID_IBMDStreamingDiscovery;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("2C837444-F989-4D87-901A-47C8A36D096D")
+ IBMDStreamingDiscovery : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE InstallDeviceNotifications(
+ /* [in] */ IBMDStreamingDeviceNotificationCallback *theCallback) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE UninstallDeviceNotifications( void) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IBMDStreamingDiscoveryVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IBMDStreamingDiscovery * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IBMDStreamingDiscovery * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IBMDStreamingDiscovery * This);
+
+ HRESULT ( STDMETHODCALLTYPE *InstallDeviceNotifications )(
+ IBMDStreamingDiscovery * This,
+ /* [in] */ IBMDStreamingDeviceNotificationCallback *theCallback);
+
+ HRESULT ( STDMETHODCALLTYPE *UninstallDeviceNotifications )(
+ IBMDStreamingDiscovery * This);
+
+ END_INTERFACE
+ } IBMDStreamingDiscoveryVtbl;
+
+ interface IBMDStreamingDiscovery
+ {
+ CONST_VTBL struct IBMDStreamingDiscoveryVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IBMDStreamingDiscovery_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IBMDStreamingDiscovery_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IBMDStreamingDiscovery_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IBMDStreamingDiscovery_InstallDeviceNotifications(This,theCallback) \
+ ( (This)->lpVtbl -> InstallDeviceNotifications(This,theCallback) )
+
+#define IBMDStreamingDiscovery_UninstallDeviceNotifications(This) \
+ ( (This)->lpVtbl -> UninstallDeviceNotifications(This) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IBMDStreamingDiscovery_INTERFACE_DEFINED__ */
+
+
+#ifndef __IBMDStreamingVideoEncodingMode_INTERFACE_DEFINED__
+#define __IBMDStreamingVideoEncodingMode_INTERFACE_DEFINED__
+
+/* interface IBMDStreamingVideoEncodingMode */
+/* [helpstring][uuid][object] */
+
+
+EXTERN_C const IID IID_IBMDStreamingVideoEncodingMode;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("1AB8035B-CD13-458D-B6DF-5E8F7C2141D9")
+ IBMDStreamingVideoEncodingMode : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE GetName(
+ /* [out] */ BSTR *name) = 0;
+
+ virtual unsigned int STDMETHODCALLTYPE GetPresetID( void) = 0;
+
+ virtual unsigned int STDMETHODCALLTYPE GetSourcePositionX( void) = 0;
+
+ virtual unsigned int STDMETHODCALLTYPE GetSourcePositionY( void) = 0;
+
+ virtual unsigned int STDMETHODCALLTYPE GetSourceWidth( void) = 0;
+
+ virtual unsigned int STDMETHODCALLTYPE GetSourceHeight( void) = 0;
+
+ virtual unsigned int STDMETHODCALLTYPE GetDestWidth( void) = 0;
+
+ virtual unsigned int STDMETHODCALLTYPE GetDestHeight( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetFlag(
+ /* [in] */ BMDStreamingEncodingModePropertyID cfgID,
+ /* [out] */ BOOL *value) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetInt(
+ /* [in] */ BMDStreamingEncodingModePropertyID cfgID,
+ /* [out] */ LONGLONG *value) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetFloat(
+ /* [in] */ BMDStreamingEncodingModePropertyID cfgID,
+ /* [out] */ double *value) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetString(
+ /* [in] */ BMDStreamingEncodingModePropertyID cfgID,
+ /* [out] */ BSTR *value) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE CreateMutableVideoEncodingMode(
+ /* [out] */ IBMDStreamingMutableVideoEncodingMode **newEncodingMode) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IBMDStreamingVideoEncodingModeVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IBMDStreamingVideoEncodingMode * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IBMDStreamingVideoEncodingMode * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IBMDStreamingVideoEncodingMode * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetName )(
+ IBMDStreamingVideoEncodingMode * This,
+ /* [out] */ BSTR *name);
+
+ unsigned int ( STDMETHODCALLTYPE *GetPresetID )(
+ IBMDStreamingVideoEncodingMode * This);
+
+ unsigned int ( STDMETHODCALLTYPE *GetSourcePositionX )(
+ IBMDStreamingVideoEncodingMode * This);
+
+ unsigned int ( STDMETHODCALLTYPE *GetSourcePositionY )(
+ IBMDStreamingVideoEncodingMode * This);
+
+ unsigned int ( STDMETHODCALLTYPE *GetSourceWidth )(
+ IBMDStreamingVideoEncodingMode * This);
+
+ unsigned int ( STDMETHODCALLTYPE *GetSourceHeight )(
+ IBMDStreamingVideoEncodingMode * This);
+
+ unsigned int ( STDMETHODCALLTYPE *GetDestWidth )(
+ IBMDStreamingVideoEncodingMode * This);
+
+ unsigned int ( STDMETHODCALLTYPE *GetDestHeight )(
+ IBMDStreamingVideoEncodingMode * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetFlag )(
+ IBMDStreamingVideoEncodingMode * This,
+ /* [in] */ BMDStreamingEncodingModePropertyID cfgID,
+ /* [out] */ BOOL *value);
+
+ HRESULT ( STDMETHODCALLTYPE *GetInt )(
+ IBMDStreamingVideoEncodingMode * This,
+ /* [in] */ BMDStreamingEncodingModePropertyID cfgID,
+ /* [out] */ LONGLONG *value);
+
+ HRESULT ( STDMETHODCALLTYPE *GetFloat )(
+ IBMDStreamingVideoEncodingMode * This,
+ /* [in] */ BMDStreamingEncodingModePropertyID cfgID,
+ /* [out] */ double *value);
+
+ HRESULT ( STDMETHODCALLTYPE *GetString )(
+ IBMDStreamingVideoEncodingMode * This,
+ /* [in] */ BMDStreamingEncodingModePropertyID cfgID,
+ /* [out] */ BSTR *value);
+
+ HRESULT ( STDMETHODCALLTYPE *CreateMutableVideoEncodingMode )(
+ IBMDStreamingVideoEncodingMode * This,
+ /* [out] */ IBMDStreamingMutableVideoEncodingMode **newEncodingMode);
+
+ END_INTERFACE
+ } IBMDStreamingVideoEncodingModeVtbl;
+
+ interface IBMDStreamingVideoEncodingMode
+ {
+ CONST_VTBL struct IBMDStreamingVideoEncodingModeVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IBMDStreamingVideoEncodingMode_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IBMDStreamingVideoEncodingMode_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IBMDStreamingVideoEncodingMode_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IBMDStreamingVideoEncodingMode_GetName(This,name) \
+ ( (This)->lpVtbl -> GetName(This,name) )
+
+#define IBMDStreamingVideoEncodingMode_GetPresetID(This) \
+ ( (This)->lpVtbl -> GetPresetID(This) )
+
+#define IBMDStreamingVideoEncodingMode_GetSourcePositionX(This) \
+ ( (This)->lpVtbl -> GetSourcePositionX(This) )
+
+#define IBMDStreamingVideoEncodingMode_GetSourcePositionY(This) \
+ ( (This)->lpVtbl -> GetSourcePositionY(This) )
+
+#define IBMDStreamingVideoEncodingMode_GetSourceWidth(This) \
+ ( (This)->lpVtbl -> GetSourceWidth(This) )
+
+#define IBMDStreamingVideoEncodingMode_GetSourceHeight(This) \
+ ( (This)->lpVtbl -> GetSourceHeight(This) )
+
+#define IBMDStreamingVideoEncodingMode_GetDestWidth(This) \
+ ( (This)->lpVtbl -> GetDestWidth(This) )
+
+#define IBMDStreamingVideoEncodingMode_GetDestHeight(This) \
+ ( (This)->lpVtbl -> GetDestHeight(This) )
+
+#define IBMDStreamingVideoEncodingMode_GetFlag(This,cfgID,value) \
+ ( (This)->lpVtbl -> GetFlag(This,cfgID,value) )
+
+#define IBMDStreamingVideoEncodingMode_GetInt(This,cfgID,value) \
+ ( (This)->lpVtbl -> GetInt(This,cfgID,value) )
+
+#define IBMDStreamingVideoEncodingMode_GetFloat(This,cfgID,value) \
+ ( (This)->lpVtbl -> GetFloat(This,cfgID,value) )
+
+#define IBMDStreamingVideoEncodingMode_GetString(This,cfgID,value) \
+ ( (This)->lpVtbl -> GetString(This,cfgID,value) )
+
+#define IBMDStreamingVideoEncodingMode_CreateMutableVideoEncodingMode(This,newEncodingMode) \
+ ( (This)->lpVtbl -> CreateMutableVideoEncodingMode(This,newEncodingMode) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IBMDStreamingVideoEncodingMode_INTERFACE_DEFINED__ */
+
+
+#ifndef __IBMDStreamingMutableVideoEncodingMode_INTERFACE_DEFINED__
+#define __IBMDStreamingMutableVideoEncodingMode_INTERFACE_DEFINED__
+
+/* interface IBMDStreamingMutableVideoEncodingMode */
+/* [helpstring][uuid][object] */
+
+
+EXTERN_C const IID IID_IBMDStreamingMutableVideoEncodingMode;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("19BF7D90-1E0A-400D-B2C6-FFC4E78AD49D")
+ IBMDStreamingMutableVideoEncodingMode : public IBMDStreamingVideoEncodingMode
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE SetSourceRect(
+ /* [in] */ unsigned int posX,
+ /* [in] */ unsigned int posY,
+ /* [in] */ unsigned int width,
+ /* [in] */ unsigned int height) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetDestSize(
+ /* [in] */ unsigned int width,
+ /* [in] */ unsigned int height) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetFlag(
+ /* [in] */ BMDStreamingEncodingModePropertyID cfgID,
+ /* [in] */ BOOL value) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetInt(
+ /* [in] */ BMDStreamingEncodingModePropertyID cfgID,
+ /* [in] */ LONGLONG value) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetFloat(
+ /* [in] */ BMDStreamingEncodingModePropertyID cfgID,
+ /* [in] */ double value) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetString(
+ /* [in] */ BMDStreamingEncodingModePropertyID cfgID,
+ /* [in] */ BSTR value) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IBMDStreamingMutableVideoEncodingModeVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IBMDStreamingMutableVideoEncodingMode * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IBMDStreamingMutableVideoEncodingMode * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IBMDStreamingMutableVideoEncodingMode * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetName )(
+ IBMDStreamingMutableVideoEncodingMode * This,
+ /* [out] */ BSTR *name);
+
+ unsigned int ( STDMETHODCALLTYPE *GetPresetID )(
+ IBMDStreamingMutableVideoEncodingMode * This);
+
+ unsigned int ( STDMETHODCALLTYPE *GetSourcePositionX )(
+ IBMDStreamingMutableVideoEncodingMode * This);
+
+ unsigned int ( STDMETHODCALLTYPE *GetSourcePositionY )(
+ IBMDStreamingMutableVideoEncodingMode * This);
+
+ unsigned int ( STDMETHODCALLTYPE *GetSourceWidth )(
+ IBMDStreamingMutableVideoEncodingMode * This);
+
+ unsigned int ( STDMETHODCALLTYPE *GetSourceHeight )(
+ IBMDStreamingMutableVideoEncodingMode * This);
+
+ unsigned int ( STDMETHODCALLTYPE *GetDestWidth )(
+ IBMDStreamingMutableVideoEncodingMode * This);
+
+ unsigned int ( STDMETHODCALLTYPE *GetDestHeight )(
+ IBMDStreamingMutableVideoEncodingMode * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetFlag )(
+ IBMDStreamingMutableVideoEncodingMode * This,
+ /* [in] */ BMDStreamingEncodingModePropertyID cfgID,
+ /* [out] */ BOOL *value);
+
+ HRESULT ( STDMETHODCALLTYPE *GetInt )(
+ IBMDStreamingMutableVideoEncodingMode * This,
+ /* [in] */ BMDStreamingEncodingModePropertyID cfgID,
+ /* [out] */ LONGLONG *value);
+
+ HRESULT ( STDMETHODCALLTYPE *GetFloat )(
+ IBMDStreamingMutableVideoEncodingMode * This,
+ /* [in] */ BMDStreamingEncodingModePropertyID cfgID,
+ /* [out] */ double *value);
+
+ HRESULT ( STDMETHODCALLTYPE *GetString )(
+ IBMDStreamingMutableVideoEncodingMode * This,
+ /* [in] */ BMDStreamingEncodingModePropertyID cfgID,
+ /* [out] */ BSTR *value);
+
+ HRESULT ( STDMETHODCALLTYPE *CreateMutableVideoEncodingMode )(
+ IBMDStreamingMutableVideoEncodingMode * This,
+ /* [out] */ IBMDStreamingMutableVideoEncodingMode **newEncodingMode);
+
+ HRESULT ( STDMETHODCALLTYPE *SetSourceRect )(
+ IBMDStreamingMutableVideoEncodingMode * This,
+ /* [in] */ unsigned int posX,
+ /* [in] */ unsigned int posY,
+ /* [in] */ unsigned int width,
+ /* [in] */ unsigned int height);
+
+ HRESULT ( STDMETHODCALLTYPE *SetDestSize )(
+ IBMDStreamingMutableVideoEncodingMode * This,
+ /* [in] */ unsigned int width,
+ /* [in] */ unsigned int height);
+
+ HRESULT ( STDMETHODCALLTYPE *SetFlag )(
+ IBMDStreamingMutableVideoEncodingMode * This,
+ /* [in] */ BMDStreamingEncodingModePropertyID cfgID,
+ /* [in] */ BOOL value);
+
+ HRESULT ( STDMETHODCALLTYPE *SetInt )(
+ IBMDStreamingMutableVideoEncodingMode * This,
+ /* [in] */ BMDStreamingEncodingModePropertyID cfgID,
+ /* [in] */ LONGLONG value);
+
+ HRESULT ( STDMETHODCALLTYPE *SetFloat )(
+ IBMDStreamingMutableVideoEncodingMode * This,
+ /* [in] */ BMDStreamingEncodingModePropertyID cfgID,
+ /* [in] */ double value);
+
+ HRESULT ( STDMETHODCALLTYPE *SetString )(
+ IBMDStreamingMutableVideoEncodingMode * This,
+ /* [in] */ BMDStreamingEncodingModePropertyID cfgID,
+ /* [in] */ BSTR value);
+
+ END_INTERFACE
+ } IBMDStreamingMutableVideoEncodingModeVtbl;
+
+ interface IBMDStreamingMutableVideoEncodingMode
+ {
+ CONST_VTBL struct IBMDStreamingMutableVideoEncodingModeVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IBMDStreamingMutableVideoEncodingMode_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IBMDStreamingMutableVideoEncodingMode_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IBMDStreamingMutableVideoEncodingMode_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IBMDStreamingMutableVideoEncodingMode_GetName(This,name) \
+ ( (This)->lpVtbl -> GetName(This,name) )
+
+#define IBMDStreamingMutableVideoEncodingMode_GetPresetID(This) \
+ ( (This)->lpVtbl -> GetPresetID(This) )
+
+#define IBMDStreamingMutableVideoEncodingMode_GetSourcePositionX(This) \
+ ( (This)->lpVtbl -> GetSourcePositionX(This) )
+
+#define IBMDStreamingMutableVideoEncodingMode_GetSourcePositionY(This) \
+ ( (This)->lpVtbl -> GetSourcePositionY(This) )
+
+#define IBMDStreamingMutableVideoEncodingMode_GetSourceWidth(This) \
+ ( (This)->lpVtbl -> GetSourceWidth(This) )
+
+#define IBMDStreamingMutableVideoEncodingMode_GetSourceHeight(This) \
+ ( (This)->lpVtbl -> GetSourceHeight(This) )
+
+#define IBMDStreamingMutableVideoEncodingMode_GetDestWidth(This) \
+ ( (This)->lpVtbl -> GetDestWidth(This) )
+
+#define IBMDStreamingMutableVideoEncodingMode_GetDestHeight(This) \
+ ( (This)->lpVtbl -> GetDestHeight(This) )
+
+#define IBMDStreamingMutableVideoEncodingMode_GetFlag(This,cfgID,value) \
+ ( (This)->lpVtbl -> GetFlag(This,cfgID,value) )
+
+#define IBMDStreamingMutableVideoEncodingMode_GetInt(This,cfgID,value) \
+ ( (This)->lpVtbl -> GetInt(This,cfgID,value) )
+
+#define IBMDStreamingMutableVideoEncodingMode_GetFloat(This,cfgID,value) \
+ ( (This)->lpVtbl -> GetFloat(This,cfgID,value) )
+
+#define IBMDStreamingMutableVideoEncodingMode_GetString(This,cfgID,value) \
+ ( (This)->lpVtbl -> GetString(This,cfgID,value) )
+
+#define IBMDStreamingMutableVideoEncodingMode_CreateMutableVideoEncodingMode(This,newEncodingMode) \
+ ( (This)->lpVtbl -> CreateMutableVideoEncodingMode(This,newEncodingMode) )
+
+
+#define IBMDStreamingMutableVideoEncodingMode_SetSourceRect(This,posX,posY,width,height) \
+ ( (This)->lpVtbl -> SetSourceRect(This,posX,posY,width,height) )
+
+#define IBMDStreamingMutableVideoEncodingMode_SetDestSize(This,width,height) \
+ ( (This)->lpVtbl -> SetDestSize(This,width,height) )
+
+#define IBMDStreamingMutableVideoEncodingMode_SetFlag(This,cfgID,value) \
+ ( (This)->lpVtbl -> SetFlag(This,cfgID,value) )
+
+#define IBMDStreamingMutableVideoEncodingMode_SetInt(This,cfgID,value) \
+ ( (This)->lpVtbl -> SetInt(This,cfgID,value) )
+
+#define IBMDStreamingMutableVideoEncodingMode_SetFloat(This,cfgID,value) \
+ ( (This)->lpVtbl -> SetFloat(This,cfgID,value) )
+
+#define IBMDStreamingMutableVideoEncodingMode_SetString(This,cfgID,value) \
+ ( (This)->lpVtbl -> SetString(This,cfgID,value) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IBMDStreamingMutableVideoEncodingMode_INTERFACE_DEFINED__ */
+
+
+#ifndef __IBMDStreamingVideoEncodingModePresetIterator_INTERFACE_DEFINED__
+#define __IBMDStreamingVideoEncodingModePresetIterator_INTERFACE_DEFINED__
+
+/* interface IBMDStreamingVideoEncodingModePresetIterator */
+/* [helpstring][uuid][object] */
+
+
+EXTERN_C const IID IID_IBMDStreamingVideoEncodingModePresetIterator;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("7AC731A3-C950-4AD0-804A-8377AA51C6C4")
+ IBMDStreamingVideoEncodingModePresetIterator : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Next(
+ /* [out] */ IBMDStreamingVideoEncodingMode **videoEncodingMode) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IBMDStreamingVideoEncodingModePresetIteratorVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IBMDStreamingVideoEncodingModePresetIterator * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IBMDStreamingVideoEncodingModePresetIterator * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IBMDStreamingVideoEncodingModePresetIterator * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Next )(
+ IBMDStreamingVideoEncodingModePresetIterator * This,
+ /* [out] */ IBMDStreamingVideoEncodingMode **videoEncodingMode);
+
+ END_INTERFACE
+ } IBMDStreamingVideoEncodingModePresetIteratorVtbl;
+
+ interface IBMDStreamingVideoEncodingModePresetIterator
+ {
+ CONST_VTBL struct IBMDStreamingVideoEncodingModePresetIteratorVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IBMDStreamingVideoEncodingModePresetIterator_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IBMDStreamingVideoEncodingModePresetIterator_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IBMDStreamingVideoEncodingModePresetIterator_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IBMDStreamingVideoEncodingModePresetIterator_Next(This,videoEncodingMode) \
+ ( (This)->lpVtbl -> Next(This,videoEncodingMode) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IBMDStreamingVideoEncodingModePresetIterator_INTERFACE_DEFINED__ */
+
+
+#ifndef __IBMDStreamingDeviceInput_INTERFACE_DEFINED__
+#define __IBMDStreamingDeviceInput_INTERFACE_DEFINED__
+
+/* interface IBMDStreamingDeviceInput */
+/* [helpstring][uuid][object] */
+
+
+EXTERN_C const IID IID_IBMDStreamingDeviceInput;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("24B6B6EC-1727-44BB-9818-34FF086ACF98")
+ IBMDStreamingDeviceInput : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE DoesSupportVideoInputMode(
+ /* [in] */ BMDDisplayMode inputMode,
+ /* [out] */ BOOL *result) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetVideoInputModeIterator(
+ /* [out] */ IDeckLinkDisplayModeIterator **iterator) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetVideoInputMode(
+ /* [in] */ BMDDisplayMode inputMode) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetCurrentDetectedVideoInputMode(
+ /* [out] */ BMDDisplayMode *detectedMode) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetVideoEncodingMode(
+ /* [out] */ IBMDStreamingVideoEncodingMode **encodingMode) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetVideoEncodingModePresetIterator(
+ /* [in] */ BMDDisplayMode inputMode,
+ /* [out] */ IBMDStreamingVideoEncodingModePresetIterator **iterator) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE DoesSupportVideoEncodingMode(
+ /* [in] */ BMDDisplayMode inputMode,
+ /* [in] */ IBMDStreamingVideoEncodingMode *encodingMode,
+ /* [out] */ BMDStreamingEncodingSupport *result,
+ /* [out] */ IBMDStreamingVideoEncodingMode **changedEncodingMode) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetVideoEncodingMode(
+ /* [in] */ IBMDStreamingVideoEncodingMode *encodingMode) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE StartCapture( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE StopCapture( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetCallback(
+ /* [in] */ IUnknown *theCallback) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IBMDStreamingDeviceInputVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IBMDStreamingDeviceInput * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IBMDStreamingDeviceInput * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IBMDStreamingDeviceInput * This);
+
+ HRESULT ( STDMETHODCALLTYPE *DoesSupportVideoInputMode )(
+ IBMDStreamingDeviceInput * This,
+ /* [in] */ BMDDisplayMode inputMode,
+ /* [out] */ BOOL *result);
+
+ HRESULT ( STDMETHODCALLTYPE *GetVideoInputModeIterator )(
+ IBMDStreamingDeviceInput * This,
+ /* [out] */ IDeckLinkDisplayModeIterator **iterator);
+
+ HRESULT ( STDMETHODCALLTYPE *SetVideoInputMode )(
+ IBMDStreamingDeviceInput * This,
+ /* [in] */ BMDDisplayMode inputMode);
+
+ HRESULT ( STDMETHODCALLTYPE *GetCurrentDetectedVideoInputMode )(
+ IBMDStreamingDeviceInput * This,
+ /* [out] */ BMDDisplayMode *detectedMode);
+
+ HRESULT ( STDMETHODCALLTYPE *GetVideoEncodingMode )(
+ IBMDStreamingDeviceInput * This,
+ /* [out] */ IBMDStreamingVideoEncodingMode **encodingMode);
+
+ HRESULT ( STDMETHODCALLTYPE *GetVideoEncodingModePresetIterator )(
+ IBMDStreamingDeviceInput * This,
+ /* [in] */ BMDDisplayMode inputMode,
+ /* [out] */ IBMDStreamingVideoEncodingModePresetIterator **iterator);
+
+ HRESULT ( STDMETHODCALLTYPE *DoesSupportVideoEncodingMode )(
+ IBMDStreamingDeviceInput * This,
+ /* [in] */ BMDDisplayMode inputMode,
+ /* [in] */ IBMDStreamingVideoEncodingMode *encodingMode,
+ /* [out] */ BMDStreamingEncodingSupport *result,
+ /* [out] */ IBMDStreamingVideoEncodingMode **changedEncodingMode);
+
+ HRESULT ( STDMETHODCALLTYPE *SetVideoEncodingMode )(
+ IBMDStreamingDeviceInput * This,
+ /* [in] */ IBMDStreamingVideoEncodingMode *encodingMode);
+
+ HRESULT ( STDMETHODCALLTYPE *StartCapture )(
+ IBMDStreamingDeviceInput * This);
+
+ HRESULT ( STDMETHODCALLTYPE *StopCapture )(
+ IBMDStreamingDeviceInput * This);
+
+ HRESULT ( STDMETHODCALLTYPE *SetCallback )(
+ IBMDStreamingDeviceInput * This,
+ /* [in] */ IUnknown *theCallback);
+
+ END_INTERFACE
+ } IBMDStreamingDeviceInputVtbl;
+
+ interface IBMDStreamingDeviceInput
+ {
+ CONST_VTBL struct IBMDStreamingDeviceInputVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IBMDStreamingDeviceInput_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IBMDStreamingDeviceInput_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IBMDStreamingDeviceInput_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IBMDStreamingDeviceInput_DoesSupportVideoInputMode(This,inputMode,result) \
+ ( (This)->lpVtbl -> DoesSupportVideoInputMode(This,inputMode,result) )
+
+#define IBMDStreamingDeviceInput_GetVideoInputModeIterator(This,iterator) \
+ ( (This)->lpVtbl -> GetVideoInputModeIterator(This,iterator) )
+
+#define IBMDStreamingDeviceInput_SetVideoInputMode(This,inputMode) \
+ ( (This)->lpVtbl -> SetVideoInputMode(This,inputMode) )
+
+#define IBMDStreamingDeviceInput_GetCurrentDetectedVideoInputMode(This,detectedMode) \
+ ( (This)->lpVtbl -> GetCurrentDetectedVideoInputMode(This,detectedMode) )
+
+#define IBMDStreamingDeviceInput_GetVideoEncodingMode(This,encodingMode) \
+ ( (This)->lpVtbl -> GetVideoEncodingMode(This,encodingMode) )
+
+#define IBMDStreamingDeviceInput_GetVideoEncodingModePresetIterator(This,inputMode,iterator) \
+ ( (This)->lpVtbl -> GetVideoEncodingModePresetIterator(This,inputMode,iterator) )
+
+#define IBMDStreamingDeviceInput_DoesSupportVideoEncodingMode(This,inputMode,encodingMode,result,changedEncodingMode) \
+ ( (This)->lpVtbl -> DoesSupportVideoEncodingMode(This,inputMode,encodingMode,result,changedEncodingMode) )
+
+#define IBMDStreamingDeviceInput_SetVideoEncodingMode(This,encodingMode) \
+ ( (This)->lpVtbl -> SetVideoEncodingMode(This,encodingMode) )
+
+#define IBMDStreamingDeviceInput_StartCapture(This) \
+ ( (This)->lpVtbl -> StartCapture(This) )
+
+#define IBMDStreamingDeviceInput_StopCapture(This) \
+ ( (This)->lpVtbl -> StopCapture(This) )
+
+#define IBMDStreamingDeviceInput_SetCallback(This,theCallback) \
+ ( (This)->lpVtbl -> SetCallback(This,theCallback) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IBMDStreamingDeviceInput_INTERFACE_DEFINED__ */
+
+
+#ifndef __IBMDStreamingH264NALPacket_INTERFACE_DEFINED__
+#define __IBMDStreamingH264NALPacket_INTERFACE_DEFINED__
+
+/* interface IBMDStreamingH264NALPacket */
+/* [helpstring][uuid][object] */
+
+
+EXTERN_C const IID IID_IBMDStreamingH264NALPacket;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("E260E955-14BE-4395-9775-9F02CC0A9D89")
+ IBMDStreamingH264NALPacket : public IUnknown
+ {
+ public:
+ virtual long STDMETHODCALLTYPE GetPayloadSize( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetBytes(
+ /* [out] */ void **buffer) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetBytesWithSizePrefix(
+ /* [out] */ void **buffer) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetDisplayTime(
+ /* [in] */ ULONGLONG requestedTimeScale,
+ /* [out] */ ULONGLONG *displayTime) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetPacketIndex(
+ /* [out] */ unsigned int *packetIndex) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IBMDStreamingH264NALPacketVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IBMDStreamingH264NALPacket * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IBMDStreamingH264NALPacket * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IBMDStreamingH264NALPacket * This);
+
+ long ( STDMETHODCALLTYPE *GetPayloadSize )(
+ IBMDStreamingH264NALPacket * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetBytes )(
+ IBMDStreamingH264NALPacket * This,
+ /* [out] */ void **buffer);
+
+ HRESULT ( STDMETHODCALLTYPE *GetBytesWithSizePrefix )(
+ IBMDStreamingH264NALPacket * This,
+ /* [out] */ void **buffer);
+
+ HRESULT ( STDMETHODCALLTYPE *GetDisplayTime )(
+ IBMDStreamingH264NALPacket * This,
+ /* [in] */ ULONGLONG requestedTimeScale,
+ /* [out] */ ULONGLONG *displayTime);
+
+ HRESULT ( STDMETHODCALLTYPE *GetPacketIndex )(
+ IBMDStreamingH264NALPacket * This,
+ /* [out] */ unsigned int *packetIndex);
+
+ END_INTERFACE
+ } IBMDStreamingH264NALPacketVtbl;
+
+ interface IBMDStreamingH264NALPacket
+ {
+ CONST_VTBL struct IBMDStreamingH264NALPacketVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IBMDStreamingH264NALPacket_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IBMDStreamingH264NALPacket_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IBMDStreamingH264NALPacket_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IBMDStreamingH264NALPacket_GetPayloadSize(This) \
+ ( (This)->lpVtbl -> GetPayloadSize(This) )
+
+#define IBMDStreamingH264NALPacket_GetBytes(This,buffer) \
+ ( (This)->lpVtbl -> GetBytes(This,buffer) )
+
+#define IBMDStreamingH264NALPacket_GetBytesWithSizePrefix(This,buffer) \
+ ( (This)->lpVtbl -> GetBytesWithSizePrefix(This,buffer) )
+
+#define IBMDStreamingH264NALPacket_GetDisplayTime(This,requestedTimeScale,displayTime) \
+ ( (This)->lpVtbl -> GetDisplayTime(This,requestedTimeScale,displayTime) )
+
+#define IBMDStreamingH264NALPacket_GetPacketIndex(This,packetIndex) \
+ ( (This)->lpVtbl -> GetPacketIndex(This,packetIndex) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IBMDStreamingH264NALPacket_INTERFACE_DEFINED__ */
+
+
+#ifndef __IBMDStreamingAudioPacket_INTERFACE_DEFINED__
+#define __IBMDStreamingAudioPacket_INTERFACE_DEFINED__
+
+/* interface IBMDStreamingAudioPacket */
+/* [helpstring][uuid][object] */
+
+
+EXTERN_C const IID IID_IBMDStreamingAudioPacket;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("D9EB5902-1AD2-43F4-9E2C-3CFA50B5EE19")
+ IBMDStreamingAudioPacket : public IUnknown
+ {
+ public:
+ virtual BMDStreamingAudioCodec STDMETHODCALLTYPE GetCodec( void) = 0;
+
+ virtual long STDMETHODCALLTYPE GetPayloadSize( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetBytes(
+ /* [out] */ void **buffer) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetPlayTime(
+ /* [in] */ ULONGLONG requestedTimeScale,
+ /* [out] */ ULONGLONG *playTime) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetPacketIndex(
+ /* [out] */ unsigned int *packetIndex) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IBMDStreamingAudioPacketVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IBMDStreamingAudioPacket * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IBMDStreamingAudioPacket * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IBMDStreamingAudioPacket * This);
+
+ BMDStreamingAudioCodec ( STDMETHODCALLTYPE *GetCodec )(
+ IBMDStreamingAudioPacket * This);
+
+ long ( STDMETHODCALLTYPE *GetPayloadSize )(
+ IBMDStreamingAudioPacket * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetBytes )(
+ IBMDStreamingAudioPacket * This,
+ /* [out] */ void **buffer);
+
+ HRESULT ( STDMETHODCALLTYPE *GetPlayTime )(
+ IBMDStreamingAudioPacket * This,
+ /* [in] */ ULONGLONG requestedTimeScale,
+ /* [out] */ ULONGLONG *playTime);
+
+ HRESULT ( STDMETHODCALLTYPE *GetPacketIndex )(
+ IBMDStreamingAudioPacket * This,
+ /* [out] */ unsigned int *packetIndex);
+
+ END_INTERFACE
+ } IBMDStreamingAudioPacketVtbl;
+
+ interface IBMDStreamingAudioPacket
+ {
+ CONST_VTBL struct IBMDStreamingAudioPacketVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IBMDStreamingAudioPacket_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IBMDStreamingAudioPacket_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IBMDStreamingAudioPacket_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IBMDStreamingAudioPacket_GetCodec(This) \
+ ( (This)->lpVtbl -> GetCodec(This) )
+
+#define IBMDStreamingAudioPacket_GetPayloadSize(This) \
+ ( (This)->lpVtbl -> GetPayloadSize(This) )
+
+#define IBMDStreamingAudioPacket_GetBytes(This,buffer) \
+ ( (This)->lpVtbl -> GetBytes(This,buffer) )
+
+#define IBMDStreamingAudioPacket_GetPlayTime(This,requestedTimeScale,playTime) \
+ ( (This)->lpVtbl -> GetPlayTime(This,requestedTimeScale,playTime) )
+
+#define IBMDStreamingAudioPacket_GetPacketIndex(This,packetIndex) \
+ ( (This)->lpVtbl -> GetPacketIndex(This,packetIndex) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IBMDStreamingAudioPacket_INTERFACE_DEFINED__ */
+
+
+#ifndef __IBMDStreamingMPEG2TSPacket_INTERFACE_DEFINED__
+#define __IBMDStreamingMPEG2TSPacket_INTERFACE_DEFINED__
+
+/* interface IBMDStreamingMPEG2TSPacket */
+/* [helpstring][uuid][object] */
+
+
+EXTERN_C const IID IID_IBMDStreamingMPEG2TSPacket;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("91810D1C-4FB3-4AAA-AE56-FA301D3DFA4C")
+ IBMDStreamingMPEG2TSPacket : public IUnknown
+ {
+ public:
+ virtual long STDMETHODCALLTYPE GetPayloadSize( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetBytes(
+ /* [out] */ void **buffer) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IBMDStreamingMPEG2TSPacketVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IBMDStreamingMPEG2TSPacket * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IBMDStreamingMPEG2TSPacket * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IBMDStreamingMPEG2TSPacket * This);
+
+ long ( STDMETHODCALLTYPE *GetPayloadSize )(
+ IBMDStreamingMPEG2TSPacket * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetBytes )(
+ IBMDStreamingMPEG2TSPacket * This,
+ /* [out] */ void **buffer);
+
+ END_INTERFACE
+ } IBMDStreamingMPEG2TSPacketVtbl;
+
+ interface IBMDStreamingMPEG2TSPacket
+ {
+ CONST_VTBL struct IBMDStreamingMPEG2TSPacketVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IBMDStreamingMPEG2TSPacket_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IBMDStreamingMPEG2TSPacket_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IBMDStreamingMPEG2TSPacket_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IBMDStreamingMPEG2TSPacket_GetPayloadSize(This) \
+ ( (This)->lpVtbl -> GetPayloadSize(This) )
+
+#define IBMDStreamingMPEG2TSPacket_GetBytes(This,buffer) \
+ ( (This)->lpVtbl -> GetBytes(This,buffer) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IBMDStreamingMPEG2TSPacket_INTERFACE_DEFINED__ */
+
+
+#ifndef __IBMDStreamingH264NALParser_INTERFACE_DEFINED__
+#define __IBMDStreamingH264NALParser_INTERFACE_DEFINED__
+
+/* interface IBMDStreamingH264NALParser */
+/* [helpstring][uuid][object] */
+
+
+EXTERN_C const IID IID_IBMDStreamingH264NALParser;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("5867F18C-5BFA-4CCC-B2A7-9DFD140417D2")
+ IBMDStreamingH264NALParser : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE IsNALSequenceParameterSet(
+ /* [in] */ IBMDStreamingH264NALPacket *nal) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE IsNALPictureParameterSet(
+ /* [in] */ IBMDStreamingH264NALPacket *nal) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetProfileAndLevelFromSPS(
+ /* [in] */ IBMDStreamingH264NALPacket *nal,
+ /* [out] */ unsigned int *profileIdc,
+ /* [out] */ unsigned int *profileCompatability,
+ /* [out] */ unsigned int *levelIdc) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IBMDStreamingH264NALParserVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IBMDStreamingH264NALParser * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IBMDStreamingH264NALParser * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IBMDStreamingH264NALParser * This);
+
+ HRESULT ( STDMETHODCALLTYPE *IsNALSequenceParameterSet )(
+ IBMDStreamingH264NALParser * This,
+ /* [in] */ IBMDStreamingH264NALPacket *nal);
+
+ HRESULT ( STDMETHODCALLTYPE *IsNALPictureParameterSet )(
+ IBMDStreamingH264NALParser * This,
+ /* [in] */ IBMDStreamingH264NALPacket *nal);
+
+ HRESULT ( STDMETHODCALLTYPE *GetProfileAndLevelFromSPS )(
+ IBMDStreamingH264NALParser * This,
+ /* [in] */ IBMDStreamingH264NALPacket *nal,
+ /* [out] */ unsigned int *profileIdc,
+ /* [out] */ unsigned int *profileCompatability,
+ /* [out] */ unsigned int *levelIdc);
+
+ END_INTERFACE
+ } IBMDStreamingH264NALParserVtbl;
+
+ interface IBMDStreamingH264NALParser
+ {
+ CONST_VTBL struct IBMDStreamingH264NALParserVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IBMDStreamingH264NALParser_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IBMDStreamingH264NALParser_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IBMDStreamingH264NALParser_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IBMDStreamingH264NALParser_IsNALSequenceParameterSet(This,nal) \
+ ( (This)->lpVtbl -> IsNALSequenceParameterSet(This,nal) )
+
+#define IBMDStreamingH264NALParser_IsNALPictureParameterSet(This,nal) \
+ ( (This)->lpVtbl -> IsNALPictureParameterSet(This,nal) )
+
+#define IBMDStreamingH264NALParser_GetProfileAndLevelFromSPS(This,nal,profileIdc,profileCompatability,levelIdc) \
+ ( (This)->lpVtbl -> GetProfileAndLevelFromSPS(This,nal,profileIdc,profileCompatability,levelIdc) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IBMDStreamingH264NALParser_INTERFACE_DEFINED__ */
+
+
+EXTERN_C const CLSID CLSID_CBMDStreamingDiscovery;
+
+#ifdef __cplusplus
+
+class DECLSPEC_UUID("0CAA31F6-8A26-40B0-86A4-BF58DCCA710C")
+CBMDStreamingDiscovery;
+#endif
+
+EXTERN_C const CLSID CLSID_CBMDStreamingH264NALParser;
+
+#ifdef __cplusplus
+
+class DECLSPEC_UUID("7753EFBD-951C-407C-97A5-23C737B73B52")
+CBMDStreamingH264NALParser;
+#endif
+
+#ifndef __IDeckLinkVideoOutputCallback_INTERFACE_DEFINED__
+#define __IDeckLinkVideoOutputCallback_INTERFACE_DEFINED__
+
+/* interface IDeckLinkVideoOutputCallback */
+/* [helpstring][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkVideoOutputCallback;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("20AA5225-1958-47CB-820B-80A8D521A6EE")
+ IDeckLinkVideoOutputCallback : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE ScheduledFrameCompleted(
+ /* [in] */ IDeckLinkVideoFrame *completedFrame,
+ /* [in] */ BMDOutputFrameCompletionResult result) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE ScheduledPlaybackHasStopped( void) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkVideoOutputCallbackVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkVideoOutputCallback * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkVideoOutputCallback * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkVideoOutputCallback * This);
+
+ HRESULT ( STDMETHODCALLTYPE *ScheduledFrameCompleted )(
+ IDeckLinkVideoOutputCallback * This,
+ /* [in] */ IDeckLinkVideoFrame *completedFrame,
+ /* [in] */ BMDOutputFrameCompletionResult result);
+
+ HRESULT ( STDMETHODCALLTYPE *ScheduledPlaybackHasStopped )(
+ IDeckLinkVideoOutputCallback * This);
+
+ END_INTERFACE
+ } IDeckLinkVideoOutputCallbackVtbl;
+
+ interface IDeckLinkVideoOutputCallback
+ {
+ CONST_VTBL struct IDeckLinkVideoOutputCallbackVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkVideoOutputCallback_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkVideoOutputCallback_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkVideoOutputCallback_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkVideoOutputCallback_ScheduledFrameCompleted(This,completedFrame,result) \
+ ( (This)->lpVtbl -> ScheduledFrameCompleted(This,completedFrame,result) )
+
+#define IDeckLinkVideoOutputCallback_ScheduledPlaybackHasStopped(This) \
+ ( (This)->lpVtbl -> ScheduledPlaybackHasStopped(This) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkVideoOutputCallback_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkInputCallback_INTERFACE_DEFINED__
+#define __IDeckLinkInputCallback_INTERFACE_DEFINED__
+
+/* interface IDeckLinkInputCallback */
+/* [helpstring][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkInputCallback;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("DD04E5EC-7415-42AB-AE4A-E80C4DFC044A")
+ IDeckLinkInputCallback : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE VideoInputFormatChanged(
+ /* [in] */ BMDVideoInputFormatChangedEvents notificationEvents,
+ /* [in] */ IDeckLinkDisplayMode *newDisplayMode,
+ /* [in] */ BMDDetectedVideoInputFormatFlags detectedSignalFlags) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE VideoInputFrameArrived(
+ /* [in] */ IDeckLinkVideoInputFrame *videoFrame,
+ /* [in] */ IDeckLinkAudioInputPacket *audioPacket) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkInputCallbackVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkInputCallback * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkInputCallback * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkInputCallback * This);
+
+ HRESULT ( STDMETHODCALLTYPE *VideoInputFormatChanged )(
+ IDeckLinkInputCallback * This,
+ /* [in] */ BMDVideoInputFormatChangedEvents notificationEvents,
+ /* [in] */ IDeckLinkDisplayMode *newDisplayMode,
+ /* [in] */ BMDDetectedVideoInputFormatFlags detectedSignalFlags);
+
+ HRESULT ( STDMETHODCALLTYPE *VideoInputFrameArrived )(
+ IDeckLinkInputCallback * This,
+ /* [in] */ IDeckLinkVideoInputFrame *videoFrame,
+ /* [in] */ IDeckLinkAudioInputPacket *audioPacket);
+
+ END_INTERFACE
+ } IDeckLinkInputCallbackVtbl;
+
+ interface IDeckLinkInputCallback
+ {
+ CONST_VTBL struct IDeckLinkInputCallbackVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkInputCallback_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkInputCallback_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkInputCallback_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkInputCallback_VideoInputFormatChanged(This,notificationEvents,newDisplayMode,detectedSignalFlags) \
+ ( (This)->lpVtbl -> VideoInputFormatChanged(This,notificationEvents,newDisplayMode,detectedSignalFlags) )
+
+#define IDeckLinkInputCallback_VideoInputFrameArrived(This,videoFrame,audioPacket) \
+ ( (This)->lpVtbl -> VideoInputFrameArrived(This,videoFrame,audioPacket) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkInputCallback_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkMemoryAllocator_INTERFACE_DEFINED__
+#define __IDeckLinkMemoryAllocator_INTERFACE_DEFINED__
+
+/* interface IDeckLinkMemoryAllocator */
+/* [helpstring][local][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkMemoryAllocator;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("B36EB6E7-9D29-4AA8-92EF-843B87A289E8")
+ IDeckLinkMemoryAllocator : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE AllocateBuffer(
+ /* [in] */ unsigned int bufferSize,
+ /* [out] */ void **allocatedBuffer) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE ReleaseBuffer(
+ /* [in] */ void *buffer) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Commit( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Decommit( void) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkMemoryAllocatorVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkMemoryAllocator * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkMemoryAllocator * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkMemoryAllocator * This);
+
+ HRESULT ( STDMETHODCALLTYPE *AllocateBuffer )(
+ IDeckLinkMemoryAllocator * This,
+ /* [in] */ unsigned int bufferSize,
+ /* [out] */ void **allocatedBuffer);
+
+ HRESULT ( STDMETHODCALLTYPE *ReleaseBuffer )(
+ IDeckLinkMemoryAllocator * This,
+ /* [in] */ void *buffer);
+
+ HRESULT ( STDMETHODCALLTYPE *Commit )(
+ IDeckLinkMemoryAllocator * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Decommit )(
+ IDeckLinkMemoryAllocator * This);
+
+ END_INTERFACE
+ } IDeckLinkMemoryAllocatorVtbl;
+
+ interface IDeckLinkMemoryAllocator
+ {
+ CONST_VTBL struct IDeckLinkMemoryAllocatorVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkMemoryAllocator_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkMemoryAllocator_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkMemoryAllocator_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkMemoryAllocator_AllocateBuffer(This,bufferSize,allocatedBuffer) \
+ ( (This)->lpVtbl -> AllocateBuffer(This,bufferSize,allocatedBuffer) )
+
+#define IDeckLinkMemoryAllocator_ReleaseBuffer(This,buffer) \
+ ( (This)->lpVtbl -> ReleaseBuffer(This,buffer) )
+
+#define IDeckLinkMemoryAllocator_Commit(This) \
+ ( (This)->lpVtbl -> Commit(This) )
+
+#define IDeckLinkMemoryAllocator_Decommit(This) \
+ ( (This)->lpVtbl -> Decommit(This) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkMemoryAllocator_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkAudioOutputCallback_INTERFACE_DEFINED__
+#define __IDeckLinkAudioOutputCallback_INTERFACE_DEFINED__
+
+/* interface IDeckLinkAudioOutputCallback */
+/* [helpstring][local][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkAudioOutputCallback;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("403C681B-7F46-4A12-B993-2BB127084EE6")
+ IDeckLinkAudioOutputCallback : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE RenderAudioSamples(
+ /* [in] */ BOOL preroll) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkAudioOutputCallbackVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkAudioOutputCallback * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkAudioOutputCallback * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkAudioOutputCallback * This);
+
+ HRESULT ( STDMETHODCALLTYPE *RenderAudioSamples )(
+ IDeckLinkAudioOutputCallback * This,
+ /* [in] */ BOOL preroll);
+
+ END_INTERFACE
+ } IDeckLinkAudioOutputCallbackVtbl;
+
+ interface IDeckLinkAudioOutputCallback
+ {
+ CONST_VTBL struct IDeckLinkAudioOutputCallbackVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkAudioOutputCallback_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkAudioOutputCallback_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkAudioOutputCallback_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkAudioOutputCallback_RenderAudioSamples(This,preroll) \
+ ( (This)->lpVtbl -> RenderAudioSamples(This,preroll) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkAudioOutputCallback_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkIterator_INTERFACE_DEFINED__
+#define __IDeckLinkIterator_INTERFACE_DEFINED__
+
+/* interface IDeckLinkIterator */
+/* [helpstring][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkIterator;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("50FB36CD-3063-4B73-BDBB-958087F2D8BA")
+ IDeckLinkIterator : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Next(
+ /* [out] */ IDeckLink **deckLinkInstance) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkIteratorVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkIterator * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkIterator * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkIterator * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Next )(
+ IDeckLinkIterator * This,
+ /* [out] */ IDeckLink **deckLinkInstance);
+
+ END_INTERFACE
+ } IDeckLinkIteratorVtbl;
+
+ interface IDeckLinkIterator
+ {
+ CONST_VTBL struct IDeckLinkIteratorVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkIterator_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkIterator_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkIterator_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkIterator_Next(This,deckLinkInstance) \
+ ( (This)->lpVtbl -> Next(This,deckLinkInstance) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkIterator_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkAPIInformation_INTERFACE_DEFINED__
+#define __IDeckLinkAPIInformation_INTERFACE_DEFINED__
+
+/* interface IDeckLinkAPIInformation */
+/* [helpstring][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkAPIInformation;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("7BEA3C68-730D-4322-AF34-8A7152B532A4")
+ IDeckLinkAPIInformation : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE GetFlag(
+ /* [in] */ BMDDeckLinkAPIInformationID cfgID,
+ /* [out] */ BOOL *value) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetInt(
+ /* [in] */ BMDDeckLinkAPIInformationID cfgID,
+ /* [out] */ LONGLONG *value) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetFloat(
+ /* [in] */ BMDDeckLinkAPIInformationID cfgID,
+ /* [out] */ double *value) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetString(
+ /* [in] */ BMDDeckLinkAPIInformationID cfgID,
+ /* [out] */ BSTR *value) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkAPIInformationVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkAPIInformation * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkAPIInformation * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkAPIInformation * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetFlag )(
+ IDeckLinkAPIInformation * This,
+ /* [in] */ BMDDeckLinkAPIInformationID cfgID,
+ /* [out] */ BOOL *value);
+
+ HRESULT ( STDMETHODCALLTYPE *GetInt )(
+ IDeckLinkAPIInformation * This,
+ /* [in] */ BMDDeckLinkAPIInformationID cfgID,
+ /* [out] */ LONGLONG *value);
+
+ HRESULT ( STDMETHODCALLTYPE *GetFloat )(
+ IDeckLinkAPIInformation * This,
+ /* [in] */ BMDDeckLinkAPIInformationID cfgID,
+ /* [out] */ double *value);
+
+ HRESULT ( STDMETHODCALLTYPE *GetString )(
+ IDeckLinkAPIInformation * This,
+ /* [in] */ BMDDeckLinkAPIInformationID cfgID,
+ /* [out] */ BSTR *value);
+
+ END_INTERFACE
+ } IDeckLinkAPIInformationVtbl;
+
+ interface IDeckLinkAPIInformation
+ {
+ CONST_VTBL struct IDeckLinkAPIInformationVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkAPIInformation_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkAPIInformation_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkAPIInformation_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkAPIInformation_GetFlag(This,cfgID,value) \
+ ( (This)->lpVtbl -> GetFlag(This,cfgID,value) )
+
+#define IDeckLinkAPIInformation_GetInt(This,cfgID,value) \
+ ( (This)->lpVtbl -> GetInt(This,cfgID,value) )
+
+#define IDeckLinkAPIInformation_GetFloat(This,cfgID,value) \
+ ( (This)->lpVtbl -> GetFloat(This,cfgID,value) )
+
+#define IDeckLinkAPIInformation_GetString(This,cfgID,value) \
+ ( (This)->lpVtbl -> GetString(This,cfgID,value) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkAPIInformation_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkOutput_INTERFACE_DEFINED__
+#define __IDeckLinkOutput_INTERFACE_DEFINED__
+
+/* interface IDeckLinkOutput */
+/* [helpstring][local][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkOutput;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("CC5C8A6E-3F2F-4B3A-87EA-FD78AF300564")
+ IDeckLinkOutput : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE DoesSupportVideoMode(
+ /* [in] */ BMDDisplayMode displayMode,
+ /* [in] */ BMDPixelFormat pixelFormat,
+ /* [in] */ BMDVideoOutputFlags flags,
+ /* [out] */ BMDDisplayModeSupport *result,
+ /* [out] */ IDeckLinkDisplayMode **resultDisplayMode) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetDisplayModeIterator(
+ /* [out] */ IDeckLinkDisplayModeIterator **iterator) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetScreenPreviewCallback(
+ /* [in] */ IDeckLinkScreenPreviewCallback *previewCallback) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE EnableVideoOutput(
+ /* [in] */ BMDDisplayMode displayMode,
+ /* [in] */ BMDVideoOutputFlags flags) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE DisableVideoOutput( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetVideoOutputFrameMemoryAllocator(
+ /* [in] */ IDeckLinkMemoryAllocator *theAllocator) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE CreateVideoFrame(
+ /* [in] */ int width,
+ /* [in] */ int height,
+ /* [in] */ int rowBytes,
+ /* [in] */ BMDPixelFormat pixelFormat,
+ /* [in] */ BMDFrameFlags flags,
+ /* [out] */ IDeckLinkMutableVideoFrame **outFrame) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE CreateAncillaryData(
+ /* [in] */ BMDPixelFormat pixelFormat,
+ /* [out] */ IDeckLinkVideoFrameAncillary **outBuffer) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE DisplayVideoFrameSync(
+ /* [in] */ IDeckLinkVideoFrame *theFrame) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE ScheduleVideoFrame(
+ /* [in] */ IDeckLinkVideoFrame *theFrame,
+ /* [in] */ BMDTimeValue displayTime,
+ /* [in] */ BMDTimeValue displayDuration,
+ /* [in] */ BMDTimeScale timeScale) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetScheduledFrameCompletionCallback(
+ /* [in] */ IDeckLinkVideoOutputCallback *theCallback) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetBufferedVideoFrameCount(
+ /* [out] */ unsigned int *bufferedFrameCount) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE EnableAudioOutput(
+ /* [in] */ BMDAudioSampleRate sampleRate,
+ /* [in] */ BMDAudioSampleType sampleType,
+ /* [in] */ unsigned int channelCount,
+ /* [in] */ BMDAudioOutputStreamType streamType) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE DisableAudioOutput( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE WriteAudioSamplesSync(
+ /* [in] */ void *buffer,
+ /* [in] */ unsigned int sampleFrameCount,
+ /* [out] */ unsigned int *sampleFramesWritten) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE BeginAudioPreroll( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE EndAudioPreroll( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE ScheduleAudioSamples(
+ /* [in] */ void *buffer,
+ /* [in] */ unsigned int sampleFrameCount,
+ /* [in] */ BMDTimeValue streamTime,
+ /* [in] */ BMDTimeScale timeScale,
+ /* [out] */ unsigned int *sampleFramesWritten) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetBufferedAudioSampleFrameCount(
+ /* [out] */ unsigned int *bufferedSampleFrameCount) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE FlushBufferedAudioSamples( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetAudioCallback(
+ /* [in] */ IDeckLinkAudioOutputCallback *theCallback) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE StartScheduledPlayback(
+ /* [in] */ BMDTimeValue playbackStartTime,
+ /* [in] */ BMDTimeScale timeScale,
+ /* [in] */ double playbackSpeed) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE StopScheduledPlayback(
+ /* [in] */ BMDTimeValue stopPlaybackAtTime,
+ /* [out] */ BMDTimeValue *actualStopTime,
+ /* [in] */ BMDTimeScale timeScale) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE IsScheduledPlaybackRunning(
+ /* [out] */ BOOL *active) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetScheduledStreamTime(
+ /* [in] */ BMDTimeScale desiredTimeScale,
+ /* [out] */ BMDTimeValue *streamTime,
+ /* [out] */ double *playbackSpeed) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetReferenceStatus(
+ /* [out] */ BMDReferenceStatus *referenceStatus) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetHardwareReferenceClock(
+ /* [in] */ BMDTimeScale desiredTimeScale,
+ /* [out] */ BMDTimeValue *hardwareTime,
+ /* [out] */ BMDTimeValue *timeInFrame,
+ /* [out] */ BMDTimeValue *ticksPerFrame) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetFrameCompletionReferenceTimestamp(
+ /* [in] */ IDeckLinkVideoFrame *theFrame,
+ /* [in] */ BMDTimeScale desiredTimeScale,
+ /* [out] */ BMDTimeValue *frameCompletionTimestamp) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkOutputVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkOutput * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkOutput * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkOutput * This);
+
+ HRESULT ( STDMETHODCALLTYPE *DoesSupportVideoMode )(
+ IDeckLinkOutput * This,
+ /* [in] */ BMDDisplayMode displayMode,
+ /* [in] */ BMDPixelFormat pixelFormat,
+ /* [in] */ BMDVideoOutputFlags flags,
+ /* [out] */ BMDDisplayModeSupport *result,
+ /* [out] */ IDeckLinkDisplayMode **resultDisplayMode);
+
+ HRESULT ( STDMETHODCALLTYPE *GetDisplayModeIterator )(
+ IDeckLinkOutput * This,
+ /* [out] */ IDeckLinkDisplayModeIterator **iterator);
+
+ HRESULT ( STDMETHODCALLTYPE *SetScreenPreviewCallback )(
+ IDeckLinkOutput * This,
+ /* [in] */ IDeckLinkScreenPreviewCallback *previewCallback);
+
+ HRESULT ( STDMETHODCALLTYPE *EnableVideoOutput )(
+ IDeckLinkOutput * This,
+ /* [in] */ BMDDisplayMode displayMode,
+ /* [in] */ BMDVideoOutputFlags flags);
+
+ HRESULT ( STDMETHODCALLTYPE *DisableVideoOutput )(
+ IDeckLinkOutput * This);
+
+ HRESULT ( STDMETHODCALLTYPE *SetVideoOutputFrameMemoryAllocator )(
+ IDeckLinkOutput * This,
+ /* [in] */ IDeckLinkMemoryAllocator *theAllocator);
+
+ HRESULT ( STDMETHODCALLTYPE *CreateVideoFrame )(
+ IDeckLinkOutput * This,
+ /* [in] */ int width,
+ /* [in] */ int height,
+ /* [in] */ int rowBytes,
+ /* [in] */ BMDPixelFormat pixelFormat,
+ /* [in] */ BMDFrameFlags flags,
+ /* [out] */ IDeckLinkMutableVideoFrame **outFrame);
+
+ HRESULT ( STDMETHODCALLTYPE *CreateAncillaryData )(
+ IDeckLinkOutput * This,
+ /* [in] */ BMDPixelFormat pixelFormat,
+ /* [out] */ IDeckLinkVideoFrameAncillary **outBuffer);
+
+ HRESULT ( STDMETHODCALLTYPE *DisplayVideoFrameSync )(
+ IDeckLinkOutput * This,
+ /* [in] */ IDeckLinkVideoFrame *theFrame);
+
+ HRESULT ( STDMETHODCALLTYPE *ScheduleVideoFrame )(
+ IDeckLinkOutput * This,
+ /* [in] */ IDeckLinkVideoFrame *theFrame,
+ /* [in] */ BMDTimeValue displayTime,
+ /* [in] */ BMDTimeValue displayDuration,
+ /* [in] */ BMDTimeScale timeScale);
+
+ HRESULT ( STDMETHODCALLTYPE *SetScheduledFrameCompletionCallback )(
+ IDeckLinkOutput * This,
+ /* [in] */ IDeckLinkVideoOutputCallback *theCallback);
+
+ HRESULT ( STDMETHODCALLTYPE *GetBufferedVideoFrameCount )(
+ IDeckLinkOutput * This,
+ /* [out] */ unsigned int *bufferedFrameCount);
+
+ HRESULT ( STDMETHODCALLTYPE *EnableAudioOutput )(
+ IDeckLinkOutput * This,
+ /* [in] */ BMDAudioSampleRate sampleRate,
+ /* [in] */ BMDAudioSampleType sampleType,
+ /* [in] */ unsigned int channelCount,
+ /* [in] */ BMDAudioOutputStreamType streamType);
+
+ HRESULT ( STDMETHODCALLTYPE *DisableAudioOutput )(
+ IDeckLinkOutput * This);
+
+ HRESULT ( STDMETHODCALLTYPE *WriteAudioSamplesSync )(
+ IDeckLinkOutput * This,
+ /* [in] */ void *buffer,
+ /* [in] */ unsigned int sampleFrameCount,
+ /* [out] */ unsigned int *sampleFramesWritten);
+
+ HRESULT ( STDMETHODCALLTYPE *BeginAudioPreroll )(
+ IDeckLinkOutput * This);
+
+ HRESULT ( STDMETHODCALLTYPE *EndAudioPreroll )(
+ IDeckLinkOutput * This);
+
+ HRESULT ( STDMETHODCALLTYPE *ScheduleAudioSamples )(
+ IDeckLinkOutput * This,
+ /* [in] */ void *buffer,
+ /* [in] */ unsigned int sampleFrameCount,
+ /* [in] */ BMDTimeValue streamTime,
+ /* [in] */ BMDTimeScale timeScale,
+ /* [out] */ unsigned int *sampleFramesWritten);
+
+ HRESULT ( STDMETHODCALLTYPE *GetBufferedAudioSampleFrameCount )(
+ IDeckLinkOutput * This,
+ /* [out] */ unsigned int *bufferedSampleFrameCount);
+
+ HRESULT ( STDMETHODCALLTYPE *FlushBufferedAudioSamples )(
+ IDeckLinkOutput * This);
+
+ HRESULT ( STDMETHODCALLTYPE *SetAudioCallback )(
+ IDeckLinkOutput * This,
+ /* [in] */ IDeckLinkAudioOutputCallback *theCallback);
+
+ HRESULT ( STDMETHODCALLTYPE *StartScheduledPlayback )(
+ IDeckLinkOutput * This,
+ /* [in] */ BMDTimeValue playbackStartTime,
+ /* [in] */ BMDTimeScale timeScale,
+ /* [in] */ double playbackSpeed);
+
+ HRESULT ( STDMETHODCALLTYPE *StopScheduledPlayback )(
+ IDeckLinkOutput * This,
+ /* [in] */ BMDTimeValue stopPlaybackAtTime,
+ /* [out] */ BMDTimeValue *actualStopTime,
+ /* [in] */ BMDTimeScale timeScale);
+
+ HRESULT ( STDMETHODCALLTYPE *IsScheduledPlaybackRunning )(
+ IDeckLinkOutput * This,
+ /* [out] */ BOOL *active);
+
+ HRESULT ( STDMETHODCALLTYPE *GetScheduledStreamTime )(
+ IDeckLinkOutput * This,
+ /* [in] */ BMDTimeScale desiredTimeScale,
+ /* [out] */ BMDTimeValue *streamTime,
+ /* [out] */ double *playbackSpeed);
+
+ HRESULT ( STDMETHODCALLTYPE *GetReferenceStatus )(
+ IDeckLinkOutput * This,
+ /* [out] */ BMDReferenceStatus *referenceStatus);
+
+ HRESULT ( STDMETHODCALLTYPE *GetHardwareReferenceClock )(
+ IDeckLinkOutput * This,
+ /* [in] */ BMDTimeScale desiredTimeScale,
+ /* [out] */ BMDTimeValue *hardwareTime,
+ /* [out] */ BMDTimeValue *timeInFrame,
+ /* [out] */ BMDTimeValue *ticksPerFrame);
+
+ HRESULT ( STDMETHODCALLTYPE *GetFrameCompletionReferenceTimestamp )(
+ IDeckLinkOutput * This,
+ /* [in] */ IDeckLinkVideoFrame *theFrame,
+ /* [in] */ BMDTimeScale desiredTimeScale,
+ /* [out] */ BMDTimeValue *frameCompletionTimestamp);
+
+ END_INTERFACE
+ } IDeckLinkOutputVtbl;
+
+ interface IDeckLinkOutput
+ {
+ CONST_VTBL struct IDeckLinkOutputVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkOutput_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkOutput_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkOutput_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkOutput_DoesSupportVideoMode(This,displayMode,pixelFormat,flags,result,resultDisplayMode) \
+ ( (This)->lpVtbl -> DoesSupportVideoMode(This,displayMode,pixelFormat,flags,result,resultDisplayMode) )
+
+#define IDeckLinkOutput_GetDisplayModeIterator(This,iterator) \
+ ( (This)->lpVtbl -> GetDisplayModeIterator(This,iterator) )
+
+#define IDeckLinkOutput_SetScreenPreviewCallback(This,previewCallback) \
+ ( (This)->lpVtbl -> SetScreenPreviewCallback(This,previewCallback) )
+
+#define IDeckLinkOutput_EnableVideoOutput(This,displayMode,flags) \
+ ( (This)->lpVtbl -> EnableVideoOutput(This,displayMode,flags) )
+
+#define IDeckLinkOutput_DisableVideoOutput(This) \
+ ( (This)->lpVtbl -> DisableVideoOutput(This) )
+
+#define IDeckLinkOutput_SetVideoOutputFrameMemoryAllocator(This,theAllocator) \
+ ( (This)->lpVtbl -> SetVideoOutputFrameMemoryAllocator(This,theAllocator) )
+
+#define IDeckLinkOutput_CreateVideoFrame(This,width,height,rowBytes,pixelFormat,flags,outFrame) \
+ ( (This)->lpVtbl -> CreateVideoFrame(This,width,height,rowBytes,pixelFormat,flags,outFrame) )
+
+#define IDeckLinkOutput_CreateAncillaryData(This,pixelFormat,outBuffer) \
+ ( (This)->lpVtbl -> CreateAncillaryData(This,pixelFormat,outBuffer) )
+
+#define IDeckLinkOutput_DisplayVideoFrameSync(This,theFrame) \
+ ( (This)->lpVtbl -> DisplayVideoFrameSync(This,theFrame) )
+
+#define IDeckLinkOutput_ScheduleVideoFrame(This,theFrame,displayTime,displayDuration,timeScale) \
+ ( (This)->lpVtbl -> ScheduleVideoFrame(This,theFrame,displayTime,displayDuration,timeScale) )
+
+#define IDeckLinkOutput_SetScheduledFrameCompletionCallback(This,theCallback) \
+ ( (This)->lpVtbl -> SetScheduledFrameCompletionCallback(This,theCallback) )
+
+#define IDeckLinkOutput_GetBufferedVideoFrameCount(This,bufferedFrameCount) \
+ ( (This)->lpVtbl -> GetBufferedVideoFrameCount(This,bufferedFrameCount) )
+
+#define IDeckLinkOutput_EnableAudioOutput(This,sampleRate,sampleType,channelCount,streamType) \
+ ( (This)->lpVtbl -> EnableAudioOutput(This,sampleRate,sampleType,channelCount,streamType) )
+
+#define IDeckLinkOutput_DisableAudioOutput(This) \
+ ( (This)->lpVtbl -> DisableAudioOutput(This) )
+
+#define IDeckLinkOutput_WriteAudioSamplesSync(This,buffer,sampleFrameCount,sampleFramesWritten) \
+ ( (This)->lpVtbl -> WriteAudioSamplesSync(This,buffer,sampleFrameCount,sampleFramesWritten) )
+
+#define IDeckLinkOutput_BeginAudioPreroll(This) \
+ ( (This)->lpVtbl -> BeginAudioPreroll(This) )
+
+#define IDeckLinkOutput_EndAudioPreroll(This) \
+ ( (This)->lpVtbl -> EndAudioPreroll(This) )
+
+#define IDeckLinkOutput_ScheduleAudioSamples(This,buffer,sampleFrameCount,streamTime,timeScale,sampleFramesWritten) \
+ ( (This)->lpVtbl -> ScheduleAudioSamples(This,buffer,sampleFrameCount,streamTime,timeScale,sampleFramesWritten) )
+
+#define IDeckLinkOutput_GetBufferedAudioSampleFrameCount(This,bufferedSampleFrameCount) \
+ ( (This)->lpVtbl -> GetBufferedAudioSampleFrameCount(This,bufferedSampleFrameCount) )
+
+#define IDeckLinkOutput_FlushBufferedAudioSamples(This) \
+ ( (This)->lpVtbl -> FlushBufferedAudioSamples(This) )
+
+#define IDeckLinkOutput_SetAudioCallback(This,theCallback) \
+ ( (This)->lpVtbl -> SetAudioCallback(This,theCallback) )
+
+#define IDeckLinkOutput_StartScheduledPlayback(This,playbackStartTime,timeScale,playbackSpeed) \
+ ( (This)->lpVtbl -> StartScheduledPlayback(This,playbackStartTime,timeScale,playbackSpeed) )
+
+#define IDeckLinkOutput_StopScheduledPlayback(This,stopPlaybackAtTime,actualStopTime,timeScale) \
+ ( (This)->lpVtbl -> StopScheduledPlayback(This,stopPlaybackAtTime,actualStopTime,timeScale) )
+
+#define IDeckLinkOutput_IsScheduledPlaybackRunning(This,active) \
+ ( (This)->lpVtbl -> IsScheduledPlaybackRunning(This,active) )
+
+#define IDeckLinkOutput_GetScheduledStreamTime(This,desiredTimeScale,streamTime,playbackSpeed) \
+ ( (This)->lpVtbl -> GetScheduledStreamTime(This,desiredTimeScale,streamTime,playbackSpeed) )
+
+#define IDeckLinkOutput_GetReferenceStatus(This,referenceStatus) \
+ ( (This)->lpVtbl -> GetReferenceStatus(This,referenceStatus) )
+
+#define IDeckLinkOutput_GetHardwareReferenceClock(This,desiredTimeScale,hardwareTime,timeInFrame,ticksPerFrame) \
+ ( (This)->lpVtbl -> GetHardwareReferenceClock(This,desiredTimeScale,hardwareTime,timeInFrame,ticksPerFrame) )
+
+#define IDeckLinkOutput_GetFrameCompletionReferenceTimestamp(This,theFrame,desiredTimeScale,frameCompletionTimestamp) \
+ ( (This)->lpVtbl -> GetFrameCompletionReferenceTimestamp(This,theFrame,desiredTimeScale,frameCompletionTimestamp) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkOutput_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkInput_INTERFACE_DEFINED__
+#define __IDeckLinkInput_INTERFACE_DEFINED__
+
+/* interface IDeckLinkInput */
+/* [helpstring][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkInput;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("AF22762B-DFAC-4846-AA79-FA8883560995")
+ IDeckLinkInput : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE DoesSupportVideoMode(
+ /* [in] */ BMDDisplayMode displayMode,
+ /* [in] */ BMDPixelFormat pixelFormat,
+ /* [in] */ BMDVideoInputFlags flags,
+ /* [out] */ BMDDisplayModeSupport *result,
+ /* [out] */ IDeckLinkDisplayMode **resultDisplayMode) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetDisplayModeIterator(
+ /* [out] */ IDeckLinkDisplayModeIterator **iterator) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetScreenPreviewCallback(
+ /* [in] */ IDeckLinkScreenPreviewCallback *previewCallback) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE EnableVideoInput(
+ /* [in] */ BMDDisplayMode displayMode,
+ /* [in] */ BMDPixelFormat pixelFormat,
+ /* [in] */ BMDVideoInputFlags flags) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE DisableVideoInput( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetAvailableVideoFrameCount(
+ /* [out] */ unsigned int *availableFrameCount) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetVideoInputFrameMemoryAllocator(
+ /* [in] */ IDeckLinkMemoryAllocator *theAllocator) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE EnableAudioInput(
+ /* [in] */ BMDAudioSampleRate sampleRate,
+ /* [in] */ BMDAudioSampleType sampleType,
+ /* [in] */ unsigned int channelCount) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE DisableAudioInput( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetAvailableAudioSampleFrameCount(
+ /* [out] */ unsigned int *availableSampleFrameCount) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE StartStreams( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE StopStreams( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE PauseStreams( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE FlushStreams( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetCallback(
+ /* [in] */ IDeckLinkInputCallback *theCallback) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetHardwareReferenceClock(
+ /* [in] */ BMDTimeScale desiredTimeScale,
+ /* [out] */ BMDTimeValue *hardwareTime,
+ /* [out] */ BMDTimeValue *timeInFrame,
+ /* [out] */ BMDTimeValue *ticksPerFrame) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkInputVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkInput * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkInput * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkInput * This);
+
+ HRESULT ( STDMETHODCALLTYPE *DoesSupportVideoMode )(
+ IDeckLinkInput * This,
+ /* [in] */ BMDDisplayMode displayMode,
+ /* [in] */ BMDPixelFormat pixelFormat,
+ /* [in] */ BMDVideoInputFlags flags,
+ /* [out] */ BMDDisplayModeSupport *result,
+ /* [out] */ IDeckLinkDisplayMode **resultDisplayMode);
+
+ HRESULT ( STDMETHODCALLTYPE *GetDisplayModeIterator )(
+ IDeckLinkInput * This,
+ /* [out] */ IDeckLinkDisplayModeIterator **iterator);
+
+ HRESULT ( STDMETHODCALLTYPE *SetScreenPreviewCallback )(
+ IDeckLinkInput * This,
+ /* [in] */ IDeckLinkScreenPreviewCallback *previewCallback);
+
+ HRESULT ( STDMETHODCALLTYPE *EnableVideoInput )(
+ IDeckLinkInput * This,
+ /* [in] */ BMDDisplayMode displayMode,
+ /* [in] */ BMDPixelFormat pixelFormat,
+ /* [in] */ BMDVideoInputFlags flags);
+
+ HRESULT ( STDMETHODCALLTYPE *DisableVideoInput )(
+ IDeckLinkInput * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetAvailableVideoFrameCount )(
+ IDeckLinkInput * This,
+ /* [out] */ unsigned int *availableFrameCount);
+
+ HRESULT ( STDMETHODCALLTYPE *SetVideoInputFrameMemoryAllocator )(
+ IDeckLinkInput * This,
+ /* [in] */ IDeckLinkMemoryAllocator *theAllocator);
+
+ HRESULT ( STDMETHODCALLTYPE *EnableAudioInput )(
+ IDeckLinkInput * This,
+ /* [in] */ BMDAudioSampleRate sampleRate,
+ /* [in] */ BMDAudioSampleType sampleType,
+ /* [in] */ unsigned int channelCount);
+
+ HRESULT ( STDMETHODCALLTYPE *DisableAudioInput )(
+ IDeckLinkInput * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetAvailableAudioSampleFrameCount )(
+ IDeckLinkInput * This,
+ /* [out] */ unsigned int *availableSampleFrameCount);
+
+ HRESULT ( STDMETHODCALLTYPE *StartStreams )(
+ IDeckLinkInput * This);
+
+ HRESULT ( STDMETHODCALLTYPE *StopStreams )(
+ IDeckLinkInput * This);
+
+ HRESULT ( STDMETHODCALLTYPE *PauseStreams )(
+ IDeckLinkInput * This);
+
+ HRESULT ( STDMETHODCALLTYPE *FlushStreams )(
+ IDeckLinkInput * This);
+
+ HRESULT ( STDMETHODCALLTYPE *SetCallback )(
+ IDeckLinkInput * This,
+ /* [in] */ IDeckLinkInputCallback *theCallback);
+
+ HRESULT ( STDMETHODCALLTYPE *GetHardwareReferenceClock )(
+ IDeckLinkInput * This,
+ /* [in] */ BMDTimeScale desiredTimeScale,
+ /* [out] */ BMDTimeValue *hardwareTime,
+ /* [out] */ BMDTimeValue *timeInFrame,
+ /* [out] */ BMDTimeValue *ticksPerFrame);
+
+ END_INTERFACE
+ } IDeckLinkInputVtbl;
+
+ interface IDeckLinkInput
+ {
+ CONST_VTBL struct IDeckLinkInputVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkInput_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkInput_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkInput_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkInput_DoesSupportVideoMode(This,displayMode,pixelFormat,flags,result,resultDisplayMode) \
+ ( (This)->lpVtbl -> DoesSupportVideoMode(This,displayMode,pixelFormat,flags,result,resultDisplayMode) )
+
+#define IDeckLinkInput_GetDisplayModeIterator(This,iterator) \
+ ( (This)->lpVtbl -> GetDisplayModeIterator(This,iterator) )
+
+#define IDeckLinkInput_SetScreenPreviewCallback(This,previewCallback) \
+ ( (This)->lpVtbl -> SetScreenPreviewCallback(This,previewCallback) )
+
+#define IDeckLinkInput_EnableVideoInput(This,displayMode,pixelFormat,flags) \
+ ( (This)->lpVtbl -> EnableVideoInput(This,displayMode,pixelFormat,flags) )
+
+#define IDeckLinkInput_DisableVideoInput(This) \
+ ( (This)->lpVtbl -> DisableVideoInput(This) )
+
+#define IDeckLinkInput_GetAvailableVideoFrameCount(This,availableFrameCount) \
+ ( (This)->lpVtbl -> GetAvailableVideoFrameCount(This,availableFrameCount) )
+
+#define IDeckLinkInput_SetVideoInputFrameMemoryAllocator(This,theAllocator) \
+ ( (This)->lpVtbl -> SetVideoInputFrameMemoryAllocator(This,theAllocator) )
+
+#define IDeckLinkInput_EnableAudioInput(This,sampleRate,sampleType,channelCount) \
+ ( (This)->lpVtbl -> EnableAudioInput(This,sampleRate,sampleType,channelCount) )
+
+#define IDeckLinkInput_DisableAudioInput(This) \
+ ( (This)->lpVtbl -> DisableAudioInput(This) )
+
+#define IDeckLinkInput_GetAvailableAudioSampleFrameCount(This,availableSampleFrameCount) \
+ ( (This)->lpVtbl -> GetAvailableAudioSampleFrameCount(This,availableSampleFrameCount) )
+
+#define IDeckLinkInput_StartStreams(This) \
+ ( (This)->lpVtbl -> StartStreams(This) )
+
+#define IDeckLinkInput_StopStreams(This) \
+ ( (This)->lpVtbl -> StopStreams(This) )
+
+#define IDeckLinkInput_PauseStreams(This) \
+ ( (This)->lpVtbl -> PauseStreams(This) )
+
+#define IDeckLinkInput_FlushStreams(This) \
+ ( (This)->lpVtbl -> FlushStreams(This) )
+
+#define IDeckLinkInput_SetCallback(This,theCallback) \
+ ( (This)->lpVtbl -> SetCallback(This,theCallback) )
+
+#define IDeckLinkInput_GetHardwareReferenceClock(This,desiredTimeScale,hardwareTime,timeInFrame,ticksPerFrame) \
+ ( (This)->lpVtbl -> GetHardwareReferenceClock(This,desiredTimeScale,hardwareTime,timeInFrame,ticksPerFrame) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkInput_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkVideoFrame_INTERFACE_DEFINED__
+#define __IDeckLinkVideoFrame_INTERFACE_DEFINED__
+
+/* interface IDeckLinkVideoFrame */
+/* [helpstring][local][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkVideoFrame;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("3F716FE0-F023-4111-BE5D-EF4414C05B17")
+ IDeckLinkVideoFrame : public IUnknown
+ {
+ public:
+ virtual long STDMETHODCALLTYPE GetWidth( void) = 0;
+
+ virtual long STDMETHODCALLTYPE GetHeight( void) = 0;
+
+ virtual long STDMETHODCALLTYPE GetRowBytes( void) = 0;
+
+ virtual BMDPixelFormat STDMETHODCALLTYPE GetPixelFormat( void) = 0;
+
+ virtual BMDFrameFlags STDMETHODCALLTYPE GetFlags( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetBytes(
+ /* [out] */ void **buffer) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetTimecode(
+ /* [in] */ BMDTimecodeFormat format,
+ /* [out] */ IDeckLinkTimecode **timecode) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetAncillaryData(
+ /* [out] */ IDeckLinkVideoFrameAncillary **ancillary) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkVideoFrameVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkVideoFrame * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkVideoFrame * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkVideoFrame * This);
+
+ long ( STDMETHODCALLTYPE *GetWidth )(
+ IDeckLinkVideoFrame * This);
+
+ long ( STDMETHODCALLTYPE *GetHeight )(
+ IDeckLinkVideoFrame * This);
+
+ long ( STDMETHODCALLTYPE *GetRowBytes )(
+ IDeckLinkVideoFrame * This);
+
+ BMDPixelFormat ( STDMETHODCALLTYPE *GetPixelFormat )(
+ IDeckLinkVideoFrame * This);
+
+ BMDFrameFlags ( STDMETHODCALLTYPE *GetFlags )(
+ IDeckLinkVideoFrame * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetBytes )(
+ IDeckLinkVideoFrame * This,
+ /* [out] */ void **buffer);
+
+ HRESULT ( STDMETHODCALLTYPE *GetTimecode )(
+ IDeckLinkVideoFrame * This,
+ /* [in] */ BMDTimecodeFormat format,
+ /* [out] */ IDeckLinkTimecode **timecode);
+
+ HRESULT ( STDMETHODCALLTYPE *GetAncillaryData )(
+ IDeckLinkVideoFrame * This,
+ /* [out] */ IDeckLinkVideoFrameAncillary **ancillary);
+
+ END_INTERFACE
+ } IDeckLinkVideoFrameVtbl;
+
+ interface IDeckLinkVideoFrame
+ {
+ CONST_VTBL struct IDeckLinkVideoFrameVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkVideoFrame_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkVideoFrame_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkVideoFrame_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkVideoFrame_GetWidth(This) \
+ ( (This)->lpVtbl -> GetWidth(This) )
+
+#define IDeckLinkVideoFrame_GetHeight(This) \
+ ( (This)->lpVtbl -> GetHeight(This) )
+
+#define IDeckLinkVideoFrame_GetRowBytes(This) \
+ ( (This)->lpVtbl -> GetRowBytes(This) )
+
+#define IDeckLinkVideoFrame_GetPixelFormat(This) \
+ ( (This)->lpVtbl -> GetPixelFormat(This) )
+
+#define IDeckLinkVideoFrame_GetFlags(This) \
+ ( (This)->lpVtbl -> GetFlags(This) )
+
+#define IDeckLinkVideoFrame_GetBytes(This,buffer) \
+ ( (This)->lpVtbl -> GetBytes(This,buffer) )
+
+#define IDeckLinkVideoFrame_GetTimecode(This,format,timecode) \
+ ( (This)->lpVtbl -> GetTimecode(This,format,timecode) )
+
+#define IDeckLinkVideoFrame_GetAncillaryData(This,ancillary) \
+ ( (This)->lpVtbl -> GetAncillaryData(This,ancillary) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkVideoFrame_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkMutableVideoFrame_INTERFACE_DEFINED__
+#define __IDeckLinkMutableVideoFrame_INTERFACE_DEFINED__
+
+/* interface IDeckLinkMutableVideoFrame */
+/* [helpstring][local][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkMutableVideoFrame;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("69E2639F-40DA-4E19-B6F2-20ACE815C390")
+ IDeckLinkMutableVideoFrame : public IDeckLinkVideoFrame
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE SetFlags(
+ /* [in] */ BMDFrameFlags newFlags) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetTimecode(
+ /* [in] */ BMDTimecodeFormat format,
+ /* [in] */ IDeckLinkTimecode *timecode) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetTimecodeFromComponents(
+ /* [in] */ BMDTimecodeFormat format,
+ /* [in] */ unsigned char hours,
+ /* [in] */ unsigned char minutes,
+ /* [in] */ unsigned char seconds,
+ /* [in] */ unsigned char frames,
+ /* [in] */ BMDTimecodeFlags flags) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetAncillaryData(
+ /* [in] */ IDeckLinkVideoFrameAncillary *ancillary) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetTimecodeUserBits(
+ /* [in] */ BMDTimecodeFormat format,
+ /* [in] */ BMDTimecodeUserBits userBits) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkMutableVideoFrameVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkMutableVideoFrame * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkMutableVideoFrame * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkMutableVideoFrame * This);
+
+ long ( STDMETHODCALLTYPE *GetWidth )(
+ IDeckLinkMutableVideoFrame * This);
+
+ long ( STDMETHODCALLTYPE *GetHeight )(
+ IDeckLinkMutableVideoFrame * This);
+
+ long ( STDMETHODCALLTYPE *GetRowBytes )(
+ IDeckLinkMutableVideoFrame * This);
+
+ BMDPixelFormat ( STDMETHODCALLTYPE *GetPixelFormat )(
+ IDeckLinkMutableVideoFrame * This);
+
+ BMDFrameFlags ( STDMETHODCALLTYPE *GetFlags )(
+ IDeckLinkMutableVideoFrame * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetBytes )(
+ IDeckLinkMutableVideoFrame * This,
+ /* [out] */ void **buffer);
+
+ HRESULT ( STDMETHODCALLTYPE *GetTimecode )(
+ IDeckLinkMutableVideoFrame * This,
+ /* [in] */ BMDTimecodeFormat format,
+ /* [out] */ IDeckLinkTimecode **timecode);
+
+ HRESULT ( STDMETHODCALLTYPE *GetAncillaryData )(
+ IDeckLinkMutableVideoFrame * This,
+ /* [out] */ IDeckLinkVideoFrameAncillary **ancillary);
+
+ HRESULT ( STDMETHODCALLTYPE *SetFlags )(
+ IDeckLinkMutableVideoFrame * This,
+ /* [in] */ BMDFrameFlags newFlags);
+
+ HRESULT ( STDMETHODCALLTYPE *SetTimecode )(
+ IDeckLinkMutableVideoFrame * This,
+ /* [in] */ BMDTimecodeFormat format,
+ /* [in] */ IDeckLinkTimecode *timecode);
+
+ HRESULT ( STDMETHODCALLTYPE *SetTimecodeFromComponents )(
+ IDeckLinkMutableVideoFrame * This,
+ /* [in] */ BMDTimecodeFormat format,
+ /* [in] */ unsigned char hours,
+ /* [in] */ unsigned char minutes,
+ /* [in] */ unsigned char seconds,
+ /* [in] */ unsigned char frames,
+ /* [in] */ BMDTimecodeFlags flags);
+
+ HRESULT ( STDMETHODCALLTYPE *SetAncillaryData )(
+ IDeckLinkMutableVideoFrame * This,
+ /* [in] */ IDeckLinkVideoFrameAncillary *ancillary);
+
+ HRESULT ( STDMETHODCALLTYPE *SetTimecodeUserBits )(
+ IDeckLinkMutableVideoFrame * This,
+ /* [in] */ BMDTimecodeFormat format,
+ /* [in] */ BMDTimecodeUserBits userBits);
+
+ END_INTERFACE
+ } IDeckLinkMutableVideoFrameVtbl;
+
+ interface IDeckLinkMutableVideoFrame
+ {
+ CONST_VTBL struct IDeckLinkMutableVideoFrameVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkMutableVideoFrame_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkMutableVideoFrame_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkMutableVideoFrame_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkMutableVideoFrame_GetWidth(This) \
+ ( (This)->lpVtbl -> GetWidth(This) )
+
+#define IDeckLinkMutableVideoFrame_GetHeight(This) \
+ ( (This)->lpVtbl -> GetHeight(This) )
+
+#define IDeckLinkMutableVideoFrame_GetRowBytes(This) \
+ ( (This)->lpVtbl -> GetRowBytes(This) )
+
+#define IDeckLinkMutableVideoFrame_GetPixelFormat(This) \
+ ( (This)->lpVtbl -> GetPixelFormat(This) )
+
+#define IDeckLinkMutableVideoFrame_GetFlags(This) \
+ ( (This)->lpVtbl -> GetFlags(This) )
+
+#define IDeckLinkMutableVideoFrame_GetBytes(This,buffer) \
+ ( (This)->lpVtbl -> GetBytes(This,buffer) )
+
+#define IDeckLinkMutableVideoFrame_GetTimecode(This,format,timecode) \
+ ( (This)->lpVtbl -> GetTimecode(This,format,timecode) )
+
+#define IDeckLinkMutableVideoFrame_GetAncillaryData(This,ancillary) \
+ ( (This)->lpVtbl -> GetAncillaryData(This,ancillary) )
+
+
+#define IDeckLinkMutableVideoFrame_SetFlags(This,newFlags) \
+ ( (This)->lpVtbl -> SetFlags(This,newFlags) )
+
+#define IDeckLinkMutableVideoFrame_SetTimecode(This,format,timecode) \
+ ( (This)->lpVtbl -> SetTimecode(This,format,timecode) )
+
+#define IDeckLinkMutableVideoFrame_SetTimecodeFromComponents(This,format,hours,minutes,seconds,frames,flags) \
+ ( (This)->lpVtbl -> SetTimecodeFromComponents(This,format,hours,minutes,seconds,frames,flags) )
+
+#define IDeckLinkMutableVideoFrame_SetAncillaryData(This,ancillary) \
+ ( (This)->lpVtbl -> SetAncillaryData(This,ancillary) )
+
+#define IDeckLinkMutableVideoFrame_SetTimecodeUserBits(This,format,userBits) \
+ ( (This)->lpVtbl -> SetTimecodeUserBits(This,format,userBits) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkMutableVideoFrame_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkVideoFrame3DExtensions_INTERFACE_DEFINED__
+#define __IDeckLinkVideoFrame3DExtensions_INTERFACE_DEFINED__
+
+/* interface IDeckLinkVideoFrame3DExtensions */
+/* [helpstring][local][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkVideoFrame3DExtensions;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("DA0F7E4A-EDC7-48A8-9CDD-2DB51C729CD7")
+ IDeckLinkVideoFrame3DExtensions : public IUnknown
+ {
+ public:
+ virtual BMDVideo3DPackingFormat STDMETHODCALLTYPE Get3DPackingFormat( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetFrameForRightEye(
+ /* [out] */ IDeckLinkVideoFrame **rightEyeFrame) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkVideoFrame3DExtensionsVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkVideoFrame3DExtensions * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkVideoFrame3DExtensions * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkVideoFrame3DExtensions * This);
+
+ BMDVideo3DPackingFormat ( STDMETHODCALLTYPE *Get3DPackingFormat )(
+ IDeckLinkVideoFrame3DExtensions * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetFrameForRightEye )(
+ IDeckLinkVideoFrame3DExtensions * This,
+ /* [out] */ IDeckLinkVideoFrame **rightEyeFrame);
+
+ END_INTERFACE
+ } IDeckLinkVideoFrame3DExtensionsVtbl;
+
+ interface IDeckLinkVideoFrame3DExtensions
+ {
+ CONST_VTBL struct IDeckLinkVideoFrame3DExtensionsVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkVideoFrame3DExtensions_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkVideoFrame3DExtensions_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkVideoFrame3DExtensions_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkVideoFrame3DExtensions_Get3DPackingFormat(This) \
+ ( (This)->lpVtbl -> Get3DPackingFormat(This) )
+
+#define IDeckLinkVideoFrame3DExtensions_GetFrameForRightEye(This,rightEyeFrame) \
+ ( (This)->lpVtbl -> GetFrameForRightEye(This,rightEyeFrame) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkVideoFrame3DExtensions_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkVideoInputFrame_INTERFACE_DEFINED__
+#define __IDeckLinkVideoInputFrame_INTERFACE_DEFINED__
+
+/* interface IDeckLinkVideoInputFrame */
+/* [helpstring][local][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkVideoInputFrame;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("05CFE374-537C-4094-9A57-680525118F44")
+ IDeckLinkVideoInputFrame : public IDeckLinkVideoFrame
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE GetStreamTime(
+ /* [out] */ BMDTimeValue *frameTime,
+ /* [out] */ BMDTimeValue *frameDuration,
+ /* [in] */ BMDTimeScale timeScale) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetHardwareReferenceTimestamp(
+ /* [in] */ BMDTimeScale timeScale,
+ /* [out] */ BMDTimeValue *frameTime,
+ /* [out] */ BMDTimeValue *frameDuration) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkVideoInputFrameVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkVideoInputFrame * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkVideoInputFrame * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkVideoInputFrame * This);
+
+ long ( STDMETHODCALLTYPE *GetWidth )(
+ IDeckLinkVideoInputFrame * This);
+
+ long ( STDMETHODCALLTYPE *GetHeight )(
+ IDeckLinkVideoInputFrame * This);
+
+ long ( STDMETHODCALLTYPE *GetRowBytes )(
+ IDeckLinkVideoInputFrame * This);
+
+ BMDPixelFormat ( STDMETHODCALLTYPE *GetPixelFormat )(
+ IDeckLinkVideoInputFrame * This);
+
+ BMDFrameFlags ( STDMETHODCALLTYPE *GetFlags )(
+ IDeckLinkVideoInputFrame * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetBytes )(
+ IDeckLinkVideoInputFrame * This,
+ /* [out] */ void **buffer);
+
+ HRESULT ( STDMETHODCALLTYPE *GetTimecode )(
+ IDeckLinkVideoInputFrame * This,
+ /* [in] */ BMDTimecodeFormat format,
+ /* [out] */ IDeckLinkTimecode **timecode);
+
+ HRESULT ( STDMETHODCALLTYPE *GetAncillaryData )(
+ IDeckLinkVideoInputFrame * This,
+ /* [out] */ IDeckLinkVideoFrameAncillary **ancillary);
+
+ HRESULT ( STDMETHODCALLTYPE *GetStreamTime )(
+ IDeckLinkVideoInputFrame * This,
+ /* [out] */ BMDTimeValue *frameTime,
+ /* [out] */ BMDTimeValue *frameDuration,
+ /* [in] */ BMDTimeScale timeScale);
+
+ HRESULT ( STDMETHODCALLTYPE *GetHardwareReferenceTimestamp )(
+ IDeckLinkVideoInputFrame * This,
+ /* [in] */ BMDTimeScale timeScale,
+ /* [out] */ BMDTimeValue *frameTime,
+ /* [out] */ BMDTimeValue *frameDuration);
+
+ END_INTERFACE
+ } IDeckLinkVideoInputFrameVtbl;
+
+ interface IDeckLinkVideoInputFrame
+ {
+ CONST_VTBL struct IDeckLinkVideoInputFrameVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkVideoInputFrame_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkVideoInputFrame_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkVideoInputFrame_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkVideoInputFrame_GetWidth(This) \
+ ( (This)->lpVtbl -> GetWidth(This) )
+
+#define IDeckLinkVideoInputFrame_GetHeight(This) \
+ ( (This)->lpVtbl -> GetHeight(This) )
+
+#define IDeckLinkVideoInputFrame_GetRowBytes(This) \
+ ( (This)->lpVtbl -> GetRowBytes(This) )
+
+#define IDeckLinkVideoInputFrame_GetPixelFormat(This) \
+ ( (This)->lpVtbl -> GetPixelFormat(This) )
+
+#define IDeckLinkVideoInputFrame_GetFlags(This) \
+ ( (This)->lpVtbl -> GetFlags(This) )
+
+#define IDeckLinkVideoInputFrame_GetBytes(This,buffer) \
+ ( (This)->lpVtbl -> GetBytes(This,buffer) )
+
+#define IDeckLinkVideoInputFrame_GetTimecode(This,format,timecode) \
+ ( (This)->lpVtbl -> GetTimecode(This,format,timecode) )
+
+#define IDeckLinkVideoInputFrame_GetAncillaryData(This,ancillary) \
+ ( (This)->lpVtbl -> GetAncillaryData(This,ancillary) )
+
+
+#define IDeckLinkVideoInputFrame_GetStreamTime(This,frameTime,frameDuration,timeScale) \
+ ( (This)->lpVtbl -> GetStreamTime(This,frameTime,frameDuration,timeScale) )
+
+#define IDeckLinkVideoInputFrame_GetHardwareReferenceTimestamp(This,timeScale,frameTime,frameDuration) \
+ ( (This)->lpVtbl -> GetHardwareReferenceTimestamp(This,timeScale,frameTime,frameDuration) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkVideoInputFrame_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkVideoFrameAncillary_INTERFACE_DEFINED__
+#define __IDeckLinkVideoFrameAncillary_INTERFACE_DEFINED__
+
+/* interface IDeckLinkVideoFrameAncillary */
+/* [helpstring][local][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkVideoFrameAncillary;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("732E723C-D1A4-4E29-9E8E-4A88797A0004")
+ IDeckLinkVideoFrameAncillary : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE GetBufferForVerticalBlankingLine(
+ /* [in] */ unsigned int lineNumber,
+ /* [out] */ void **buffer) = 0;
+
+ virtual BMDPixelFormat STDMETHODCALLTYPE GetPixelFormat( void) = 0;
+
+ virtual BMDDisplayMode STDMETHODCALLTYPE GetDisplayMode( void) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkVideoFrameAncillaryVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkVideoFrameAncillary * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkVideoFrameAncillary * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkVideoFrameAncillary * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetBufferForVerticalBlankingLine )(
+ IDeckLinkVideoFrameAncillary * This,
+ /* [in] */ unsigned int lineNumber,
+ /* [out] */ void **buffer);
+
+ BMDPixelFormat ( STDMETHODCALLTYPE *GetPixelFormat )(
+ IDeckLinkVideoFrameAncillary * This);
+
+ BMDDisplayMode ( STDMETHODCALLTYPE *GetDisplayMode )(
+ IDeckLinkVideoFrameAncillary * This);
+
+ END_INTERFACE
+ } IDeckLinkVideoFrameAncillaryVtbl;
+
+ interface IDeckLinkVideoFrameAncillary
+ {
+ CONST_VTBL struct IDeckLinkVideoFrameAncillaryVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkVideoFrameAncillary_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkVideoFrameAncillary_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkVideoFrameAncillary_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkVideoFrameAncillary_GetBufferForVerticalBlankingLine(This,lineNumber,buffer) \
+ ( (This)->lpVtbl -> GetBufferForVerticalBlankingLine(This,lineNumber,buffer) )
+
+#define IDeckLinkVideoFrameAncillary_GetPixelFormat(This) \
+ ( (This)->lpVtbl -> GetPixelFormat(This) )
+
+#define IDeckLinkVideoFrameAncillary_GetDisplayMode(This) \
+ ( (This)->lpVtbl -> GetDisplayMode(This) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkVideoFrameAncillary_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkAudioInputPacket_INTERFACE_DEFINED__
+#define __IDeckLinkAudioInputPacket_INTERFACE_DEFINED__
+
+/* interface IDeckLinkAudioInputPacket */
+/* [helpstring][local][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkAudioInputPacket;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("E43D5870-2894-11DE-8C30-0800200C9A66")
+ IDeckLinkAudioInputPacket : public IUnknown
+ {
+ public:
+ virtual long STDMETHODCALLTYPE GetSampleFrameCount( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetBytes(
+ /* [out] */ void **buffer) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetPacketTime(
+ /* [out] */ BMDTimeValue *packetTime,
+ /* [in] */ BMDTimeScale timeScale) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkAudioInputPacketVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkAudioInputPacket * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkAudioInputPacket * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkAudioInputPacket * This);
+
+ long ( STDMETHODCALLTYPE *GetSampleFrameCount )(
+ IDeckLinkAudioInputPacket * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetBytes )(
+ IDeckLinkAudioInputPacket * This,
+ /* [out] */ void **buffer);
+
+ HRESULT ( STDMETHODCALLTYPE *GetPacketTime )(
+ IDeckLinkAudioInputPacket * This,
+ /* [out] */ BMDTimeValue *packetTime,
+ /* [in] */ BMDTimeScale timeScale);
+
+ END_INTERFACE
+ } IDeckLinkAudioInputPacketVtbl;
+
+ interface IDeckLinkAudioInputPacket
+ {
+ CONST_VTBL struct IDeckLinkAudioInputPacketVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkAudioInputPacket_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkAudioInputPacket_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkAudioInputPacket_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkAudioInputPacket_GetSampleFrameCount(This) \
+ ( (This)->lpVtbl -> GetSampleFrameCount(This) )
+
+#define IDeckLinkAudioInputPacket_GetBytes(This,buffer) \
+ ( (This)->lpVtbl -> GetBytes(This,buffer) )
+
+#define IDeckLinkAudioInputPacket_GetPacketTime(This,packetTime,timeScale) \
+ ( (This)->lpVtbl -> GetPacketTime(This,packetTime,timeScale) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkAudioInputPacket_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkScreenPreviewCallback_INTERFACE_DEFINED__
+#define __IDeckLinkScreenPreviewCallback_INTERFACE_DEFINED__
+
+/* interface IDeckLinkScreenPreviewCallback */
+/* [helpstring][local][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkScreenPreviewCallback;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("B1D3F49A-85FE-4C5D-95C8-0B5D5DCCD438")
+ IDeckLinkScreenPreviewCallback : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE DrawFrame(
+ /* [in] */ IDeckLinkVideoFrame *theFrame) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkScreenPreviewCallbackVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkScreenPreviewCallback * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkScreenPreviewCallback * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkScreenPreviewCallback * This);
+
+ HRESULT ( STDMETHODCALLTYPE *DrawFrame )(
+ IDeckLinkScreenPreviewCallback * This,
+ /* [in] */ IDeckLinkVideoFrame *theFrame);
+
+ END_INTERFACE
+ } IDeckLinkScreenPreviewCallbackVtbl;
+
+ interface IDeckLinkScreenPreviewCallback
+ {
+ CONST_VTBL struct IDeckLinkScreenPreviewCallbackVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkScreenPreviewCallback_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkScreenPreviewCallback_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkScreenPreviewCallback_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkScreenPreviewCallback_DrawFrame(This,theFrame) \
+ ( (This)->lpVtbl -> DrawFrame(This,theFrame) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkScreenPreviewCallback_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkGLScreenPreviewHelper_INTERFACE_DEFINED__
+#define __IDeckLinkGLScreenPreviewHelper_INTERFACE_DEFINED__
+
+/* interface IDeckLinkGLScreenPreviewHelper */
+/* [helpstring][local][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkGLScreenPreviewHelper;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("504E2209-CAC7-4C1A-9FB4-C5BB6274D22F")
+ IDeckLinkGLScreenPreviewHelper : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE InitializeGL( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE PaintGL( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetFrame(
+ /* [in] */ IDeckLinkVideoFrame *theFrame) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Set3DPreviewFormat(
+ /* [in] */ BMD3DPreviewFormat previewFormat) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkGLScreenPreviewHelperVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkGLScreenPreviewHelper * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkGLScreenPreviewHelper * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkGLScreenPreviewHelper * This);
+
+ HRESULT ( STDMETHODCALLTYPE *InitializeGL )(
+ IDeckLinkGLScreenPreviewHelper * This);
+
+ HRESULT ( STDMETHODCALLTYPE *PaintGL )(
+ IDeckLinkGLScreenPreviewHelper * This);
+
+ HRESULT ( STDMETHODCALLTYPE *SetFrame )(
+ IDeckLinkGLScreenPreviewHelper * This,
+ /* [in] */ IDeckLinkVideoFrame *theFrame);
+
+ HRESULT ( STDMETHODCALLTYPE *Set3DPreviewFormat )(
+ IDeckLinkGLScreenPreviewHelper * This,
+ /* [in] */ BMD3DPreviewFormat previewFormat);
+
+ END_INTERFACE
+ } IDeckLinkGLScreenPreviewHelperVtbl;
+
+ interface IDeckLinkGLScreenPreviewHelper
+ {
+ CONST_VTBL struct IDeckLinkGLScreenPreviewHelperVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkGLScreenPreviewHelper_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkGLScreenPreviewHelper_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkGLScreenPreviewHelper_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkGLScreenPreviewHelper_InitializeGL(This) \
+ ( (This)->lpVtbl -> InitializeGL(This) )
+
+#define IDeckLinkGLScreenPreviewHelper_PaintGL(This) \
+ ( (This)->lpVtbl -> PaintGL(This) )
+
+#define IDeckLinkGLScreenPreviewHelper_SetFrame(This,theFrame) \
+ ( (This)->lpVtbl -> SetFrame(This,theFrame) )
+
+#define IDeckLinkGLScreenPreviewHelper_Set3DPreviewFormat(This,previewFormat) \
+ ( (This)->lpVtbl -> Set3DPreviewFormat(This,previewFormat) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkGLScreenPreviewHelper_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkDX9ScreenPreviewHelper_INTERFACE_DEFINED__
+#define __IDeckLinkDX9ScreenPreviewHelper_INTERFACE_DEFINED__
+
+/* interface IDeckLinkDX9ScreenPreviewHelper */
+/* [helpstring][local][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkDX9ScreenPreviewHelper;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("2094B522-D1A1-40C0-9AC7-1C012218EF02")
+ IDeckLinkDX9ScreenPreviewHelper : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Initialize(
+ /* [in] */ void *device) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Render(
+ /* [in] */ RECT *rc) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetFrame(
+ /* [in] */ IDeckLinkVideoFrame *theFrame) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Set3DPreviewFormat(
+ /* [in] */ BMD3DPreviewFormat previewFormat) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkDX9ScreenPreviewHelperVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkDX9ScreenPreviewHelper * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkDX9ScreenPreviewHelper * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkDX9ScreenPreviewHelper * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Initialize )(
+ IDeckLinkDX9ScreenPreviewHelper * This,
+ /* [in] */ void *device);
+
+ HRESULT ( STDMETHODCALLTYPE *Render )(
+ IDeckLinkDX9ScreenPreviewHelper * This,
+ /* [in] */ RECT *rc);
+
+ HRESULT ( STDMETHODCALLTYPE *SetFrame )(
+ IDeckLinkDX9ScreenPreviewHelper * This,
+ /* [in] */ IDeckLinkVideoFrame *theFrame);
+
+ HRESULT ( STDMETHODCALLTYPE *Set3DPreviewFormat )(
+ IDeckLinkDX9ScreenPreviewHelper * This,
+ /* [in] */ BMD3DPreviewFormat previewFormat);
+
+ END_INTERFACE
+ } IDeckLinkDX9ScreenPreviewHelperVtbl;
+
+ interface IDeckLinkDX9ScreenPreviewHelper
+ {
+ CONST_VTBL struct IDeckLinkDX9ScreenPreviewHelperVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkDX9ScreenPreviewHelper_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkDX9ScreenPreviewHelper_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkDX9ScreenPreviewHelper_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkDX9ScreenPreviewHelper_Initialize(This,device) \
+ ( (This)->lpVtbl -> Initialize(This,device) )
+
+#define IDeckLinkDX9ScreenPreviewHelper_Render(This,rc) \
+ ( (This)->lpVtbl -> Render(This,rc) )
+
+#define IDeckLinkDX9ScreenPreviewHelper_SetFrame(This,theFrame) \
+ ( (This)->lpVtbl -> SetFrame(This,theFrame) )
+
+#define IDeckLinkDX9ScreenPreviewHelper_Set3DPreviewFormat(This,previewFormat) \
+ ( (This)->lpVtbl -> Set3DPreviewFormat(This,previewFormat) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkDX9ScreenPreviewHelper_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkNotificationCallback_INTERFACE_DEFINED__
+#define __IDeckLinkNotificationCallback_INTERFACE_DEFINED__
+
+/* interface IDeckLinkNotificationCallback */
+/* [helpstring][local][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkNotificationCallback;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("b002a1ec-070d-4288-8289-bd5d36e5ff0d")
+ IDeckLinkNotificationCallback : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Notify(
+ /* [in] */ BMDNotifications topic,
+ /* [in] */ ULONGLONG param1,
+ /* [in] */ ULONGLONG param2) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkNotificationCallbackVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkNotificationCallback * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkNotificationCallback * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkNotificationCallback * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Notify )(
+ IDeckLinkNotificationCallback * This,
+ /* [in] */ BMDNotifications topic,
+ /* [in] */ ULONGLONG param1,
+ /* [in] */ ULONGLONG param2);
+
+ END_INTERFACE
+ } IDeckLinkNotificationCallbackVtbl;
+
+ interface IDeckLinkNotificationCallback
+ {
+ CONST_VTBL struct IDeckLinkNotificationCallbackVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkNotificationCallback_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkNotificationCallback_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkNotificationCallback_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkNotificationCallback_Notify(This,topic,param1,param2) \
+ ( (This)->lpVtbl -> Notify(This,topic,param1,param2) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkNotificationCallback_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkNotification_INTERFACE_DEFINED__
+#define __IDeckLinkNotification_INTERFACE_DEFINED__
+
+/* interface IDeckLinkNotification */
+/* [helpstring][local][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkNotification;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("0a1fb207-e215-441b-9b19-6fa1575946c5")
+ IDeckLinkNotification : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Subscribe(
+ /* [in] */ BMDNotifications topic,
+ /* [in] */ IDeckLinkNotificationCallback *theCallback) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Unsubscribe(
+ /* [in] */ BMDNotifications topic,
+ /* [in] */ IDeckLinkNotificationCallback *theCallback) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkNotificationVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkNotification * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkNotification * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkNotification * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Subscribe )(
+ IDeckLinkNotification * This,
+ /* [in] */ BMDNotifications topic,
+ /* [in] */ IDeckLinkNotificationCallback *theCallback);
+
+ HRESULT ( STDMETHODCALLTYPE *Unsubscribe )(
+ IDeckLinkNotification * This,
+ /* [in] */ BMDNotifications topic,
+ /* [in] */ IDeckLinkNotificationCallback *theCallback);
+
+ END_INTERFACE
+ } IDeckLinkNotificationVtbl;
+
+ interface IDeckLinkNotification
+ {
+ CONST_VTBL struct IDeckLinkNotificationVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkNotification_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkNotification_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkNotification_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkNotification_Subscribe(This,topic,theCallback) \
+ ( (This)->lpVtbl -> Subscribe(This,topic,theCallback) )
+
+#define IDeckLinkNotification_Unsubscribe(This,topic,theCallback) \
+ ( (This)->lpVtbl -> Unsubscribe(This,topic,theCallback) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkNotification_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkAttributes_INTERFACE_DEFINED__
+#define __IDeckLinkAttributes_INTERFACE_DEFINED__
+
+/* interface IDeckLinkAttributes */
+/* [helpstring][local][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkAttributes;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("ABC11843-D966-44CB-96E2-A1CB5D3135C4")
+ IDeckLinkAttributes : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE GetFlag(
+ /* [in] */ BMDDeckLinkAttributeID cfgID,
+ /* [out] */ BOOL *value) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetInt(
+ /* [in] */ BMDDeckLinkAttributeID cfgID,
+ /* [out] */ LONGLONG *value) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetFloat(
+ /* [in] */ BMDDeckLinkAttributeID cfgID,
+ /* [out] */ double *value) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetString(
+ /* [in] */ BMDDeckLinkAttributeID cfgID,
+ /* [out] */ BSTR *value) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkAttributesVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkAttributes * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkAttributes * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkAttributes * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetFlag )(
+ IDeckLinkAttributes * This,
+ /* [in] */ BMDDeckLinkAttributeID cfgID,
+ /* [out] */ BOOL *value);
+
+ HRESULT ( STDMETHODCALLTYPE *GetInt )(
+ IDeckLinkAttributes * This,
+ /* [in] */ BMDDeckLinkAttributeID cfgID,
+ /* [out] */ LONGLONG *value);
+
+ HRESULT ( STDMETHODCALLTYPE *GetFloat )(
+ IDeckLinkAttributes * This,
+ /* [in] */ BMDDeckLinkAttributeID cfgID,
+ /* [out] */ double *value);
+
+ HRESULT ( STDMETHODCALLTYPE *GetString )(
+ IDeckLinkAttributes * This,
+ /* [in] */ BMDDeckLinkAttributeID cfgID,
+ /* [out] */ BSTR *value);
+
+ END_INTERFACE
+ } IDeckLinkAttributesVtbl;
+
+ interface IDeckLinkAttributes
+ {
+ CONST_VTBL struct IDeckLinkAttributesVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkAttributes_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkAttributes_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkAttributes_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkAttributes_GetFlag(This,cfgID,value) \
+ ( (This)->lpVtbl -> GetFlag(This,cfgID,value) )
+
+#define IDeckLinkAttributes_GetInt(This,cfgID,value) \
+ ( (This)->lpVtbl -> GetInt(This,cfgID,value) )
+
+#define IDeckLinkAttributes_GetFloat(This,cfgID,value) \
+ ( (This)->lpVtbl -> GetFloat(This,cfgID,value) )
+
+#define IDeckLinkAttributes_GetString(This,cfgID,value) \
+ ( (This)->lpVtbl -> GetString(This,cfgID,value) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkAttributes_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkKeyer_INTERFACE_DEFINED__
+#define __IDeckLinkKeyer_INTERFACE_DEFINED__
+
+/* interface IDeckLinkKeyer */
+/* [helpstring][local][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkKeyer;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("89AFCAF5-65F8-421E-98F7-96FE5F5BFBA3")
+ IDeckLinkKeyer : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Enable(
+ /* [in] */ BOOL isExternal) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetLevel(
+ /* [in] */ unsigned char level) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE RampUp(
+ /* [in] */ unsigned int numberOfFrames) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE RampDown(
+ /* [in] */ unsigned int numberOfFrames) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Disable( void) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkKeyerVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkKeyer * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkKeyer * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkKeyer * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Enable )(
+ IDeckLinkKeyer * This,
+ /* [in] */ BOOL isExternal);
+
+ HRESULT ( STDMETHODCALLTYPE *SetLevel )(
+ IDeckLinkKeyer * This,
+ /* [in] */ unsigned char level);
+
+ HRESULT ( STDMETHODCALLTYPE *RampUp )(
+ IDeckLinkKeyer * This,
+ /* [in] */ unsigned int numberOfFrames);
+
+ HRESULT ( STDMETHODCALLTYPE *RampDown )(
+ IDeckLinkKeyer * This,
+ /* [in] */ unsigned int numberOfFrames);
+
+ HRESULT ( STDMETHODCALLTYPE *Disable )(
+ IDeckLinkKeyer * This);
+
+ END_INTERFACE
+ } IDeckLinkKeyerVtbl;
+
+ interface IDeckLinkKeyer
+ {
+ CONST_VTBL struct IDeckLinkKeyerVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkKeyer_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkKeyer_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkKeyer_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkKeyer_Enable(This,isExternal) \
+ ( (This)->lpVtbl -> Enable(This,isExternal) )
+
+#define IDeckLinkKeyer_SetLevel(This,level) \
+ ( (This)->lpVtbl -> SetLevel(This,level) )
+
+#define IDeckLinkKeyer_RampUp(This,numberOfFrames) \
+ ( (This)->lpVtbl -> RampUp(This,numberOfFrames) )
+
+#define IDeckLinkKeyer_RampDown(This,numberOfFrames) \
+ ( (This)->lpVtbl -> RampDown(This,numberOfFrames) )
+
+#define IDeckLinkKeyer_Disable(This) \
+ ( (This)->lpVtbl -> Disable(This) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkKeyer_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkVideoConversion_INTERFACE_DEFINED__
+#define __IDeckLinkVideoConversion_INTERFACE_DEFINED__
+
+/* interface IDeckLinkVideoConversion */
+/* [helpstring][local][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkVideoConversion;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("3BBCB8A2-DA2C-42D9-B5D8-88083644E99A")
+ IDeckLinkVideoConversion : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE ConvertFrame(
+ /* [in] */ IDeckLinkVideoFrame *srcFrame,
+ /* [in] */ IDeckLinkVideoFrame *dstFrame) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkVideoConversionVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkVideoConversion * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkVideoConversion * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkVideoConversion * This);
+
+ HRESULT ( STDMETHODCALLTYPE *ConvertFrame )(
+ IDeckLinkVideoConversion * This,
+ /* [in] */ IDeckLinkVideoFrame *srcFrame,
+ /* [in] */ IDeckLinkVideoFrame *dstFrame);
+
+ END_INTERFACE
+ } IDeckLinkVideoConversionVtbl;
+
+ interface IDeckLinkVideoConversion
+ {
+ CONST_VTBL struct IDeckLinkVideoConversionVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkVideoConversion_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkVideoConversion_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkVideoConversion_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkVideoConversion_ConvertFrame(This,srcFrame,dstFrame) \
+ ( (This)->lpVtbl -> ConvertFrame(This,srcFrame,dstFrame) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkVideoConversion_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkDeviceNotificationCallback_INTERFACE_DEFINED__
+#define __IDeckLinkDeviceNotificationCallback_INTERFACE_DEFINED__
+
+/* interface IDeckLinkDeviceNotificationCallback */
+/* [helpstring][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkDeviceNotificationCallback;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("4997053B-0ADF-4CC8-AC70-7A50C4BE728F")
+ IDeckLinkDeviceNotificationCallback : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE DeckLinkDeviceArrived(
+ /* [in] */ IDeckLink *deckLinkDevice) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE DeckLinkDeviceRemoved(
+ /* [in] */ IDeckLink *deckLinkDevice) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkDeviceNotificationCallbackVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkDeviceNotificationCallback * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkDeviceNotificationCallback * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkDeviceNotificationCallback * This);
+
+ HRESULT ( STDMETHODCALLTYPE *DeckLinkDeviceArrived )(
+ IDeckLinkDeviceNotificationCallback * This,
+ /* [in] */ IDeckLink *deckLinkDevice);
+
+ HRESULT ( STDMETHODCALLTYPE *DeckLinkDeviceRemoved )(
+ IDeckLinkDeviceNotificationCallback * This,
+ /* [in] */ IDeckLink *deckLinkDevice);
+
+ END_INTERFACE
+ } IDeckLinkDeviceNotificationCallbackVtbl;
+
+ interface IDeckLinkDeviceNotificationCallback
+ {
+ CONST_VTBL struct IDeckLinkDeviceNotificationCallbackVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkDeviceNotificationCallback_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkDeviceNotificationCallback_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkDeviceNotificationCallback_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkDeviceNotificationCallback_DeckLinkDeviceArrived(This,deckLinkDevice) \
+ ( (This)->lpVtbl -> DeckLinkDeviceArrived(This,deckLinkDevice) )
+
+#define IDeckLinkDeviceNotificationCallback_DeckLinkDeviceRemoved(This,deckLinkDevice) \
+ ( (This)->lpVtbl -> DeckLinkDeviceRemoved(This,deckLinkDevice) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkDeviceNotificationCallback_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkDiscovery_INTERFACE_DEFINED__
+#define __IDeckLinkDiscovery_INTERFACE_DEFINED__
+
+/* interface IDeckLinkDiscovery */
+/* [helpstring][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkDiscovery;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("CDBF631C-BC76-45FA-B44D-C55059BC6101")
+ IDeckLinkDiscovery : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE InstallDeviceNotifications(
+ /* [in] */ IDeckLinkDeviceNotificationCallback *deviceNotificationCallback) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE UninstallDeviceNotifications( void) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkDiscoveryVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkDiscovery * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkDiscovery * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkDiscovery * This);
+
+ HRESULT ( STDMETHODCALLTYPE *InstallDeviceNotifications )(
+ IDeckLinkDiscovery * This,
+ /* [in] */ IDeckLinkDeviceNotificationCallback *deviceNotificationCallback);
+
+ HRESULT ( STDMETHODCALLTYPE *UninstallDeviceNotifications )(
+ IDeckLinkDiscovery * This);
+
+ END_INTERFACE
+ } IDeckLinkDiscoveryVtbl;
+
+ interface IDeckLinkDiscovery
+ {
+ CONST_VTBL struct IDeckLinkDiscoveryVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkDiscovery_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkDiscovery_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkDiscovery_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkDiscovery_InstallDeviceNotifications(This,deviceNotificationCallback) \
+ ( (This)->lpVtbl -> InstallDeviceNotifications(This,deviceNotificationCallback) )
+
+#define IDeckLinkDiscovery_UninstallDeviceNotifications(This) \
+ ( (This)->lpVtbl -> UninstallDeviceNotifications(This) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkDiscovery_INTERFACE_DEFINED__ */
+
+
+EXTERN_C const CLSID CLSID_CDeckLinkIterator;
+
+#ifdef __cplusplus
+
+class DECLSPEC_UUID("1F2E109A-8F4F-49E4-9203-135595CB6FA5")
+CDeckLinkIterator;
+#endif
+
+EXTERN_C const CLSID CLSID_CDeckLinkAPIInformation;
+
+#ifdef __cplusplus
+
+class DECLSPEC_UUID("263CA19F-ED09-482E-9F9D-84005783A237")
+CDeckLinkAPIInformation;
+#endif
+
+EXTERN_C const CLSID CLSID_CDeckLinkGLScreenPreviewHelper;
+
+#ifdef __cplusplus
+
+class DECLSPEC_UUID("F63E77C7-B655-4A4A-9AD0-3CA85D394343")
+CDeckLinkGLScreenPreviewHelper;
+#endif
+
+EXTERN_C const CLSID CLSID_CDeckLinkDX9ScreenPreviewHelper;
+
+#ifdef __cplusplus
+
+class DECLSPEC_UUID("CC010023-E01D-4525-9D59-80C8AB3DC7A0")
+CDeckLinkDX9ScreenPreviewHelper;
+#endif
+
+EXTERN_C const CLSID CLSID_CDeckLinkVideoConversion;
+
+#ifdef __cplusplus
+
+class DECLSPEC_UUID("7DBBBB11-5B7B-467D-AEA4-CEA468FD368C")
+CDeckLinkVideoConversion;
+#endif
+
+EXTERN_C const CLSID CLSID_CDeckLinkDiscovery;
+
+#ifdef __cplusplus
+
+class DECLSPEC_UUID("1073A05C-D885-47E9-B3C6-129B3F9F648B")
+CDeckLinkDiscovery;
+#endif
+
+#ifndef __IDeckLinkConfiguration_v10_2_INTERFACE_DEFINED__
+#define __IDeckLinkConfiguration_v10_2_INTERFACE_DEFINED__
+
+/* interface IDeckLinkConfiguration_v10_2 */
+/* [helpstring][local][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkConfiguration_v10_2;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("C679A35B-610C-4D09-B748-1D0478100FC0")
+ IDeckLinkConfiguration_v10_2 : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE SetFlag(
+ /* [in] */ BMDDeckLinkConfigurationID cfgID,
+ /* [in] */ BOOL value) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetFlag(
+ /* [in] */ BMDDeckLinkConfigurationID cfgID,
+ /* [out] */ BOOL *value) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetInt(
+ /* [in] */ BMDDeckLinkConfigurationID cfgID,
+ /* [in] */ LONGLONG value) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetInt(
+ /* [in] */ BMDDeckLinkConfigurationID cfgID,
+ /* [out] */ LONGLONG *value) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetFloat(
+ /* [in] */ BMDDeckLinkConfigurationID cfgID,
+ /* [in] */ double value) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetFloat(
+ /* [in] */ BMDDeckLinkConfigurationID cfgID,
+ /* [out] */ double *value) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetString(
+ /* [in] */ BMDDeckLinkConfigurationID cfgID,
+ /* [in] */ BSTR value) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetString(
+ /* [in] */ BMDDeckLinkConfigurationID cfgID,
+ /* [out] */ BSTR *value) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE WriteConfigurationToPreferences( void) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkConfiguration_v10_2Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkConfiguration_v10_2 * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkConfiguration_v10_2 * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkConfiguration_v10_2 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *SetFlag )(
+ IDeckLinkConfiguration_v10_2 * This,
+ /* [in] */ BMDDeckLinkConfigurationID cfgID,
+ /* [in] */ BOOL value);
+
+ HRESULT ( STDMETHODCALLTYPE *GetFlag )(
+ IDeckLinkConfiguration_v10_2 * This,
+ /* [in] */ BMDDeckLinkConfigurationID cfgID,
+ /* [out] */ BOOL *value);
+
+ HRESULT ( STDMETHODCALLTYPE *SetInt )(
+ IDeckLinkConfiguration_v10_2 * This,
+ /* [in] */ BMDDeckLinkConfigurationID cfgID,
+ /* [in] */ LONGLONG value);
+
+ HRESULT ( STDMETHODCALLTYPE *GetInt )(
+ IDeckLinkConfiguration_v10_2 * This,
+ /* [in] */ BMDDeckLinkConfigurationID cfgID,
+ /* [out] */ LONGLONG *value);
+
+ HRESULT ( STDMETHODCALLTYPE *SetFloat )(
+ IDeckLinkConfiguration_v10_2 * This,
+ /* [in] */ BMDDeckLinkConfigurationID cfgID,
+ /* [in] */ double value);
+
+ HRESULT ( STDMETHODCALLTYPE *GetFloat )(
+ IDeckLinkConfiguration_v10_2 * This,
+ /* [in] */ BMDDeckLinkConfigurationID cfgID,
+ /* [out] */ double *value);
+
+ HRESULT ( STDMETHODCALLTYPE *SetString )(
+ IDeckLinkConfiguration_v10_2 * This,
+ /* [in] */ BMDDeckLinkConfigurationID cfgID,
+ /* [in] */ BSTR value);
+
+ HRESULT ( STDMETHODCALLTYPE *GetString )(
+ IDeckLinkConfiguration_v10_2 * This,
+ /* [in] */ BMDDeckLinkConfigurationID cfgID,
+ /* [out] */ BSTR *value);
+
+ HRESULT ( STDMETHODCALLTYPE *WriteConfigurationToPreferences )(
+ IDeckLinkConfiguration_v10_2 * This);
+
+ END_INTERFACE
+ } IDeckLinkConfiguration_v10_2Vtbl;
+
+ interface IDeckLinkConfiguration_v10_2
+ {
+ CONST_VTBL struct IDeckLinkConfiguration_v10_2Vtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkConfiguration_v10_2_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkConfiguration_v10_2_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkConfiguration_v10_2_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkConfiguration_v10_2_SetFlag(This,cfgID,value) \
+ ( (This)->lpVtbl -> SetFlag(This,cfgID,value) )
+
+#define IDeckLinkConfiguration_v10_2_GetFlag(This,cfgID,value) \
+ ( (This)->lpVtbl -> GetFlag(This,cfgID,value) )
+
+#define IDeckLinkConfiguration_v10_2_SetInt(This,cfgID,value) \
+ ( (This)->lpVtbl -> SetInt(This,cfgID,value) )
+
+#define IDeckLinkConfiguration_v10_2_GetInt(This,cfgID,value) \
+ ( (This)->lpVtbl -> GetInt(This,cfgID,value) )
+
+#define IDeckLinkConfiguration_v10_2_SetFloat(This,cfgID,value) \
+ ( (This)->lpVtbl -> SetFloat(This,cfgID,value) )
+
+#define IDeckLinkConfiguration_v10_2_GetFloat(This,cfgID,value) \
+ ( (This)->lpVtbl -> GetFloat(This,cfgID,value) )
+
+#define IDeckLinkConfiguration_v10_2_SetString(This,cfgID,value) \
+ ( (This)->lpVtbl -> SetString(This,cfgID,value) )
+
+#define IDeckLinkConfiguration_v10_2_GetString(This,cfgID,value) \
+ ( (This)->lpVtbl -> GetString(This,cfgID,value) )
+
+#define IDeckLinkConfiguration_v10_2_WriteConfigurationToPreferences(This) \
+ ( (This)->lpVtbl -> WriteConfigurationToPreferences(This) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkConfiguration_v10_2_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkOutput_v9_9_INTERFACE_DEFINED__
+#define __IDeckLinkOutput_v9_9_INTERFACE_DEFINED__
+
+/* interface IDeckLinkOutput_v9_9 */
+/* [helpstring][local][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkOutput_v9_9;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("A3EF0963-0862-44ED-92A9-EE89ABF431C7")
+ IDeckLinkOutput_v9_9 : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE DoesSupportVideoMode(
+ /* [in] */ BMDDisplayMode displayMode,
+ /* [in] */ BMDPixelFormat pixelFormat,
+ /* [in] */ BMDVideoOutputFlags flags,
+ /* [out] */ BMDDisplayModeSupport *result,
+ /* [out] */ IDeckLinkDisplayMode **resultDisplayMode) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetDisplayModeIterator(
+ /* [out] */ IDeckLinkDisplayModeIterator **iterator) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetScreenPreviewCallback(
+ /* [in] */ IDeckLinkScreenPreviewCallback *previewCallback) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE EnableVideoOutput(
+ /* [in] */ BMDDisplayMode displayMode,
+ /* [in] */ BMDVideoOutputFlags flags) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE DisableVideoOutput( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetVideoOutputFrameMemoryAllocator(
+ /* [in] */ IDeckLinkMemoryAllocator *theAllocator) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE CreateVideoFrame(
+ /* [in] */ int width,
+ /* [in] */ int height,
+ /* [in] */ int rowBytes,
+ /* [in] */ BMDPixelFormat pixelFormat,
+ /* [in] */ BMDFrameFlags flags,
+ /* [out] */ IDeckLinkMutableVideoFrame **outFrame) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE CreateAncillaryData(
+ /* [in] */ BMDPixelFormat pixelFormat,
+ /* [out] */ IDeckLinkVideoFrameAncillary **outBuffer) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE DisplayVideoFrameSync(
+ /* [in] */ IDeckLinkVideoFrame *theFrame) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE ScheduleVideoFrame(
+ /* [in] */ IDeckLinkVideoFrame *theFrame,
+ /* [in] */ BMDTimeValue displayTime,
+ /* [in] */ BMDTimeValue displayDuration,
+ /* [in] */ BMDTimeScale timeScale) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetScheduledFrameCompletionCallback(
+ /* [in] */ IDeckLinkVideoOutputCallback *theCallback) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetBufferedVideoFrameCount(
+ /* [out] */ unsigned int *bufferedFrameCount) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE EnableAudioOutput(
+ /* [in] */ BMDAudioSampleRate sampleRate,
+ /* [in] */ BMDAudioSampleType sampleType,
+ /* [in] */ unsigned int channelCount,
+ /* [in] */ BMDAudioOutputStreamType streamType) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE DisableAudioOutput( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE WriteAudioSamplesSync(
+ /* [in] */ void *buffer,
+ /* [in] */ unsigned int sampleFrameCount,
+ /* [out] */ unsigned int *sampleFramesWritten) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE BeginAudioPreroll( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE EndAudioPreroll( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE ScheduleAudioSamples(
+ /* [in] */ void *buffer,
+ /* [in] */ unsigned int sampleFrameCount,
+ /* [in] */ BMDTimeValue streamTime,
+ /* [in] */ BMDTimeScale timeScale,
+ /* [out] */ unsigned int *sampleFramesWritten) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetBufferedAudioSampleFrameCount(
+ /* [out] */ unsigned int *bufferedSampleFrameCount) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE FlushBufferedAudioSamples( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetAudioCallback(
+ /* [in] */ IDeckLinkAudioOutputCallback *theCallback) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE StartScheduledPlayback(
+ /* [in] */ BMDTimeValue playbackStartTime,
+ /* [in] */ BMDTimeScale timeScale,
+ /* [in] */ double playbackSpeed) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE StopScheduledPlayback(
+ /* [in] */ BMDTimeValue stopPlaybackAtTime,
+ /* [out] */ BMDTimeValue *actualStopTime,
+ /* [in] */ BMDTimeScale timeScale) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE IsScheduledPlaybackRunning(
+ /* [out] */ BOOL *active) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetScheduledStreamTime(
+ /* [in] */ BMDTimeScale desiredTimeScale,
+ /* [out] */ BMDTimeValue *streamTime,
+ /* [out] */ double *playbackSpeed) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetReferenceStatus(
+ /* [out] */ BMDReferenceStatus *referenceStatus) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetHardwareReferenceClock(
+ /* [in] */ BMDTimeScale desiredTimeScale,
+ /* [out] */ BMDTimeValue *hardwareTime,
+ /* [out] */ BMDTimeValue *timeInFrame,
+ /* [out] */ BMDTimeValue *ticksPerFrame) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkOutput_v9_9Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkOutput_v9_9 * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkOutput_v9_9 * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkOutput_v9_9 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *DoesSupportVideoMode )(
+ IDeckLinkOutput_v9_9 * This,
+ /* [in] */ BMDDisplayMode displayMode,
+ /* [in] */ BMDPixelFormat pixelFormat,
+ /* [in] */ BMDVideoOutputFlags flags,
+ /* [out] */ BMDDisplayModeSupport *result,
+ /* [out] */ IDeckLinkDisplayMode **resultDisplayMode);
+
+ HRESULT ( STDMETHODCALLTYPE *GetDisplayModeIterator )(
+ IDeckLinkOutput_v9_9 * This,
+ /* [out] */ IDeckLinkDisplayModeIterator **iterator);
+
+ HRESULT ( STDMETHODCALLTYPE *SetScreenPreviewCallback )(
+ IDeckLinkOutput_v9_9 * This,
+ /* [in] */ IDeckLinkScreenPreviewCallback *previewCallback);
+
+ HRESULT ( STDMETHODCALLTYPE *EnableVideoOutput )(
+ IDeckLinkOutput_v9_9 * This,
+ /* [in] */ BMDDisplayMode displayMode,
+ /* [in] */ BMDVideoOutputFlags flags);
+
+ HRESULT ( STDMETHODCALLTYPE *DisableVideoOutput )(
+ IDeckLinkOutput_v9_9 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *SetVideoOutputFrameMemoryAllocator )(
+ IDeckLinkOutput_v9_9 * This,
+ /* [in] */ IDeckLinkMemoryAllocator *theAllocator);
+
+ HRESULT ( STDMETHODCALLTYPE *CreateVideoFrame )(
+ IDeckLinkOutput_v9_9 * This,
+ /* [in] */ int width,
+ /* [in] */ int height,
+ /* [in] */ int rowBytes,
+ /* [in] */ BMDPixelFormat pixelFormat,
+ /* [in] */ BMDFrameFlags flags,
+ /* [out] */ IDeckLinkMutableVideoFrame **outFrame);
+
+ HRESULT ( STDMETHODCALLTYPE *CreateAncillaryData )(
+ IDeckLinkOutput_v9_9 * This,
+ /* [in] */ BMDPixelFormat pixelFormat,
+ /* [out] */ IDeckLinkVideoFrameAncillary **outBuffer);
+
+ HRESULT ( STDMETHODCALLTYPE *DisplayVideoFrameSync )(
+ IDeckLinkOutput_v9_9 * This,
+ /* [in] */ IDeckLinkVideoFrame *theFrame);
+
+ HRESULT ( STDMETHODCALLTYPE *ScheduleVideoFrame )(
+ IDeckLinkOutput_v9_9 * This,
+ /* [in] */ IDeckLinkVideoFrame *theFrame,
+ /* [in] */ BMDTimeValue displayTime,
+ /* [in] */ BMDTimeValue displayDuration,
+ /* [in] */ BMDTimeScale timeScale);
+
+ HRESULT ( STDMETHODCALLTYPE *SetScheduledFrameCompletionCallback )(
+ IDeckLinkOutput_v9_9 * This,
+ /* [in] */ IDeckLinkVideoOutputCallback *theCallback);
+
+ HRESULT ( STDMETHODCALLTYPE *GetBufferedVideoFrameCount )(
+ IDeckLinkOutput_v9_9 * This,
+ /* [out] */ unsigned int *bufferedFrameCount);
+
+ HRESULT ( STDMETHODCALLTYPE *EnableAudioOutput )(
+ IDeckLinkOutput_v9_9 * This,
+ /* [in] */ BMDAudioSampleRate sampleRate,
+ /* [in] */ BMDAudioSampleType sampleType,
+ /* [in] */ unsigned int channelCount,
+ /* [in] */ BMDAudioOutputStreamType streamType);
+
+ HRESULT ( STDMETHODCALLTYPE *DisableAudioOutput )(
+ IDeckLinkOutput_v9_9 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *WriteAudioSamplesSync )(
+ IDeckLinkOutput_v9_9 * This,
+ /* [in] */ void *buffer,
+ /* [in] */ unsigned int sampleFrameCount,
+ /* [out] */ unsigned int *sampleFramesWritten);
+
+ HRESULT ( STDMETHODCALLTYPE *BeginAudioPreroll )(
+ IDeckLinkOutput_v9_9 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *EndAudioPreroll )(
+ IDeckLinkOutput_v9_9 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *ScheduleAudioSamples )(
+ IDeckLinkOutput_v9_9 * This,
+ /* [in] */ void *buffer,
+ /* [in] */ unsigned int sampleFrameCount,
+ /* [in] */ BMDTimeValue streamTime,
+ /* [in] */ BMDTimeScale timeScale,
+ /* [out] */ unsigned int *sampleFramesWritten);
+
+ HRESULT ( STDMETHODCALLTYPE *GetBufferedAudioSampleFrameCount )(
+ IDeckLinkOutput_v9_9 * This,
+ /* [out] */ unsigned int *bufferedSampleFrameCount);
+
+ HRESULT ( STDMETHODCALLTYPE *FlushBufferedAudioSamples )(
+ IDeckLinkOutput_v9_9 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *SetAudioCallback )(
+ IDeckLinkOutput_v9_9 * This,
+ /* [in] */ IDeckLinkAudioOutputCallback *theCallback);
+
+ HRESULT ( STDMETHODCALLTYPE *StartScheduledPlayback )(
+ IDeckLinkOutput_v9_9 * This,
+ /* [in] */ BMDTimeValue playbackStartTime,
+ /* [in] */ BMDTimeScale timeScale,
+ /* [in] */ double playbackSpeed);
+
+ HRESULT ( STDMETHODCALLTYPE *StopScheduledPlayback )(
+ IDeckLinkOutput_v9_9 * This,
+ /* [in] */ BMDTimeValue stopPlaybackAtTime,
+ /* [out] */ BMDTimeValue *actualStopTime,
+ /* [in] */ BMDTimeScale timeScale);
+
+ HRESULT ( STDMETHODCALLTYPE *IsScheduledPlaybackRunning )(
+ IDeckLinkOutput_v9_9 * This,
+ /* [out] */ BOOL *active);
+
+ HRESULT ( STDMETHODCALLTYPE *GetScheduledStreamTime )(
+ IDeckLinkOutput_v9_9 * This,
+ /* [in] */ BMDTimeScale desiredTimeScale,
+ /* [out] */ BMDTimeValue *streamTime,
+ /* [out] */ double *playbackSpeed);
+
+ HRESULT ( STDMETHODCALLTYPE *GetReferenceStatus )(
+ IDeckLinkOutput_v9_9 * This,
+ /* [out] */ BMDReferenceStatus *referenceStatus);
+
+ HRESULT ( STDMETHODCALLTYPE *GetHardwareReferenceClock )(
+ IDeckLinkOutput_v9_9 * This,
+ /* [in] */ BMDTimeScale desiredTimeScale,
+ /* [out] */ BMDTimeValue *hardwareTime,
+ /* [out] */ BMDTimeValue *timeInFrame,
+ /* [out] */ BMDTimeValue *ticksPerFrame);
+
+ END_INTERFACE
+ } IDeckLinkOutput_v9_9Vtbl;
+
+ interface IDeckLinkOutput_v9_9
+ {
+ CONST_VTBL struct IDeckLinkOutput_v9_9Vtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkOutput_v9_9_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkOutput_v9_9_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkOutput_v9_9_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkOutput_v9_9_DoesSupportVideoMode(This,displayMode,pixelFormat,flags,result,resultDisplayMode) \
+ ( (This)->lpVtbl -> DoesSupportVideoMode(This,displayMode,pixelFormat,flags,result,resultDisplayMode) )
+
+#define IDeckLinkOutput_v9_9_GetDisplayModeIterator(This,iterator) \
+ ( (This)->lpVtbl -> GetDisplayModeIterator(This,iterator) )
+
+#define IDeckLinkOutput_v9_9_SetScreenPreviewCallback(This,previewCallback) \
+ ( (This)->lpVtbl -> SetScreenPreviewCallback(This,previewCallback) )
+
+#define IDeckLinkOutput_v9_9_EnableVideoOutput(This,displayMode,flags) \
+ ( (This)->lpVtbl -> EnableVideoOutput(This,displayMode,flags) )
+
+#define IDeckLinkOutput_v9_9_DisableVideoOutput(This) \
+ ( (This)->lpVtbl -> DisableVideoOutput(This) )
+
+#define IDeckLinkOutput_v9_9_SetVideoOutputFrameMemoryAllocator(This,theAllocator) \
+ ( (This)->lpVtbl -> SetVideoOutputFrameMemoryAllocator(This,theAllocator) )
+
+#define IDeckLinkOutput_v9_9_CreateVideoFrame(This,width,height,rowBytes,pixelFormat,flags,outFrame) \
+ ( (This)->lpVtbl -> CreateVideoFrame(This,width,height,rowBytes,pixelFormat,flags,outFrame) )
+
+#define IDeckLinkOutput_v9_9_CreateAncillaryData(This,pixelFormat,outBuffer) \
+ ( (This)->lpVtbl -> CreateAncillaryData(This,pixelFormat,outBuffer) )
+
+#define IDeckLinkOutput_v9_9_DisplayVideoFrameSync(This,theFrame) \
+ ( (This)->lpVtbl -> DisplayVideoFrameSync(This,theFrame) )
+
+#define IDeckLinkOutput_v9_9_ScheduleVideoFrame(This,theFrame,displayTime,displayDuration,timeScale) \
+ ( (This)->lpVtbl -> ScheduleVideoFrame(This,theFrame,displayTime,displayDuration,timeScale) )
+
+#define IDeckLinkOutput_v9_9_SetScheduledFrameCompletionCallback(This,theCallback) \
+ ( (This)->lpVtbl -> SetScheduledFrameCompletionCallback(This,theCallback) )
+
+#define IDeckLinkOutput_v9_9_GetBufferedVideoFrameCount(This,bufferedFrameCount) \
+ ( (This)->lpVtbl -> GetBufferedVideoFrameCount(This,bufferedFrameCount) )
+
+#define IDeckLinkOutput_v9_9_EnableAudioOutput(This,sampleRate,sampleType,channelCount,streamType) \
+ ( (This)->lpVtbl -> EnableAudioOutput(This,sampleRate,sampleType,channelCount,streamType) )
+
+#define IDeckLinkOutput_v9_9_DisableAudioOutput(This) \
+ ( (This)->lpVtbl -> DisableAudioOutput(This) )
+
+#define IDeckLinkOutput_v9_9_WriteAudioSamplesSync(This,buffer,sampleFrameCount,sampleFramesWritten) \
+ ( (This)->lpVtbl -> WriteAudioSamplesSync(This,buffer,sampleFrameCount,sampleFramesWritten) )
+
+#define IDeckLinkOutput_v9_9_BeginAudioPreroll(This) \
+ ( (This)->lpVtbl -> BeginAudioPreroll(This) )
+
+#define IDeckLinkOutput_v9_9_EndAudioPreroll(This) \
+ ( (This)->lpVtbl -> EndAudioPreroll(This) )
+
+#define IDeckLinkOutput_v9_9_ScheduleAudioSamples(This,buffer,sampleFrameCount,streamTime,timeScale,sampleFramesWritten) \
+ ( (This)->lpVtbl -> ScheduleAudioSamples(This,buffer,sampleFrameCount,streamTime,timeScale,sampleFramesWritten) )
+
+#define IDeckLinkOutput_v9_9_GetBufferedAudioSampleFrameCount(This,bufferedSampleFrameCount) \
+ ( (This)->lpVtbl -> GetBufferedAudioSampleFrameCount(This,bufferedSampleFrameCount) )
+
+#define IDeckLinkOutput_v9_9_FlushBufferedAudioSamples(This) \
+ ( (This)->lpVtbl -> FlushBufferedAudioSamples(This) )
+
+#define IDeckLinkOutput_v9_9_SetAudioCallback(This,theCallback) \
+ ( (This)->lpVtbl -> SetAudioCallback(This,theCallback) )
+
+#define IDeckLinkOutput_v9_9_StartScheduledPlayback(This,playbackStartTime,timeScale,playbackSpeed) \
+ ( (This)->lpVtbl -> StartScheduledPlayback(This,playbackStartTime,timeScale,playbackSpeed) )
+
+#define IDeckLinkOutput_v9_9_StopScheduledPlayback(This,stopPlaybackAtTime,actualStopTime,timeScale) \
+ ( (This)->lpVtbl -> StopScheduledPlayback(This,stopPlaybackAtTime,actualStopTime,timeScale) )
+
+#define IDeckLinkOutput_v9_9_IsScheduledPlaybackRunning(This,active) \
+ ( (This)->lpVtbl -> IsScheduledPlaybackRunning(This,active) )
+
+#define IDeckLinkOutput_v9_9_GetScheduledStreamTime(This,desiredTimeScale,streamTime,playbackSpeed) \
+ ( (This)->lpVtbl -> GetScheduledStreamTime(This,desiredTimeScale,streamTime,playbackSpeed) )
+
+#define IDeckLinkOutput_v9_9_GetReferenceStatus(This,referenceStatus) \
+ ( (This)->lpVtbl -> GetReferenceStatus(This,referenceStatus) )
+
+#define IDeckLinkOutput_v9_9_GetHardwareReferenceClock(This,desiredTimeScale,hardwareTime,timeInFrame,ticksPerFrame) \
+ ( (This)->lpVtbl -> GetHardwareReferenceClock(This,desiredTimeScale,hardwareTime,timeInFrame,ticksPerFrame) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkOutput_v9_9_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkInput_v9_2_INTERFACE_DEFINED__
+#define __IDeckLinkInput_v9_2_INTERFACE_DEFINED__
+
+/* interface IDeckLinkInput_v9_2 */
+/* [helpstring][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkInput_v9_2;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("6D40EF78-28B9-4E21-990D-95BB7750A04F")
+ IDeckLinkInput_v9_2 : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE DoesSupportVideoMode(
+ /* [in] */ BMDDisplayMode displayMode,
+ /* [in] */ BMDPixelFormat pixelFormat,
+ /* [in] */ BMDVideoInputFlags flags,
+ /* [out] */ BMDDisplayModeSupport *result,
+ /* [out] */ IDeckLinkDisplayMode **resultDisplayMode) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetDisplayModeIterator(
+ /* [out] */ IDeckLinkDisplayModeIterator **iterator) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetScreenPreviewCallback(
+ /* [in] */ IDeckLinkScreenPreviewCallback *previewCallback) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE EnableVideoInput(
+ /* [in] */ BMDDisplayMode displayMode,
+ /* [in] */ BMDPixelFormat pixelFormat,
+ /* [in] */ BMDVideoInputFlags flags) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE DisableVideoInput( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetAvailableVideoFrameCount(
+ /* [out] */ unsigned int *availableFrameCount) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE EnableAudioInput(
+ /* [in] */ BMDAudioSampleRate sampleRate,
+ /* [in] */ BMDAudioSampleType sampleType,
+ /* [in] */ unsigned int channelCount) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE DisableAudioInput( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetAvailableAudioSampleFrameCount(
+ /* [out] */ unsigned int *availableSampleFrameCount) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE StartStreams( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE StopStreams( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE PauseStreams( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE FlushStreams( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetCallback(
+ /* [in] */ IDeckLinkInputCallback *theCallback) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetHardwareReferenceClock(
+ /* [in] */ BMDTimeScale desiredTimeScale,
+ /* [out] */ BMDTimeValue *hardwareTime,
+ /* [out] */ BMDTimeValue *timeInFrame,
+ /* [out] */ BMDTimeValue *ticksPerFrame) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkInput_v9_2Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkInput_v9_2 * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkInput_v9_2 * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkInput_v9_2 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *DoesSupportVideoMode )(
+ IDeckLinkInput_v9_2 * This,
+ /* [in] */ BMDDisplayMode displayMode,
+ /* [in] */ BMDPixelFormat pixelFormat,
+ /* [in] */ BMDVideoInputFlags flags,
+ /* [out] */ BMDDisplayModeSupport *result,
+ /* [out] */ IDeckLinkDisplayMode **resultDisplayMode);
+
+ HRESULT ( STDMETHODCALLTYPE *GetDisplayModeIterator )(
+ IDeckLinkInput_v9_2 * This,
+ /* [out] */ IDeckLinkDisplayModeIterator **iterator);
+
+ HRESULT ( STDMETHODCALLTYPE *SetScreenPreviewCallback )(
+ IDeckLinkInput_v9_2 * This,
+ /* [in] */ IDeckLinkScreenPreviewCallback *previewCallback);
+
+ HRESULT ( STDMETHODCALLTYPE *EnableVideoInput )(
+ IDeckLinkInput_v9_2 * This,
+ /* [in] */ BMDDisplayMode displayMode,
+ /* [in] */ BMDPixelFormat pixelFormat,
+ /* [in] */ BMDVideoInputFlags flags);
+
+ HRESULT ( STDMETHODCALLTYPE *DisableVideoInput )(
+ IDeckLinkInput_v9_2 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetAvailableVideoFrameCount )(
+ IDeckLinkInput_v9_2 * This,
+ /* [out] */ unsigned int *availableFrameCount);
+
+ HRESULT ( STDMETHODCALLTYPE *EnableAudioInput )(
+ IDeckLinkInput_v9_2 * This,
+ /* [in] */ BMDAudioSampleRate sampleRate,
+ /* [in] */ BMDAudioSampleType sampleType,
+ /* [in] */ unsigned int channelCount);
+
+ HRESULT ( STDMETHODCALLTYPE *DisableAudioInput )(
+ IDeckLinkInput_v9_2 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetAvailableAudioSampleFrameCount )(
+ IDeckLinkInput_v9_2 * This,
+ /* [out] */ unsigned int *availableSampleFrameCount);
+
+ HRESULT ( STDMETHODCALLTYPE *StartStreams )(
+ IDeckLinkInput_v9_2 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *StopStreams )(
+ IDeckLinkInput_v9_2 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *PauseStreams )(
+ IDeckLinkInput_v9_2 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *FlushStreams )(
+ IDeckLinkInput_v9_2 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *SetCallback )(
+ IDeckLinkInput_v9_2 * This,
+ /* [in] */ IDeckLinkInputCallback *theCallback);
+
+ HRESULT ( STDMETHODCALLTYPE *GetHardwareReferenceClock )(
+ IDeckLinkInput_v9_2 * This,
+ /* [in] */ BMDTimeScale desiredTimeScale,
+ /* [out] */ BMDTimeValue *hardwareTime,
+ /* [out] */ BMDTimeValue *timeInFrame,
+ /* [out] */ BMDTimeValue *ticksPerFrame);
+
+ END_INTERFACE
+ } IDeckLinkInput_v9_2Vtbl;
+
+ interface IDeckLinkInput_v9_2
+ {
+ CONST_VTBL struct IDeckLinkInput_v9_2Vtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkInput_v9_2_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkInput_v9_2_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkInput_v9_2_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkInput_v9_2_DoesSupportVideoMode(This,displayMode,pixelFormat,flags,result,resultDisplayMode) \
+ ( (This)->lpVtbl -> DoesSupportVideoMode(This,displayMode,pixelFormat,flags,result,resultDisplayMode) )
+
+#define IDeckLinkInput_v9_2_GetDisplayModeIterator(This,iterator) \
+ ( (This)->lpVtbl -> GetDisplayModeIterator(This,iterator) )
+
+#define IDeckLinkInput_v9_2_SetScreenPreviewCallback(This,previewCallback) \
+ ( (This)->lpVtbl -> SetScreenPreviewCallback(This,previewCallback) )
+
+#define IDeckLinkInput_v9_2_EnableVideoInput(This,displayMode,pixelFormat,flags) \
+ ( (This)->lpVtbl -> EnableVideoInput(This,displayMode,pixelFormat,flags) )
+
+#define IDeckLinkInput_v9_2_DisableVideoInput(This) \
+ ( (This)->lpVtbl -> DisableVideoInput(This) )
+
+#define IDeckLinkInput_v9_2_GetAvailableVideoFrameCount(This,availableFrameCount) \
+ ( (This)->lpVtbl -> GetAvailableVideoFrameCount(This,availableFrameCount) )
+
+#define IDeckLinkInput_v9_2_EnableAudioInput(This,sampleRate,sampleType,channelCount) \
+ ( (This)->lpVtbl -> EnableAudioInput(This,sampleRate,sampleType,channelCount) )
+
+#define IDeckLinkInput_v9_2_DisableAudioInput(This) \
+ ( (This)->lpVtbl -> DisableAudioInput(This) )
+
+#define IDeckLinkInput_v9_2_GetAvailableAudioSampleFrameCount(This,availableSampleFrameCount) \
+ ( (This)->lpVtbl -> GetAvailableAudioSampleFrameCount(This,availableSampleFrameCount) )
+
+#define IDeckLinkInput_v9_2_StartStreams(This) \
+ ( (This)->lpVtbl -> StartStreams(This) )
+
+#define IDeckLinkInput_v9_2_StopStreams(This) \
+ ( (This)->lpVtbl -> StopStreams(This) )
+
+#define IDeckLinkInput_v9_2_PauseStreams(This) \
+ ( (This)->lpVtbl -> PauseStreams(This) )
+
+#define IDeckLinkInput_v9_2_FlushStreams(This) \
+ ( (This)->lpVtbl -> FlushStreams(This) )
+
+#define IDeckLinkInput_v9_2_SetCallback(This,theCallback) \
+ ( (This)->lpVtbl -> SetCallback(This,theCallback) )
+
+#define IDeckLinkInput_v9_2_GetHardwareReferenceClock(This,desiredTimeScale,hardwareTime,timeInFrame,ticksPerFrame) \
+ ( (This)->lpVtbl -> GetHardwareReferenceClock(This,desiredTimeScale,hardwareTime,timeInFrame,ticksPerFrame) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkInput_v9_2_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkDeckControlStatusCallback_v8_1_INTERFACE_DEFINED__
+#define __IDeckLinkDeckControlStatusCallback_v8_1_INTERFACE_DEFINED__
+
+/* interface IDeckLinkDeckControlStatusCallback_v8_1 */
+/* [helpstring][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkDeckControlStatusCallback_v8_1;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("E5F693C1-4283-4716-B18F-C1431521955B")
+ IDeckLinkDeckControlStatusCallback_v8_1 : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE TimecodeUpdate(
+ /* [in] */ BMDTimecodeBCD currentTimecode) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE VTRControlStateChanged(
+ /* [in] */ BMDDeckControlVTRControlState_v8_1 newState,
+ /* [in] */ BMDDeckControlError error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE DeckControlEventReceived(
+ /* [in] */ BMDDeckControlEvent event,
+ /* [in] */ BMDDeckControlError error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE DeckControlStatusChanged(
+ /* [in] */ BMDDeckControlStatusFlags flags,
+ /* [in] */ unsigned int mask) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkDeckControlStatusCallback_v8_1Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkDeckControlStatusCallback_v8_1 * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkDeckControlStatusCallback_v8_1 * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkDeckControlStatusCallback_v8_1 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *TimecodeUpdate )(
+ IDeckLinkDeckControlStatusCallback_v8_1 * This,
+ /* [in] */ BMDTimecodeBCD currentTimecode);
+
+ HRESULT ( STDMETHODCALLTYPE *VTRControlStateChanged )(
+ IDeckLinkDeckControlStatusCallback_v8_1 * This,
+ /* [in] */ BMDDeckControlVTRControlState_v8_1 newState,
+ /* [in] */ BMDDeckControlError error);
+
+ HRESULT ( STDMETHODCALLTYPE *DeckControlEventReceived )(
+ IDeckLinkDeckControlStatusCallback_v8_1 * This,
+ /* [in] */ BMDDeckControlEvent event,
+ /* [in] */ BMDDeckControlError error);
+
+ HRESULT ( STDMETHODCALLTYPE *DeckControlStatusChanged )(
+ IDeckLinkDeckControlStatusCallback_v8_1 * This,
+ /* [in] */ BMDDeckControlStatusFlags flags,
+ /* [in] */ unsigned int mask);
+
+ END_INTERFACE
+ } IDeckLinkDeckControlStatusCallback_v8_1Vtbl;
+
+ interface IDeckLinkDeckControlStatusCallback_v8_1
+ {
+ CONST_VTBL struct IDeckLinkDeckControlStatusCallback_v8_1Vtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkDeckControlStatusCallback_v8_1_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkDeckControlStatusCallback_v8_1_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkDeckControlStatusCallback_v8_1_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkDeckControlStatusCallback_v8_1_TimecodeUpdate(This,currentTimecode) \
+ ( (This)->lpVtbl -> TimecodeUpdate(This,currentTimecode) )
+
+#define IDeckLinkDeckControlStatusCallback_v8_1_VTRControlStateChanged(This,newState,error) \
+ ( (This)->lpVtbl -> VTRControlStateChanged(This,newState,error) )
+
+#define IDeckLinkDeckControlStatusCallback_v8_1_DeckControlEventReceived(This,event,error) \
+ ( (This)->lpVtbl -> DeckControlEventReceived(This,event,error) )
+
+#define IDeckLinkDeckControlStatusCallback_v8_1_DeckControlStatusChanged(This,flags,mask) \
+ ( (This)->lpVtbl -> DeckControlStatusChanged(This,flags,mask) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkDeckControlStatusCallback_v8_1_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkDeckControl_v8_1_INTERFACE_DEFINED__
+#define __IDeckLinkDeckControl_v8_1_INTERFACE_DEFINED__
+
+/* interface IDeckLinkDeckControl_v8_1 */
+/* [helpstring][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkDeckControl_v8_1;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("522A9E39-0F3C-4742-94EE-D80DE335DA1D")
+ IDeckLinkDeckControl_v8_1 : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Open(
+ /* [in] */ BMDTimeScale timeScale,
+ /* [in] */ BMDTimeValue timeValue,
+ /* [in] */ BOOL timecodeIsDropFrame,
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Close(
+ /* [in] */ BOOL standbyOn) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetCurrentState(
+ /* [out] */ BMDDeckControlMode *mode,
+ /* [out] */ BMDDeckControlVTRControlState_v8_1 *vtrControlState,
+ /* [out] */ BMDDeckControlStatusFlags *flags) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetStandby(
+ /* [in] */ BOOL standbyOn) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SendCommand(
+ /* [in] */ unsigned char *inBuffer,
+ /* [in] */ unsigned int inBufferSize,
+ /* [out] */ unsigned char *outBuffer,
+ /* [out] */ unsigned int *outDataSize,
+ /* [in] */ unsigned int outBufferSize,
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Play(
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Stop(
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE TogglePlayStop(
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Eject(
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GoToTimecode(
+ /* [in] */ BMDTimecodeBCD timecode,
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE FastForward(
+ /* [in] */ BOOL viewTape,
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Rewind(
+ /* [in] */ BOOL viewTape,
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE StepForward(
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE StepBack(
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Jog(
+ /* [in] */ double rate,
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Shuttle(
+ /* [in] */ double rate,
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetTimecodeString(
+ /* [out] */ BSTR *currentTimeCode,
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetTimecode(
+ /* [out] */ IDeckLinkTimecode **currentTimecode,
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetTimecodeBCD(
+ /* [out] */ BMDTimecodeBCD *currentTimecode,
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetPreroll(
+ /* [in] */ unsigned int prerollSeconds) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetPreroll(
+ /* [out] */ unsigned int *prerollSeconds) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetExportOffset(
+ /* [in] */ int exportOffsetFields) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetExportOffset(
+ /* [out] */ int *exportOffsetFields) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetManualExportOffset(
+ /* [out] */ int *deckManualExportOffsetFields) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetCaptureOffset(
+ /* [in] */ int captureOffsetFields) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetCaptureOffset(
+ /* [out] */ int *captureOffsetFields) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE StartExport(
+ /* [in] */ BMDTimecodeBCD inTimecode,
+ /* [in] */ BMDTimecodeBCD outTimecode,
+ /* [in] */ BMDDeckControlExportModeOpsFlags exportModeOps,
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE StartCapture(
+ /* [in] */ BOOL useVITC,
+ /* [in] */ BMDTimecodeBCD inTimecode,
+ /* [in] */ BMDTimecodeBCD outTimecode,
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetDeviceID(
+ /* [out] */ unsigned short *deviceId,
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Abort( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE CrashRecordStart(
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE CrashRecordStop(
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetCallback(
+ /* [in] */ IDeckLinkDeckControlStatusCallback_v8_1 *callback) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkDeckControl_v8_1Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkDeckControl_v8_1 * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkDeckControl_v8_1 * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkDeckControl_v8_1 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Open )(
+ IDeckLinkDeckControl_v8_1 * This,
+ /* [in] */ BMDTimeScale timeScale,
+ /* [in] */ BMDTimeValue timeValue,
+ /* [in] */ BOOL timecodeIsDropFrame,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *Close )(
+ IDeckLinkDeckControl_v8_1 * This,
+ /* [in] */ BOOL standbyOn);
+
+ HRESULT ( STDMETHODCALLTYPE *GetCurrentState )(
+ IDeckLinkDeckControl_v8_1 * This,
+ /* [out] */ BMDDeckControlMode *mode,
+ /* [out] */ BMDDeckControlVTRControlState_v8_1 *vtrControlState,
+ /* [out] */ BMDDeckControlStatusFlags *flags);
+
+ HRESULT ( STDMETHODCALLTYPE *SetStandby )(
+ IDeckLinkDeckControl_v8_1 * This,
+ /* [in] */ BOOL standbyOn);
+
+ HRESULT ( STDMETHODCALLTYPE *SendCommand )(
+ IDeckLinkDeckControl_v8_1 * This,
+ /* [in] */ unsigned char *inBuffer,
+ /* [in] */ unsigned int inBufferSize,
+ /* [out] */ unsigned char *outBuffer,
+ /* [out] */ unsigned int *outDataSize,
+ /* [in] */ unsigned int outBufferSize,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *Play )(
+ IDeckLinkDeckControl_v8_1 * This,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *Stop )(
+ IDeckLinkDeckControl_v8_1 * This,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *TogglePlayStop )(
+ IDeckLinkDeckControl_v8_1 * This,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *Eject )(
+ IDeckLinkDeckControl_v8_1 * This,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *GoToTimecode )(
+ IDeckLinkDeckControl_v8_1 * This,
+ /* [in] */ BMDTimecodeBCD timecode,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *FastForward )(
+ IDeckLinkDeckControl_v8_1 * This,
+ /* [in] */ BOOL viewTape,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *Rewind )(
+ IDeckLinkDeckControl_v8_1 * This,
+ /* [in] */ BOOL viewTape,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *StepForward )(
+ IDeckLinkDeckControl_v8_1 * This,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *StepBack )(
+ IDeckLinkDeckControl_v8_1 * This,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *Jog )(
+ IDeckLinkDeckControl_v8_1 * This,
+ /* [in] */ double rate,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *Shuttle )(
+ IDeckLinkDeckControl_v8_1 * This,
+ /* [in] */ double rate,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *GetTimecodeString )(
+ IDeckLinkDeckControl_v8_1 * This,
+ /* [out] */ BSTR *currentTimeCode,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *GetTimecode )(
+ IDeckLinkDeckControl_v8_1 * This,
+ /* [out] */ IDeckLinkTimecode **currentTimecode,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *GetTimecodeBCD )(
+ IDeckLinkDeckControl_v8_1 * This,
+ /* [out] */ BMDTimecodeBCD *currentTimecode,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *SetPreroll )(
+ IDeckLinkDeckControl_v8_1 * This,
+ /* [in] */ unsigned int prerollSeconds);
+
+ HRESULT ( STDMETHODCALLTYPE *GetPreroll )(
+ IDeckLinkDeckControl_v8_1 * This,
+ /* [out] */ unsigned int *prerollSeconds);
+
+ HRESULT ( STDMETHODCALLTYPE *SetExportOffset )(
+ IDeckLinkDeckControl_v8_1 * This,
+ /* [in] */ int exportOffsetFields);
+
+ HRESULT ( STDMETHODCALLTYPE *GetExportOffset )(
+ IDeckLinkDeckControl_v8_1 * This,
+ /* [out] */ int *exportOffsetFields);
+
+ HRESULT ( STDMETHODCALLTYPE *GetManualExportOffset )(
+ IDeckLinkDeckControl_v8_1 * This,
+ /* [out] */ int *deckManualExportOffsetFields);
+
+ HRESULT ( STDMETHODCALLTYPE *SetCaptureOffset )(
+ IDeckLinkDeckControl_v8_1 * This,
+ /* [in] */ int captureOffsetFields);
+
+ HRESULT ( STDMETHODCALLTYPE *GetCaptureOffset )(
+ IDeckLinkDeckControl_v8_1 * This,
+ /* [out] */ int *captureOffsetFields);
+
+ HRESULT ( STDMETHODCALLTYPE *StartExport )(
+ IDeckLinkDeckControl_v8_1 * This,
+ /* [in] */ BMDTimecodeBCD inTimecode,
+ /* [in] */ BMDTimecodeBCD outTimecode,
+ /* [in] */ BMDDeckControlExportModeOpsFlags exportModeOps,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *StartCapture )(
+ IDeckLinkDeckControl_v8_1 * This,
+ /* [in] */ BOOL useVITC,
+ /* [in] */ BMDTimecodeBCD inTimecode,
+ /* [in] */ BMDTimecodeBCD outTimecode,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *GetDeviceID )(
+ IDeckLinkDeckControl_v8_1 * This,
+ /* [out] */ unsigned short *deviceId,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *Abort )(
+ IDeckLinkDeckControl_v8_1 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *CrashRecordStart )(
+ IDeckLinkDeckControl_v8_1 * This,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *CrashRecordStop )(
+ IDeckLinkDeckControl_v8_1 * This,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *SetCallback )(
+ IDeckLinkDeckControl_v8_1 * This,
+ /* [in] */ IDeckLinkDeckControlStatusCallback_v8_1 *callback);
+
+ END_INTERFACE
+ } IDeckLinkDeckControl_v8_1Vtbl;
+
+ interface IDeckLinkDeckControl_v8_1
+ {
+ CONST_VTBL struct IDeckLinkDeckControl_v8_1Vtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkDeckControl_v8_1_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkDeckControl_v8_1_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkDeckControl_v8_1_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkDeckControl_v8_1_Open(This,timeScale,timeValue,timecodeIsDropFrame,error) \
+ ( (This)->lpVtbl -> Open(This,timeScale,timeValue,timecodeIsDropFrame,error) )
+
+#define IDeckLinkDeckControl_v8_1_Close(This,standbyOn) \
+ ( (This)->lpVtbl -> Close(This,standbyOn) )
+
+#define IDeckLinkDeckControl_v8_1_GetCurrentState(This,mode,vtrControlState,flags) \
+ ( (This)->lpVtbl -> GetCurrentState(This,mode,vtrControlState,flags) )
+
+#define IDeckLinkDeckControl_v8_1_SetStandby(This,standbyOn) \
+ ( (This)->lpVtbl -> SetStandby(This,standbyOn) )
+
+#define IDeckLinkDeckControl_v8_1_SendCommand(This,inBuffer,inBufferSize,outBuffer,outDataSize,outBufferSize,error) \
+ ( (This)->lpVtbl -> SendCommand(This,inBuffer,inBufferSize,outBuffer,outDataSize,outBufferSize,error) )
+
+#define IDeckLinkDeckControl_v8_1_Play(This,error) \
+ ( (This)->lpVtbl -> Play(This,error) )
+
+#define IDeckLinkDeckControl_v8_1_Stop(This,error) \
+ ( (This)->lpVtbl -> Stop(This,error) )
+
+#define IDeckLinkDeckControl_v8_1_TogglePlayStop(This,error) \
+ ( (This)->lpVtbl -> TogglePlayStop(This,error) )
+
+#define IDeckLinkDeckControl_v8_1_Eject(This,error) \
+ ( (This)->lpVtbl -> Eject(This,error) )
+
+#define IDeckLinkDeckControl_v8_1_GoToTimecode(This,timecode,error) \
+ ( (This)->lpVtbl -> GoToTimecode(This,timecode,error) )
+
+#define IDeckLinkDeckControl_v8_1_FastForward(This,viewTape,error) \
+ ( (This)->lpVtbl -> FastForward(This,viewTape,error) )
+
+#define IDeckLinkDeckControl_v8_1_Rewind(This,viewTape,error) \
+ ( (This)->lpVtbl -> Rewind(This,viewTape,error) )
+
+#define IDeckLinkDeckControl_v8_1_StepForward(This,error) \
+ ( (This)->lpVtbl -> StepForward(This,error) )
+
+#define IDeckLinkDeckControl_v8_1_StepBack(This,error) \
+ ( (This)->lpVtbl -> StepBack(This,error) )
+
+#define IDeckLinkDeckControl_v8_1_Jog(This,rate,error) \
+ ( (This)->lpVtbl -> Jog(This,rate,error) )
+
+#define IDeckLinkDeckControl_v8_1_Shuttle(This,rate,error) \
+ ( (This)->lpVtbl -> Shuttle(This,rate,error) )
+
+#define IDeckLinkDeckControl_v8_1_GetTimecodeString(This,currentTimeCode,error) \
+ ( (This)->lpVtbl -> GetTimecodeString(This,currentTimeCode,error) )
+
+#define IDeckLinkDeckControl_v8_1_GetTimecode(This,currentTimecode,error) \
+ ( (This)->lpVtbl -> GetTimecode(This,currentTimecode,error) )
+
+#define IDeckLinkDeckControl_v8_1_GetTimecodeBCD(This,currentTimecode,error) \
+ ( (This)->lpVtbl -> GetTimecodeBCD(This,currentTimecode,error) )
+
+#define IDeckLinkDeckControl_v8_1_SetPreroll(This,prerollSeconds) \
+ ( (This)->lpVtbl -> SetPreroll(This,prerollSeconds) )
+
+#define IDeckLinkDeckControl_v8_1_GetPreroll(This,prerollSeconds) \
+ ( (This)->lpVtbl -> GetPreroll(This,prerollSeconds) )
+
+#define IDeckLinkDeckControl_v8_1_SetExportOffset(This,exportOffsetFields) \
+ ( (This)->lpVtbl -> SetExportOffset(This,exportOffsetFields) )
+
+#define IDeckLinkDeckControl_v8_1_GetExportOffset(This,exportOffsetFields) \
+ ( (This)->lpVtbl -> GetExportOffset(This,exportOffsetFields) )
+
+#define IDeckLinkDeckControl_v8_1_GetManualExportOffset(This,deckManualExportOffsetFields) \
+ ( (This)->lpVtbl -> GetManualExportOffset(This,deckManualExportOffsetFields) )
+
+#define IDeckLinkDeckControl_v8_1_SetCaptureOffset(This,captureOffsetFields) \
+ ( (This)->lpVtbl -> SetCaptureOffset(This,captureOffsetFields) )
+
+#define IDeckLinkDeckControl_v8_1_GetCaptureOffset(This,captureOffsetFields) \
+ ( (This)->lpVtbl -> GetCaptureOffset(This,captureOffsetFields) )
+
+#define IDeckLinkDeckControl_v8_1_StartExport(This,inTimecode,outTimecode,exportModeOps,error) \
+ ( (This)->lpVtbl -> StartExport(This,inTimecode,outTimecode,exportModeOps,error) )
+
+#define IDeckLinkDeckControl_v8_1_StartCapture(This,useVITC,inTimecode,outTimecode,error) \
+ ( (This)->lpVtbl -> StartCapture(This,useVITC,inTimecode,outTimecode,error) )
+
+#define IDeckLinkDeckControl_v8_1_GetDeviceID(This,deviceId,error) \
+ ( (This)->lpVtbl -> GetDeviceID(This,deviceId,error) )
+
+#define IDeckLinkDeckControl_v8_1_Abort(This) \
+ ( (This)->lpVtbl -> Abort(This) )
+
+#define IDeckLinkDeckControl_v8_1_CrashRecordStart(This,error) \
+ ( (This)->lpVtbl -> CrashRecordStart(This,error) )
+
+#define IDeckLinkDeckControl_v8_1_CrashRecordStop(This,error) \
+ ( (This)->lpVtbl -> CrashRecordStop(This,error) )
+
+#define IDeckLinkDeckControl_v8_1_SetCallback(This,callback) \
+ ( (This)->lpVtbl -> SetCallback(This,callback) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkDeckControl_v8_1_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLink_v8_0_INTERFACE_DEFINED__
+#define __IDeckLink_v8_0_INTERFACE_DEFINED__
+
+/* interface IDeckLink_v8_0 */
+/* [helpstring][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLink_v8_0;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("62BFF75D-6569-4E55-8D4D-66AA03829ABC")
+ IDeckLink_v8_0 : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE GetModelName(
+ /* [out] */ BSTR *modelName) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLink_v8_0Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLink_v8_0 * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLink_v8_0 * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLink_v8_0 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetModelName )(
+ IDeckLink_v8_0 * This,
+ /* [out] */ BSTR *modelName);
+
+ END_INTERFACE
+ } IDeckLink_v8_0Vtbl;
+
+ interface IDeckLink_v8_0
+ {
+ CONST_VTBL struct IDeckLink_v8_0Vtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLink_v8_0_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLink_v8_0_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLink_v8_0_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLink_v8_0_GetModelName(This,modelName) \
+ ( (This)->lpVtbl -> GetModelName(This,modelName) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLink_v8_0_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkIterator_v8_0_INTERFACE_DEFINED__
+#define __IDeckLinkIterator_v8_0_INTERFACE_DEFINED__
+
+/* interface IDeckLinkIterator_v8_0 */
+/* [helpstring][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkIterator_v8_0;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("74E936FC-CC28-4A67-81A0-1E94E52D4E69")
+ IDeckLinkIterator_v8_0 : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Next(
+ /* [out] */ IDeckLink_v8_0 **deckLinkInstance) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkIterator_v8_0Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkIterator_v8_0 * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkIterator_v8_0 * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkIterator_v8_0 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Next )(
+ IDeckLinkIterator_v8_0 * This,
+ /* [out] */ IDeckLink_v8_0 **deckLinkInstance);
+
+ END_INTERFACE
+ } IDeckLinkIterator_v8_0Vtbl;
+
+ interface IDeckLinkIterator_v8_0
+ {
+ CONST_VTBL struct IDeckLinkIterator_v8_0Vtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkIterator_v8_0_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkIterator_v8_0_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkIterator_v8_0_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkIterator_v8_0_Next(This,deckLinkInstance) \
+ ( (This)->lpVtbl -> Next(This,deckLinkInstance) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkIterator_v8_0_INTERFACE_DEFINED__ */
+
+
+EXTERN_C const CLSID CLSID_CDeckLinkIterator_v8_0;
+
+#ifdef __cplusplus
+
+class DECLSPEC_UUID("D9EDA3B3-2887-41FA-B724-017CF1EB1D37")
+CDeckLinkIterator_v8_0;
+#endif
+
+#ifndef __IDeckLinkDeckControl_v7_9_INTERFACE_DEFINED__
+#define __IDeckLinkDeckControl_v7_9_INTERFACE_DEFINED__
+
+/* interface IDeckLinkDeckControl_v7_9 */
+/* [helpstring][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkDeckControl_v7_9;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("A4D81043-0619-42B7-8ED6-602D29041DF7")
+ IDeckLinkDeckControl_v7_9 : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Open(
+ /* [in] */ BMDTimeScale timeScale,
+ /* [in] */ BMDTimeValue timeValue,
+ /* [in] */ BOOL timecodeIsDropFrame,
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Close(
+ /* [in] */ BOOL standbyOn) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetCurrentState(
+ /* [out] */ BMDDeckControlMode *mode,
+ /* [out] */ BMDDeckControlVTRControlState *vtrControlState,
+ /* [out] */ BMDDeckControlStatusFlags *flags) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetStandby(
+ /* [in] */ BOOL standbyOn) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Play(
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Stop(
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE TogglePlayStop(
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Eject(
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GoToTimecode(
+ /* [in] */ BMDTimecodeBCD timecode,
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE FastForward(
+ /* [in] */ BOOL viewTape,
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Rewind(
+ /* [in] */ BOOL viewTape,
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE StepForward(
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE StepBack(
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Jog(
+ /* [in] */ double rate,
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Shuttle(
+ /* [in] */ double rate,
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetTimecodeString(
+ /* [out] */ BSTR *currentTimeCode,
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetTimecode(
+ /* [out] */ IDeckLinkTimecode **currentTimecode,
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetTimecodeBCD(
+ /* [out] */ BMDTimecodeBCD *currentTimecode,
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetPreroll(
+ /* [in] */ unsigned int prerollSeconds) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetPreroll(
+ /* [out] */ unsigned int *prerollSeconds) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetExportOffset(
+ /* [in] */ int exportOffsetFields) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetExportOffset(
+ /* [out] */ int *exportOffsetFields) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetManualExportOffset(
+ /* [out] */ int *deckManualExportOffsetFields) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetCaptureOffset(
+ /* [in] */ int captureOffsetFields) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetCaptureOffset(
+ /* [out] */ int *captureOffsetFields) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE StartExport(
+ /* [in] */ BMDTimecodeBCD inTimecode,
+ /* [in] */ BMDTimecodeBCD outTimecode,
+ /* [in] */ BMDDeckControlExportModeOpsFlags exportModeOps,
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE StartCapture(
+ /* [in] */ BOOL useVITC,
+ /* [in] */ BMDTimecodeBCD inTimecode,
+ /* [in] */ BMDTimecodeBCD outTimecode,
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetDeviceID(
+ /* [out] */ unsigned short *deviceId,
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Abort( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE CrashRecordStart(
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE CrashRecordStop(
+ /* [out] */ BMDDeckControlError *error) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetCallback(
+ /* [in] */ IDeckLinkDeckControlStatusCallback *callback) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkDeckControl_v7_9Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkDeckControl_v7_9 * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkDeckControl_v7_9 * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkDeckControl_v7_9 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Open )(
+ IDeckLinkDeckControl_v7_9 * This,
+ /* [in] */ BMDTimeScale timeScale,
+ /* [in] */ BMDTimeValue timeValue,
+ /* [in] */ BOOL timecodeIsDropFrame,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *Close )(
+ IDeckLinkDeckControl_v7_9 * This,
+ /* [in] */ BOOL standbyOn);
+
+ HRESULT ( STDMETHODCALLTYPE *GetCurrentState )(
+ IDeckLinkDeckControl_v7_9 * This,
+ /* [out] */ BMDDeckControlMode *mode,
+ /* [out] */ BMDDeckControlVTRControlState *vtrControlState,
+ /* [out] */ BMDDeckControlStatusFlags *flags);
+
+ HRESULT ( STDMETHODCALLTYPE *SetStandby )(
+ IDeckLinkDeckControl_v7_9 * This,
+ /* [in] */ BOOL standbyOn);
+
+ HRESULT ( STDMETHODCALLTYPE *Play )(
+ IDeckLinkDeckControl_v7_9 * This,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *Stop )(
+ IDeckLinkDeckControl_v7_9 * This,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *TogglePlayStop )(
+ IDeckLinkDeckControl_v7_9 * This,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *Eject )(
+ IDeckLinkDeckControl_v7_9 * This,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *GoToTimecode )(
+ IDeckLinkDeckControl_v7_9 * This,
+ /* [in] */ BMDTimecodeBCD timecode,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *FastForward )(
+ IDeckLinkDeckControl_v7_9 * This,
+ /* [in] */ BOOL viewTape,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *Rewind )(
+ IDeckLinkDeckControl_v7_9 * This,
+ /* [in] */ BOOL viewTape,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *StepForward )(
+ IDeckLinkDeckControl_v7_9 * This,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *StepBack )(
+ IDeckLinkDeckControl_v7_9 * This,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *Jog )(
+ IDeckLinkDeckControl_v7_9 * This,
+ /* [in] */ double rate,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *Shuttle )(
+ IDeckLinkDeckControl_v7_9 * This,
+ /* [in] */ double rate,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *GetTimecodeString )(
+ IDeckLinkDeckControl_v7_9 * This,
+ /* [out] */ BSTR *currentTimeCode,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *GetTimecode )(
+ IDeckLinkDeckControl_v7_9 * This,
+ /* [out] */ IDeckLinkTimecode **currentTimecode,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *GetTimecodeBCD )(
+ IDeckLinkDeckControl_v7_9 * This,
+ /* [out] */ BMDTimecodeBCD *currentTimecode,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *SetPreroll )(
+ IDeckLinkDeckControl_v7_9 * This,
+ /* [in] */ unsigned int prerollSeconds);
+
+ HRESULT ( STDMETHODCALLTYPE *GetPreroll )(
+ IDeckLinkDeckControl_v7_9 * This,
+ /* [out] */ unsigned int *prerollSeconds);
+
+ HRESULT ( STDMETHODCALLTYPE *SetExportOffset )(
+ IDeckLinkDeckControl_v7_9 * This,
+ /* [in] */ int exportOffsetFields);
+
+ HRESULT ( STDMETHODCALLTYPE *GetExportOffset )(
+ IDeckLinkDeckControl_v7_9 * This,
+ /* [out] */ int *exportOffsetFields);
+
+ HRESULT ( STDMETHODCALLTYPE *GetManualExportOffset )(
+ IDeckLinkDeckControl_v7_9 * This,
+ /* [out] */ int *deckManualExportOffsetFields);
+
+ HRESULT ( STDMETHODCALLTYPE *SetCaptureOffset )(
+ IDeckLinkDeckControl_v7_9 * This,
+ /* [in] */ int captureOffsetFields);
+
+ HRESULT ( STDMETHODCALLTYPE *GetCaptureOffset )(
+ IDeckLinkDeckControl_v7_9 * This,
+ /* [out] */ int *captureOffsetFields);
+
+ HRESULT ( STDMETHODCALLTYPE *StartExport )(
+ IDeckLinkDeckControl_v7_9 * This,
+ /* [in] */ BMDTimecodeBCD inTimecode,
+ /* [in] */ BMDTimecodeBCD outTimecode,
+ /* [in] */ BMDDeckControlExportModeOpsFlags exportModeOps,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *StartCapture )(
+ IDeckLinkDeckControl_v7_9 * This,
+ /* [in] */ BOOL useVITC,
+ /* [in] */ BMDTimecodeBCD inTimecode,
+ /* [in] */ BMDTimecodeBCD outTimecode,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *GetDeviceID )(
+ IDeckLinkDeckControl_v7_9 * This,
+ /* [out] */ unsigned short *deviceId,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *Abort )(
+ IDeckLinkDeckControl_v7_9 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *CrashRecordStart )(
+ IDeckLinkDeckControl_v7_9 * This,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *CrashRecordStop )(
+ IDeckLinkDeckControl_v7_9 * This,
+ /* [out] */ BMDDeckControlError *error);
+
+ HRESULT ( STDMETHODCALLTYPE *SetCallback )(
+ IDeckLinkDeckControl_v7_9 * This,
+ /* [in] */ IDeckLinkDeckControlStatusCallback *callback);
+
+ END_INTERFACE
+ } IDeckLinkDeckControl_v7_9Vtbl;
+
+ interface IDeckLinkDeckControl_v7_9
+ {
+ CONST_VTBL struct IDeckLinkDeckControl_v7_9Vtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkDeckControl_v7_9_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkDeckControl_v7_9_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkDeckControl_v7_9_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkDeckControl_v7_9_Open(This,timeScale,timeValue,timecodeIsDropFrame,error) \
+ ( (This)->lpVtbl -> Open(This,timeScale,timeValue,timecodeIsDropFrame,error) )
+
+#define IDeckLinkDeckControl_v7_9_Close(This,standbyOn) \
+ ( (This)->lpVtbl -> Close(This,standbyOn) )
+
+#define IDeckLinkDeckControl_v7_9_GetCurrentState(This,mode,vtrControlState,flags) \
+ ( (This)->lpVtbl -> GetCurrentState(This,mode,vtrControlState,flags) )
+
+#define IDeckLinkDeckControl_v7_9_SetStandby(This,standbyOn) \
+ ( (This)->lpVtbl -> SetStandby(This,standbyOn) )
+
+#define IDeckLinkDeckControl_v7_9_Play(This,error) \
+ ( (This)->lpVtbl -> Play(This,error) )
+
+#define IDeckLinkDeckControl_v7_9_Stop(This,error) \
+ ( (This)->lpVtbl -> Stop(This,error) )
+
+#define IDeckLinkDeckControl_v7_9_TogglePlayStop(This,error) \
+ ( (This)->lpVtbl -> TogglePlayStop(This,error) )
+
+#define IDeckLinkDeckControl_v7_9_Eject(This,error) \
+ ( (This)->lpVtbl -> Eject(This,error) )
+
+#define IDeckLinkDeckControl_v7_9_GoToTimecode(This,timecode,error) \
+ ( (This)->lpVtbl -> GoToTimecode(This,timecode,error) )
+
+#define IDeckLinkDeckControl_v7_9_FastForward(This,viewTape,error) \
+ ( (This)->lpVtbl -> FastForward(This,viewTape,error) )
+
+#define IDeckLinkDeckControl_v7_9_Rewind(This,viewTape,error) \
+ ( (This)->lpVtbl -> Rewind(This,viewTape,error) )
+
+#define IDeckLinkDeckControl_v7_9_StepForward(This,error) \
+ ( (This)->lpVtbl -> StepForward(This,error) )
+
+#define IDeckLinkDeckControl_v7_9_StepBack(This,error) \
+ ( (This)->lpVtbl -> StepBack(This,error) )
+
+#define IDeckLinkDeckControl_v7_9_Jog(This,rate,error) \
+ ( (This)->lpVtbl -> Jog(This,rate,error) )
+
+#define IDeckLinkDeckControl_v7_9_Shuttle(This,rate,error) \
+ ( (This)->lpVtbl -> Shuttle(This,rate,error) )
+
+#define IDeckLinkDeckControl_v7_9_GetTimecodeString(This,currentTimeCode,error) \
+ ( (This)->lpVtbl -> GetTimecodeString(This,currentTimeCode,error) )
+
+#define IDeckLinkDeckControl_v7_9_GetTimecode(This,currentTimecode,error) \
+ ( (This)->lpVtbl -> GetTimecode(This,currentTimecode,error) )
+
+#define IDeckLinkDeckControl_v7_9_GetTimecodeBCD(This,currentTimecode,error) \
+ ( (This)->lpVtbl -> GetTimecodeBCD(This,currentTimecode,error) )
+
+#define IDeckLinkDeckControl_v7_9_SetPreroll(This,prerollSeconds) \
+ ( (This)->lpVtbl -> SetPreroll(This,prerollSeconds) )
+
+#define IDeckLinkDeckControl_v7_9_GetPreroll(This,prerollSeconds) \
+ ( (This)->lpVtbl -> GetPreroll(This,prerollSeconds) )
+
+#define IDeckLinkDeckControl_v7_9_SetExportOffset(This,exportOffsetFields) \
+ ( (This)->lpVtbl -> SetExportOffset(This,exportOffsetFields) )
+
+#define IDeckLinkDeckControl_v7_9_GetExportOffset(This,exportOffsetFields) \
+ ( (This)->lpVtbl -> GetExportOffset(This,exportOffsetFields) )
+
+#define IDeckLinkDeckControl_v7_9_GetManualExportOffset(This,deckManualExportOffsetFields) \
+ ( (This)->lpVtbl -> GetManualExportOffset(This,deckManualExportOffsetFields) )
+
+#define IDeckLinkDeckControl_v7_9_SetCaptureOffset(This,captureOffsetFields) \
+ ( (This)->lpVtbl -> SetCaptureOffset(This,captureOffsetFields) )
+
+#define IDeckLinkDeckControl_v7_9_GetCaptureOffset(This,captureOffsetFields) \
+ ( (This)->lpVtbl -> GetCaptureOffset(This,captureOffsetFields) )
+
+#define IDeckLinkDeckControl_v7_9_StartExport(This,inTimecode,outTimecode,exportModeOps,error) \
+ ( (This)->lpVtbl -> StartExport(This,inTimecode,outTimecode,exportModeOps,error) )
+
+#define IDeckLinkDeckControl_v7_9_StartCapture(This,useVITC,inTimecode,outTimecode,error) \
+ ( (This)->lpVtbl -> StartCapture(This,useVITC,inTimecode,outTimecode,error) )
+
+#define IDeckLinkDeckControl_v7_9_GetDeviceID(This,deviceId,error) \
+ ( (This)->lpVtbl -> GetDeviceID(This,deviceId,error) )
+
+#define IDeckLinkDeckControl_v7_9_Abort(This) \
+ ( (This)->lpVtbl -> Abort(This) )
+
+#define IDeckLinkDeckControl_v7_9_CrashRecordStart(This,error) \
+ ( (This)->lpVtbl -> CrashRecordStart(This,error) )
+
+#define IDeckLinkDeckControl_v7_9_CrashRecordStop(This,error) \
+ ( (This)->lpVtbl -> CrashRecordStop(This,error) )
+
+#define IDeckLinkDeckControl_v7_9_SetCallback(This,callback) \
+ ( (This)->lpVtbl -> SetCallback(This,callback) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkDeckControl_v7_9_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkDisplayModeIterator_v7_6_INTERFACE_DEFINED__
+#define __IDeckLinkDisplayModeIterator_v7_6_INTERFACE_DEFINED__
+
+/* interface IDeckLinkDisplayModeIterator_v7_6 */
+/* [helpstring][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkDisplayModeIterator_v7_6;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("455D741F-1779-4800-86F5-0B5D13D79751")
+ IDeckLinkDisplayModeIterator_v7_6 : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Next(
+ /* [out] */ IDeckLinkDisplayMode_v7_6 **deckLinkDisplayMode) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkDisplayModeIterator_v7_6Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkDisplayModeIterator_v7_6 * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkDisplayModeIterator_v7_6 * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkDisplayModeIterator_v7_6 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Next )(
+ IDeckLinkDisplayModeIterator_v7_6 * This,
+ /* [out] */ IDeckLinkDisplayMode_v7_6 **deckLinkDisplayMode);
+
+ END_INTERFACE
+ } IDeckLinkDisplayModeIterator_v7_6Vtbl;
+
+ interface IDeckLinkDisplayModeIterator_v7_6
+ {
+ CONST_VTBL struct IDeckLinkDisplayModeIterator_v7_6Vtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkDisplayModeIterator_v7_6_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkDisplayModeIterator_v7_6_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkDisplayModeIterator_v7_6_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkDisplayModeIterator_v7_6_Next(This,deckLinkDisplayMode) \
+ ( (This)->lpVtbl -> Next(This,deckLinkDisplayMode) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkDisplayModeIterator_v7_6_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkDisplayMode_v7_6_INTERFACE_DEFINED__
+#define __IDeckLinkDisplayMode_v7_6_INTERFACE_DEFINED__
+
+/* interface IDeckLinkDisplayMode_v7_6 */
+/* [helpstring][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkDisplayMode_v7_6;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("87451E84-2B7E-439E-A629-4393EA4A8550")
+ IDeckLinkDisplayMode_v7_6 : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE GetName(
+ /* [out] */ BSTR *name) = 0;
+
+ virtual BMDDisplayMode STDMETHODCALLTYPE GetDisplayMode( void) = 0;
+
+ virtual long STDMETHODCALLTYPE GetWidth( void) = 0;
+
+ virtual long STDMETHODCALLTYPE GetHeight( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetFrameRate(
+ /* [out] */ BMDTimeValue *frameDuration,
+ /* [out] */ BMDTimeScale *timeScale) = 0;
+
+ virtual BMDFieldDominance STDMETHODCALLTYPE GetFieldDominance( void) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkDisplayMode_v7_6Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkDisplayMode_v7_6 * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkDisplayMode_v7_6 * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkDisplayMode_v7_6 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetName )(
+ IDeckLinkDisplayMode_v7_6 * This,
+ /* [out] */ BSTR *name);
+
+ BMDDisplayMode ( STDMETHODCALLTYPE *GetDisplayMode )(
+ IDeckLinkDisplayMode_v7_6 * This);
+
+ long ( STDMETHODCALLTYPE *GetWidth )(
+ IDeckLinkDisplayMode_v7_6 * This);
+
+ long ( STDMETHODCALLTYPE *GetHeight )(
+ IDeckLinkDisplayMode_v7_6 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetFrameRate )(
+ IDeckLinkDisplayMode_v7_6 * This,
+ /* [out] */ BMDTimeValue *frameDuration,
+ /* [out] */ BMDTimeScale *timeScale);
+
+ BMDFieldDominance ( STDMETHODCALLTYPE *GetFieldDominance )(
+ IDeckLinkDisplayMode_v7_6 * This);
+
+ END_INTERFACE
+ } IDeckLinkDisplayMode_v7_6Vtbl;
+
+ interface IDeckLinkDisplayMode_v7_6
+ {
+ CONST_VTBL struct IDeckLinkDisplayMode_v7_6Vtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkDisplayMode_v7_6_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkDisplayMode_v7_6_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkDisplayMode_v7_6_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkDisplayMode_v7_6_GetName(This,name) \
+ ( (This)->lpVtbl -> GetName(This,name) )
+
+#define IDeckLinkDisplayMode_v7_6_GetDisplayMode(This) \
+ ( (This)->lpVtbl -> GetDisplayMode(This) )
+
+#define IDeckLinkDisplayMode_v7_6_GetWidth(This) \
+ ( (This)->lpVtbl -> GetWidth(This) )
+
+#define IDeckLinkDisplayMode_v7_6_GetHeight(This) \
+ ( (This)->lpVtbl -> GetHeight(This) )
+
+#define IDeckLinkDisplayMode_v7_6_GetFrameRate(This,frameDuration,timeScale) \
+ ( (This)->lpVtbl -> GetFrameRate(This,frameDuration,timeScale) )
+
+#define IDeckLinkDisplayMode_v7_6_GetFieldDominance(This) \
+ ( (This)->lpVtbl -> GetFieldDominance(This) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkDisplayMode_v7_6_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkOutput_v7_6_INTERFACE_DEFINED__
+#define __IDeckLinkOutput_v7_6_INTERFACE_DEFINED__
+
+/* interface IDeckLinkOutput_v7_6 */
+/* [helpstring][local][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkOutput_v7_6;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("29228142-EB8C-4141-A621-F74026450955")
+ IDeckLinkOutput_v7_6 : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE DoesSupportVideoMode(
+ BMDDisplayMode displayMode,
+ BMDPixelFormat pixelFormat,
+ /* [out] */ BMDDisplayModeSupport *result) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetDisplayModeIterator(
+ /* [out] */ IDeckLinkDisplayModeIterator_v7_6 **iterator) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetScreenPreviewCallback(
+ /* [in] */ IDeckLinkScreenPreviewCallback_v7_6 *previewCallback) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE EnableVideoOutput(
+ BMDDisplayMode displayMode,
+ BMDVideoOutputFlags flags) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE DisableVideoOutput( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetVideoOutputFrameMemoryAllocator(
+ /* [in] */ IDeckLinkMemoryAllocator *theAllocator) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE CreateVideoFrame(
+ int width,
+ int height,
+ int rowBytes,
+ BMDPixelFormat pixelFormat,
+ BMDFrameFlags flags,
+ /* [out] */ IDeckLinkMutableVideoFrame_v7_6 **outFrame) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE CreateAncillaryData(
+ BMDPixelFormat pixelFormat,
+ /* [out] */ IDeckLinkVideoFrameAncillary **outBuffer) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE DisplayVideoFrameSync(
+ /* [in] */ IDeckLinkVideoFrame_v7_6 *theFrame) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE ScheduleVideoFrame(
+ /* [in] */ IDeckLinkVideoFrame_v7_6 *theFrame,
+ BMDTimeValue displayTime,
+ BMDTimeValue displayDuration,
+ BMDTimeScale timeScale) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetScheduledFrameCompletionCallback(
+ /* [in] */ IDeckLinkVideoOutputCallback_v7_6 *theCallback) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetBufferedVideoFrameCount(
+ /* [out] */ unsigned int *bufferedFrameCount) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE EnableAudioOutput(
+ BMDAudioSampleRate sampleRate,
+ BMDAudioSampleType sampleType,
+ unsigned int channelCount,
+ BMDAudioOutputStreamType streamType) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE DisableAudioOutput( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE WriteAudioSamplesSync(
+ /* [in] */ void *buffer,
+ unsigned int sampleFrameCount,
+ /* [out] */ unsigned int *sampleFramesWritten) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE BeginAudioPreroll( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE EndAudioPreroll( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE ScheduleAudioSamples(
+ /* [in] */ void *buffer,
+ unsigned int sampleFrameCount,
+ BMDTimeValue streamTime,
+ BMDTimeScale timeScale,
+ /* [out] */ unsigned int *sampleFramesWritten) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetBufferedAudioSampleFrameCount(
+ /* [out] */ unsigned int *bufferedSampleFrameCount) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE FlushBufferedAudioSamples( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetAudioCallback(
+ /* [in] */ IDeckLinkAudioOutputCallback *theCallback) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE StartScheduledPlayback(
+ BMDTimeValue playbackStartTime,
+ BMDTimeScale timeScale,
+ double playbackSpeed) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE StopScheduledPlayback(
+ BMDTimeValue stopPlaybackAtTime,
+ /* [out] */ BMDTimeValue *actualStopTime,
+ BMDTimeScale timeScale) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE IsScheduledPlaybackRunning(
+ /* [out] */ BOOL *active) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetScheduledStreamTime(
+ BMDTimeScale desiredTimeScale,
+ /* [out] */ BMDTimeValue *streamTime,
+ /* [out] */ double *playbackSpeed) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetHardwareReferenceClock(
+ BMDTimeScale desiredTimeScale,
+ /* [out] */ BMDTimeValue *hardwareTime,
+ /* [out] */ BMDTimeValue *timeInFrame,
+ /* [out] */ BMDTimeValue *ticksPerFrame) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkOutput_v7_6Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkOutput_v7_6 * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkOutput_v7_6 * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkOutput_v7_6 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *DoesSupportVideoMode )(
+ IDeckLinkOutput_v7_6 * This,
+ BMDDisplayMode displayMode,
+ BMDPixelFormat pixelFormat,
+ /* [out] */ BMDDisplayModeSupport *result);
+
+ HRESULT ( STDMETHODCALLTYPE *GetDisplayModeIterator )(
+ IDeckLinkOutput_v7_6 * This,
+ /* [out] */ IDeckLinkDisplayModeIterator_v7_6 **iterator);
+
+ HRESULT ( STDMETHODCALLTYPE *SetScreenPreviewCallback )(
+ IDeckLinkOutput_v7_6 * This,
+ /* [in] */ IDeckLinkScreenPreviewCallback_v7_6 *previewCallback);
+
+ HRESULT ( STDMETHODCALLTYPE *EnableVideoOutput )(
+ IDeckLinkOutput_v7_6 * This,
+ BMDDisplayMode displayMode,
+ BMDVideoOutputFlags flags);
+
+ HRESULT ( STDMETHODCALLTYPE *DisableVideoOutput )(
+ IDeckLinkOutput_v7_6 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *SetVideoOutputFrameMemoryAllocator )(
+ IDeckLinkOutput_v7_6 * This,
+ /* [in] */ IDeckLinkMemoryAllocator *theAllocator);
+
+ HRESULT ( STDMETHODCALLTYPE *CreateVideoFrame )(
+ IDeckLinkOutput_v7_6 * This,
+ int width,
+ int height,
+ int rowBytes,
+ BMDPixelFormat pixelFormat,
+ BMDFrameFlags flags,
+ /* [out] */ IDeckLinkMutableVideoFrame_v7_6 **outFrame);
+
+ HRESULT ( STDMETHODCALLTYPE *CreateAncillaryData )(
+ IDeckLinkOutput_v7_6 * This,
+ BMDPixelFormat pixelFormat,
+ /* [out] */ IDeckLinkVideoFrameAncillary **outBuffer);
+
+ HRESULT ( STDMETHODCALLTYPE *DisplayVideoFrameSync )(
+ IDeckLinkOutput_v7_6 * This,
+ /* [in] */ IDeckLinkVideoFrame_v7_6 *theFrame);
+
+ HRESULT ( STDMETHODCALLTYPE *ScheduleVideoFrame )(
+ IDeckLinkOutput_v7_6 * This,
+ /* [in] */ IDeckLinkVideoFrame_v7_6 *theFrame,
+ BMDTimeValue displayTime,
+ BMDTimeValue displayDuration,
+ BMDTimeScale timeScale);
+
+ HRESULT ( STDMETHODCALLTYPE *SetScheduledFrameCompletionCallback )(
+ IDeckLinkOutput_v7_6 * This,
+ /* [in] */ IDeckLinkVideoOutputCallback_v7_6 *theCallback);
+
+ HRESULT ( STDMETHODCALLTYPE *GetBufferedVideoFrameCount )(
+ IDeckLinkOutput_v7_6 * This,
+ /* [out] */ unsigned int *bufferedFrameCount);
+
+ HRESULT ( STDMETHODCALLTYPE *EnableAudioOutput )(
+ IDeckLinkOutput_v7_6 * This,
+ BMDAudioSampleRate sampleRate,
+ BMDAudioSampleType sampleType,
+ unsigned int channelCount,
+ BMDAudioOutputStreamType streamType);
+
+ HRESULT ( STDMETHODCALLTYPE *DisableAudioOutput )(
+ IDeckLinkOutput_v7_6 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *WriteAudioSamplesSync )(
+ IDeckLinkOutput_v7_6 * This,
+ /* [in] */ void *buffer,
+ unsigned int sampleFrameCount,
+ /* [out] */ unsigned int *sampleFramesWritten);
+
+ HRESULT ( STDMETHODCALLTYPE *BeginAudioPreroll )(
+ IDeckLinkOutput_v7_6 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *EndAudioPreroll )(
+ IDeckLinkOutput_v7_6 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *ScheduleAudioSamples )(
+ IDeckLinkOutput_v7_6 * This,
+ /* [in] */ void *buffer,
+ unsigned int sampleFrameCount,
+ BMDTimeValue streamTime,
+ BMDTimeScale timeScale,
+ /* [out] */ unsigned int *sampleFramesWritten);
+
+ HRESULT ( STDMETHODCALLTYPE *GetBufferedAudioSampleFrameCount )(
+ IDeckLinkOutput_v7_6 * This,
+ /* [out] */ unsigned int *bufferedSampleFrameCount);
+
+ HRESULT ( STDMETHODCALLTYPE *FlushBufferedAudioSamples )(
+ IDeckLinkOutput_v7_6 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *SetAudioCallback )(
+ IDeckLinkOutput_v7_6 * This,
+ /* [in] */ IDeckLinkAudioOutputCallback *theCallback);
+
+ HRESULT ( STDMETHODCALLTYPE *StartScheduledPlayback )(
+ IDeckLinkOutput_v7_6 * This,
+ BMDTimeValue playbackStartTime,
+ BMDTimeScale timeScale,
+ double playbackSpeed);
+
+ HRESULT ( STDMETHODCALLTYPE *StopScheduledPlayback )(
+ IDeckLinkOutput_v7_6 * This,
+ BMDTimeValue stopPlaybackAtTime,
+ /* [out] */ BMDTimeValue *actualStopTime,
+ BMDTimeScale timeScale);
+
+ HRESULT ( STDMETHODCALLTYPE *IsScheduledPlaybackRunning )(
+ IDeckLinkOutput_v7_6 * This,
+ /* [out] */ BOOL *active);
+
+ HRESULT ( STDMETHODCALLTYPE *GetScheduledStreamTime )(
+ IDeckLinkOutput_v7_6 * This,
+ BMDTimeScale desiredTimeScale,
+ /* [out] */ BMDTimeValue *streamTime,
+ /* [out] */ double *playbackSpeed);
+
+ HRESULT ( STDMETHODCALLTYPE *GetHardwareReferenceClock )(
+ IDeckLinkOutput_v7_6 * This,
+ BMDTimeScale desiredTimeScale,
+ /* [out] */ BMDTimeValue *hardwareTime,
+ /* [out] */ BMDTimeValue *timeInFrame,
+ /* [out] */ BMDTimeValue *ticksPerFrame);
+
+ END_INTERFACE
+ } IDeckLinkOutput_v7_6Vtbl;
+
+ interface IDeckLinkOutput_v7_6
+ {
+ CONST_VTBL struct IDeckLinkOutput_v7_6Vtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkOutput_v7_6_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkOutput_v7_6_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkOutput_v7_6_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkOutput_v7_6_DoesSupportVideoMode(This,displayMode,pixelFormat,result) \
+ ( (This)->lpVtbl -> DoesSupportVideoMode(This,displayMode,pixelFormat,result) )
+
+#define IDeckLinkOutput_v7_6_GetDisplayModeIterator(This,iterator) \
+ ( (This)->lpVtbl -> GetDisplayModeIterator(This,iterator) )
+
+#define IDeckLinkOutput_v7_6_SetScreenPreviewCallback(This,previewCallback) \
+ ( (This)->lpVtbl -> SetScreenPreviewCallback(This,previewCallback) )
+
+#define IDeckLinkOutput_v7_6_EnableVideoOutput(This,displayMode,flags) \
+ ( (This)->lpVtbl -> EnableVideoOutput(This,displayMode,flags) )
+
+#define IDeckLinkOutput_v7_6_DisableVideoOutput(This) \
+ ( (This)->lpVtbl -> DisableVideoOutput(This) )
+
+#define IDeckLinkOutput_v7_6_SetVideoOutputFrameMemoryAllocator(This,theAllocator) \
+ ( (This)->lpVtbl -> SetVideoOutputFrameMemoryAllocator(This,theAllocator) )
+
+#define IDeckLinkOutput_v7_6_CreateVideoFrame(This,width,height,rowBytes,pixelFormat,flags,outFrame) \
+ ( (This)->lpVtbl -> CreateVideoFrame(This,width,height,rowBytes,pixelFormat,flags,outFrame) )
+
+#define IDeckLinkOutput_v7_6_CreateAncillaryData(This,pixelFormat,outBuffer) \
+ ( (This)->lpVtbl -> CreateAncillaryData(This,pixelFormat,outBuffer) )
+
+#define IDeckLinkOutput_v7_6_DisplayVideoFrameSync(This,theFrame) \
+ ( (This)->lpVtbl -> DisplayVideoFrameSync(This,theFrame) )
+
+#define IDeckLinkOutput_v7_6_ScheduleVideoFrame(This,theFrame,displayTime,displayDuration,timeScale) \
+ ( (This)->lpVtbl -> ScheduleVideoFrame(This,theFrame,displayTime,displayDuration,timeScale) )
+
+#define IDeckLinkOutput_v7_6_SetScheduledFrameCompletionCallback(This,theCallback) \
+ ( (This)->lpVtbl -> SetScheduledFrameCompletionCallback(This,theCallback) )
+
+#define IDeckLinkOutput_v7_6_GetBufferedVideoFrameCount(This,bufferedFrameCount) \
+ ( (This)->lpVtbl -> GetBufferedVideoFrameCount(This,bufferedFrameCount) )
+
+#define IDeckLinkOutput_v7_6_EnableAudioOutput(This,sampleRate,sampleType,channelCount,streamType) \
+ ( (This)->lpVtbl -> EnableAudioOutput(This,sampleRate,sampleType,channelCount,streamType) )
+
+#define IDeckLinkOutput_v7_6_DisableAudioOutput(This) \
+ ( (This)->lpVtbl -> DisableAudioOutput(This) )
+
+#define IDeckLinkOutput_v7_6_WriteAudioSamplesSync(This,buffer,sampleFrameCount,sampleFramesWritten) \
+ ( (This)->lpVtbl -> WriteAudioSamplesSync(This,buffer,sampleFrameCount,sampleFramesWritten) )
+
+#define IDeckLinkOutput_v7_6_BeginAudioPreroll(This) \
+ ( (This)->lpVtbl -> BeginAudioPreroll(This) )
+
+#define IDeckLinkOutput_v7_6_EndAudioPreroll(This) \
+ ( (This)->lpVtbl -> EndAudioPreroll(This) )
+
+#define IDeckLinkOutput_v7_6_ScheduleAudioSamples(This,buffer,sampleFrameCount,streamTime,timeScale,sampleFramesWritten) \
+ ( (This)->lpVtbl -> ScheduleAudioSamples(This,buffer,sampleFrameCount,streamTime,timeScale,sampleFramesWritten) )
+
+#define IDeckLinkOutput_v7_6_GetBufferedAudioSampleFrameCount(This,bufferedSampleFrameCount) \
+ ( (This)->lpVtbl -> GetBufferedAudioSampleFrameCount(This,bufferedSampleFrameCount) )
+
+#define IDeckLinkOutput_v7_6_FlushBufferedAudioSamples(This) \
+ ( (This)->lpVtbl -> FlushBufferedAudioSamples(This) )
+
+#define IDeckLinkOutput_v7_6_SetAudioCallback(This,theCallback) \
+ ( (This)->lpVtbl -> SetAudioCallback(This,theCallback) )
+
+#define IDeckLinkOutput_v7_6_StartScheduledPlayback(This,playbackStartTime,timeScale,playbackSpeed) \
+ ( (This)->lpVtbl -> StartScheduledPlayback(This,playbackStartTime,timeScale,playbackSpeed) )
+
+#define IDeckLinkOutput_v7_6_StopScheduledPlayback(This,stopPlaybackAtTime,actualStopTime,timeScale) \
+ ( (This)->lpVtbl -> StopScheduledPlayback(This,stopPlaybackAtTime,actualStopTime,timeScale) )
+
+#define IDeckLinkOutput_v7_6_IsScheduledPlaybackRunning(This,active) \
+ ( (This)->lpVtbl -> IsScheduledPlaybackRunning(This,active) )
+
+#define IDeckLinkOutput_v7_6_GetScheduledStreamTime(This,desiredTimeScale,streamTime,playbackSpeed) \
+ ( (This)->lpVtbl -> GetScheduledStreamTime(This,desiredTimeScale,streamTime,playbackSpeed) )
+
+#define IDeckLinkOutput_v7_6_GetHardwareReferenceClock(This,desiredTimeScale,hardwareTime,timeInFrame,ticksPerFrame) \
+ ( (This)->lpVtbl -> GetHardwareReferenceClock(This,desiredTimeScale,hardwareTime,timeInFrame,ticksPerFrame) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkOutput_v7_6_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkInput_v7_6_INTERFACE_DEFINED__
+#define __IDeckLinkInput_v7_6_INTERFACE_DEFINED__
+
+/* interface IDeckLinkInput_v7_6 */
+/* [helpstring][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkInput_v7_6;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("300C135A-9F43-48E2-9906-6D7911D93CF1")
+ IDeckLinkInput_v7_6 : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE DoesSupportVideoMode(
+ BMDDisplayMode displayMode,
+ BMDPixelFormat pixelFormat,
+ /* [out] */ BMDDisplayModeSupport *result) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetDisplayModeIterator(
+ /* [out] */ IDeckLinkDisplayModeIterator_v7_6 **iterator) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetScreenPreviewCallback(
+ /* [in] */ IDeckLinkScreenPreviewCallback_v7_6 *previewCallback) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE EnableVideoInput(
+ BMDDisplayMode displayMode,
+ BMDPixelFormat pixelFormat,
+ BMDVideoInputFlags flags) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE DisableVideoInput( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetAvailableVideoFrameCount(
+ /* [out] */ unsigned int *availableFrameCount) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE EnableAudioInput(
+ BMDAudioSampleRate sampleRate,
+ BMDAudioSampleType sampleType,
+ unsigned int channelCount) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE DisableAudioInput( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetAvailableAudioSampleFrameCount(
+ /* [out] */ unsigned int *availableSampleFrameCount) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE StartStreams( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE StopStreams( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE PauseStreams( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE FlushStreams( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetCallback(
+ /* [in] */ IDeckLinkInputCallback_v7_6 *theCallback) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetHardwareReferenceClock(
+ BMDTimeScale desiredTimeScale,
+ /* [out] */ BMDTimeValue *hardwareTime,
+ /* [out] */ BMDTimeValue *timeInFrame,
+ /* [out] */ BMDTimeValue *ticksPerFrame) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkInput_v7_6Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkInput_v7_6 * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkInput_v7_6 * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkInput_v7_6 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *DoesSupportVideoMode )(
+ IDeckLinkInput_v7_6 * This,
+ BMDDisplayMode displayMode,
+ BMDPixelFormat pixelFormat,
+ /* [out] */ BMDDisplayModeSupport *result);
+
+ HRESULT ( STDMETHODCALLTYPE *GetDisplayModeIterator )(
+ IDeckLinkInput_v7_6 * This,
+ /* [out] */ IDeckLinkDisplayModeIterator_v7_6 **iterator);
+
+ HRESULT ( STDMETHODCALLTYPE *SetScreenPreviewCallback )(
+ IDeckLinkInput_v7_6 * This,
+ /* [in] */ IDeckLinkScreenPreviewCallback_v7_6 *previewCallback);
+
+ HRESULT ( STDMETHODCALLTYPE *EnableVideoInput )(
+ IDeckLinkInput_v7_6 * This,
+ BMDDisplayMode displayMode,
+ BMDPixelFormat pixelFormat,
+ BMDVideoInputFlags flags);
+
+ HRESULT ( STDMETHODCALLTYPE *DisableVideoInput )(
+ IDeckLinkInput_v7_6 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetAvailableVideoFrameCount )(
+ IDeckLinkInput_v7_6 * This,
+ /* [out] */ unsigned int *availableFrameCount);
+
+ HRESULT ( STDMETHODCALLTYPE *EnableAudioInput )(
+ IDeckLinkInput_v7_6 * This,
+ BMDAudioSampleRate sampleRate,
+ BMDAudioSampleType sampleType,
+ unsigned int channelCount);
+
+ HRESULT ( STDMETHODCALLTYPE *DisableAudioInput )(
+ IDeckLinkInput_v7_6 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetAvailableAudioSampleFrameCount )(
+ IDeckLinkInput_v7_6 * This,
+ /* [out] */ unsigned int *availableSampleFrameCount);
+
+ HRESULT ( STDMETHODCALLTYPE *StartStreams )(
+ IDeckLinkInput_v7_6 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *StopStreams )(
+ IDeckLinkInput_v7_6 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *PauseStreams )(
+ IDeckLinkInput_v7_6 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *FlushStreams )(
+ IDeckLinkInput_v7_6 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *SetCallback )(
+ IDeckLinkInput_v7_6 * This,
+ /* [in] */ IDeckLinkInputCallback_v7_6 *theCallback);
+
+ HRESULT ( STDMETHODCALLTYPE *GetHardwareReferenceClock )(
+ IDeckLinkInput_v7_6 * This,
+ BMDTimeScale desiredTimeScale,
+ /* [out] */ BMDTimeValue *hardwareTime,
+ /* [out] */ BMDTimeValue *timeInFrame,
+ /* [out] */ BMDTimeValue *ticksPerFrame);
+
+ END_INTERFACE
+ } IDeckLinkInput_v7_6Vtbl;
+
+ interface IDeckLinkInput_v7_6
+ {
+ CONST_VTBL struct IDeckLinkInput_v7_6Vtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkInput_v7_6_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkInput_v7_6_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkInput_v7_6_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkInput_v7_6_DoesSupportVideoMode(This,displayMode,pixelFormat,result) \
+ ( (This)->lpVtbl -> DoesSupportVideoMode(This,displayMode,pixelFormat,result) )
+
+#define IDeckLinkInput_v7_6_GetDisplayModeIterator(This,iterator) \
+ ( (This)->lpVtbl -> GetDisplayModeIterator(This,iterator) )
+
+#define IDeckLinkInput_v7_6_SetScreenPreviewCallback(This,previewCallback) \
+ ( (This)->lpVtbl -> SetScreenPreviewCallback(This,previewCallback) )
+
+#define IDeckLinkInput_v7_6_EnableVideoInput(This,displayMode,pixelFormat,flags) \
+ ( (This)->lpVtbl -> EnableVideoInput(This,displayMode,pixelFormat,flags) )
+
+#define IDeckLinkInput_v7_6_DisableVideoInput(This) \
+ ( (This)->lpVtbl -> DisableVideoInput(This) )
+
+#define IDeckLinkInput_v7_6_GetAvailableVideoFrameCount(This,availableFrameCount) \
+ ( (This)->lpVtbl -> GetAvailableVideoFrameCount(This,availableFrameCount) )
+
+#define IDeckLinkInput_v7_6_EnableAudioInput(This,sampleRate,sampleType,channelCount) \
+ ( (This)->lpVtbl -> EnableAudioInput(This,sampleRate,sampleType,channelCount) )
+
+#define IDeckLinkInput_v7_6_DisableAudioInput(This) \
+ ( (This)->lpVtbl -> DisableAudioInput(This) )
+
+#define IDeckLinkInput_v7_6_GetAvailableAudioSampleFrameCount(This,availableSampleFrameCount) \
+ ( (This)->lpVtbl -> GetAvailableAudioSampleFrameCount(This,availableSampleFrameCount) )
+
+#define IDeckLinkInput_v7_6_StartStreams(This) \
+ ( (This)->lpVtbl -> StartStreams(This) )
+
+#define IDeckLinkInput_v7_6_StopStreams(This) \
+ ( (This)->lpVtbl -> StopStreams(This) )
+
+#define IDeckLinkInput_v7_6_PauseStreams(This) \
+ ( (This)->lpVtbl -> PauseStreams(This) )
+
+#define IDeckLinkInput_v7_6_FlushStreams(This) \
+ ( (This)->lpVtbl -> FlushStreams(This) )
+
+#define IDeckLinkInput_v7_6_SetCallback(This,theCallback) \
+ ( (This)->lpVtbl -> SetCallback(This,theCallback) )
+
+#define IDeckLinkInput_v7_6_GetHardwareReferenceClock(This,desiredTimeScale,hardwareTime,timeInFrame,ticksPerFrame) \
+ ( (This)->lpVtbl -> GetHardwareReferenceClock(This,desiredTimeScale,hardwareTime,timeInFrame,ticksPerFrame) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkInput_v7_6_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkTimecode_v7_6_INTERFACE_DEFINED__
+#define __IDeckLinkTimecode_v7_6_INTERFACE_DEFINED__
+
+/* interface IDeckLinkTimecode_v7_6 */
+/* [helpstring][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkTimecode_v7_6;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("EFB9BCA6-A521-44F7-BD69-2332F24D9EE6")
+ IDeckLinkTimecode_v7_6 : public IUnknown
+ {
+ public:
+ virtual BMDTimecodeBCD STDMETHODCALLTYPE GetBCD( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetComponents(
+ /* [out] */ unsigned char *hours,
+ /* [out] */ unsigned char *minutes,
+ /* [out] */ unsigned char *seconds,
+ /* [out] */ unsigned char *frames) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetString(
+ /* [out] */ BSTR *timecode) = 0;
+
+ virtual BMDTimecodeFlags STDMETHODCALLTYPE GetFlags( void) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkTimecode_v7_6Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkTimecode_v7_6 * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkTimecode_v7_6 * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkTimecode_v7_6 * This);
+
+ BMDTimecodeBCD ( STDMETHODCALLTYPE *GetBCD )(
+ IDeckLinkTimecode_v7_6 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetComponents )(
+ IDeckLinkTimecode_v7_6 * This,
+ /* [out] */ unsigned char *hours,
+ /* [out] */ unsigned char *minutes,
+ /* [out] */ unsigned char *seconds,
+ /* [out] */ unsigned char *frames);
+
+ HRESULT ( STDMETHODCALLTYPE *GetString )(
+ IDeckLinkTimecode_v7_6 * This,
+ /* [out] */ BSTR *timecode);
+
+ BMDTimecodeFlags ( STDMETHODCALLTYPE *GetFlags )(
+ IDeckLinkTimecode_v7_6 * This);
+
+ END_INTERFACE
+ } IDeckLinkTimecode_v7_6Vtbl;
+
+ interface IDeckLinkTimecode_v7_6
+ {
+ CONST_VTBL struct IDeckLinkTimecode_v7_6Vtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkTimecode_v7_6_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkTimecode_v7_6_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkTimecode_v7_6_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkTimecode_v7_6_GetBCD(This) \
+ ( (This)->lpVtbl -> GetBCD(This) )
+
+#define IDeckLinkTimecode_v7_6_GetComponents(This,hours,minutes,seconds,frames) \
+ ( (This)->lpVtbl -> GetComponents(This,hours,minutes,seconds,frames) )
+
+#define IDeckLinkTimecode_v7_6_GetString(This,timecode) \
+ ( (This)->lpVtbl -> GetString(This,timecode) )
+
+#define IDeckLinkTimecode_v7_6_GetFlags(This) \
+ ( (This)->lpVtbl -> GetFlags(This) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkTimecode_v7_6_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkVideoFrame_v7_6_INTERFACE_DEFINED__
+#define __IDeckLinkVideoFrame_v7_6_INTERFACE_DEFINED__
+
+/* interface IDeckLinkVideoFrame_v7_6 */
+/* [helpstring][local][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkVideoFrame_v7_6;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("A8D8238E-6B18-4196-99E1-5AF717B83D32")
+ IDeckLinkVideoFrame_v7_6 : public IUnknown
+ {
+ public:
+ virtual long STDMETHODCALLTYPE GetWidth( void) = 0;
+
+ virtual long STDMETHODCALLTYPE GetHeight( void) = 0;
+
+ virtual long STDMETHODCALLTYPE GetRowBytes( void) = 0;
+
+ virtual BMDPixelFormat STDMETHODCALLTYPE GetPixelFormat( void) = 0;
+
+ virtual BMDFrameFlags STDMETHODCALLTYPE GetFlags( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetBytes(
+ /* [out] */ void **buffer) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetTimecode(
+ BMDTimecodeFormat format,
+ /* [out] */ IDeckLinkTimecode_v7_6 **timecode) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetAncillaryData(
+ /* [out] */ IDeckLinkVideoFrameAncillary **ancillary) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkVideoFrame_v7_6Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkVideoFrame_v7_6 * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkVideoFrame_v7_6 * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkVideoFrame_v7_6 * This);
+
+ long ( STDMETHODCALLTYPE *GetWidth )(
+ IDeckLinkVideoFrame_v7_6 * This);
+
+ long ( STDMETHODCALLTYPE *GetHeight )(
+ IDeckLinkVideoFrame_v7_6 * This);
+
+ long ( STDMETHODCALLTYPE *GetRowBytes )(
+ IDeckLinkVideoFrame_v7_6 * This);
+
+ BMDPixelFormat ( STDMETHODCALLTYPE *GetPixelFormat )(
+ IDeckLinkVideoFrame_v7_6 * This);
+
+ BMDFrameFlags ( STDMETHODCALLTYPE *GetFlags )(
+ IDeckLinkVideoFrame_v7_6 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetBytes )(
+ IDeckLinkVideoFrame_v7_6 * This,
+ /* [out] */ void **buffer);
+
+ HRESULT ( STDMETHODCALLTYPE *GetTimecode )(
+ IDeckLinkVideoFrame_v7_6 * This,
+ BMDTimecodeFormat format,
+ /* [out] */ IDeckLinkTimecode_v7_6 **timecode);
+
+ HRESULT ( STDMETHODCALLTYPE *GetAncillaryData )(
+ IDeckLinkVideoFrame_v7_6 * This,
+ /* [out] */ IDeckLinkVideoFrameAncillary **ancillary);
+
+ END_INTERFACE
+ } IDeckLinkVideoFrame_v7_6Vtbl;
+
+ interface IDeckLinkVideoFrame_v7_6
+ {
+ CONST_VTBL struct IDeckLinkVideoFrame_v7_6Vtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkVideoFrame_v7_6_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkVideoFrame_v7_6_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkVideoFrame_v7_6_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkVideoFrame_v7_6_GetWidth(This) \
+ ( (This)->lpVtbl -> GetWidth(This) )
+
+#define IDeckLinkVideoFrame_v7_6_GetHeight(This) \
+ ( (This)->lpVtbl -> GetHeight(This) )
+
+#define IDeckLinkVideoFrame_v7_6_GetRowBytes(This) \
+ ( (This)->lpVtbl -> GetRowBytes(This) )
+
+#define IDeckLinkVideoFrame_v7_6_GetPixelFormat(This) \
+ ( (This)->lpVtbl -> GetPixelFormat(This) )
+
+#define IDeckLinkVideoFrame_v7_6_GetFlags(This) \
+ ( (This)->lpVtbl -> GetFlags(This) )
+
+#define IDeckLinkVideoFrame_v7_6_GetBytes(This,buffer) \
+ ( (This)->lpVtbl -> GetBytes(This,buffer) )
+
+#define IDeckLinkVideoFrame_v7_6_GetTimecode(This,format,timecode) \
+ ( (This)->lpVtbl -> GetTimecode(This,format,timecode) )
+
+#define IDeckLinkVideoFrame_v7_6_GetAncillaryData(This,ancillary) \
+ ( (This)->lpVtbl -> GetAncillaryData(This,ancillary) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkVideoFrame_v7_6_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkMutableVideoFrame_v7_6_INTERFACE_DEFINED__
+#define __IDeckLinkMutableVideoFrame_v7_6_INTERFACE_DEFINED__
+
+/* interface IDeckLinkMutableVideoFrame_v7_6 */
+/* [helpstring][local][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkMutableVideoFrame_v7_6;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("46FCEE00-B4E6-43D0-91C0-023A7FCEB34F")
+ IDeckLinkMutableVideoFrame_v7_6 : public IDeckLinkVideoFrame_v7_6
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE SetFlags(
+ BMDFrameFlags newFlags) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetTimecode(
+ BMDTimecodeFormat format,
+ /* [in] */ IDeckLinkTimecode_v7_6 *timecode) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetTimecodeFromComponents(
+ BMDTimecodeFormat format,
+ unsigned char hours,
+ unsigned char minutes,
+ unsigned char seconds,
+ unsigned char frames,
+ BMDTimecodeFlags flags) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetAncillaryData(
+ /* [in] */ IDeckLinkVideoFrameAncillary *ancillary) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkMutableVideoFrame_v7_6Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkMutableVideoFrame_v7_6 * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkMutableVideoFrame_v7_6 * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkMutableVideoFrame_v7_6 * This);
+
+ long ( STDMETHODCALLTYPE *GetWidth )(
+ IDeckLinkMutableVideoFrame_v7_6 * This);
+
+ long ( STDMETHODCALLTYPE *GetHeight )(
+ IDeckLinkMutableVideoFrame_v7_6 * This);
+
+ long ( STDMETHODCALLTYPE *GetRowBytes )(
+ IDeckLinkMutableVideoFrame_v7_6 * This);
+
+ BMDPixelFormat ( STDMETHODCALLTYPE *GetPixelFormat )(
+ IDeckLinkMutableVideoFrame_v7_6 * This);
+
+ BMDFrameFlags ( STDMETHODCALLTYPE *GetFlags )(
+ IDeckLinkMutableVideoFrame_v7_6 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetBytes )(
+ IDeckLinkMutableVideoFrame_v7_6 * This,
+ /* [out] */ void **buffer);
+
+ HRESULT ( STDMETHODCALLTYPE *GetTimecode )(
+ IDeckLinkMutableVideoFrame_v7_6 * This,
+ BMDTimecodeFormat format,
+ /* [out] */ IDeckLinkTimecode_v7_6 **timecode);
+
+ HRESULT ( STDMETHODCALLTYPE *GetAncillaryData )(
+ IDeckLinkMutableVideoFrame_v7_6 * This,
+ /* [out] */ IDeckLinkVideoFrameAncillary **ancillary);
+
+ HRESULT ( STDMETHODCALLTYPE *SetFlags )(
+ IDeckLinkMutableVideoFrame_v7_6 * This,
+ BMDFrameFlags newFlags);
+
+ HRESULT ( STDMETHODCALLTYPE *SetTimecode )(
+ IDeckLinkMutableVideoFrame_v7_6 * This,
+ BMDTimecodeFormat format,
+ /* [in] */ IDeckLinkTimecode_v7_6 *timecode);
+
+ HRESULT ( STDMETHODCALLTYPE *SetTimecodeFromComponents )(
+ IDeckLinkMutableVideoFrame_v7_6 * This,
+ BMDTimecodeFormat format,
+ unsigned char hours,
+ unsigned char minutes,
+ unsigned char seconds,
+ unsigned char frames,
+ BMDTimecodeFlags flags);
+
+ HRESULT ( STDMETHODCALLTYPE *SetAncillaryData )(
+ IDeckLinkMutableVideoFrame_v7_6 * This,
+ /* [in] */ IDeckLinkVideoFrameAncillary *ancillary);
+
+ END_INTERFACE
+ } IDeckLinkMutableVideoFrame_v7_6Vtbl;
+
+ interface IDeckLinkMutableVideoFrame_v7_6
+ {
+ CONST_VTBL struct IDeckLinkMutableVideoFrame_v7_6Vtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkMutableVideoFrame_v7_6_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkMutableVideoFrame_v7_6_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkMutableVideoFrame_v7_6_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkMutableVideoFrame_v7_6_GetWidth(This) \
+ ( (This)->lpVtbl -> GetWidth(This) )
+
+#define IDeckLinkMutableVideoFrame_v7_6_GetHeight(This) \
+ ( (This)->lpVtbl -> GetHeight(This) )
+
+#define IDeckLinkMutableVideoFrame_v7_6_GetRowBytes(This) \
+ ( (This)->lpVtbl -> GetRowBytes(This) )
+
+#define IDeckLinkMutableVideoFrame_v7_6_GetPixelFormat(This) \
+ ( (This)->lpVtbl -> GetPixelFormat(This) )
+
+#define IDeckLinkMutableVideoFrame_v7_6_GetFlags(This) \
+ ( (This)->lpVtbl -> GetFlags(This) )
+
+#define IDeckLinkMutableVideoFrame_v7_6_GetBytes(This,buffer) \
+ ( (This)->lpVtbl -> GetBytes(This,buffer) )
+
+#define IDeckLinkMutableVideoFrame_v7_6_GetTimecode(This,format,timecode) \
+ ( (This)->lpVtbl -> GetTimecode(This,format,timecode) )
+
+#define IDeckLinkMutableVideoFrame_v7_6_GetAncillaryData(This,ancillary) \
+ ( (This)->lpVtbl -> GetAncillaryData(This,ancillary) )
+
+
+#define IDeckLinkMutableVideoFrame_v7_6_SetFlags(This,newFlags) \
+ ( (This)->lpVtbl -> SetFlags(This,newFlags) )
+
+#define IDeckLinkMutableVideoFrame_v7_6_SetTimecode(This,format,timecode) \
+ ( (This)->lpVtbl -> SetTimecode(This,format,timecode) )
+
+#define IDeckLinkMutableVideoFrame_v7_6_SetTimecodeFromComponents(This,format,hours,minutes,seconds,frames,flags) \
+ ( (This)->lpVtbl -> SetTimecodeFromComponents(This,format,hours,minutes,seconds,frames,flags) )
+
+#define IDeckLinkMutableVideoFrame_v7_6_SetAncillaryData(This,ancillary) \
+ ( (This)->lpVtbl -> SetAncillaryData(This,ancillary) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkMutableVideoFrame_v7_6_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkVideoInputFrame_v7_6_INTERFACE_DEFINED__
+#define __IDeckLinkVideoInputFrame_v7_6_INTERFACE_DEFINED__
+
+/* interface IDeckLinkVideoInputFrame_v7_6 */
+/* [helpstring][local][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkVideoInputFrame_v7_6;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("9A74FA41-AE9F-47AC-8CF4-01F42DD59965")
+ IDeckLinkVideoInputFrame_v7_6 : public IDeckLinkVideoFrame_v7_6
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE GetStreamTime(
+ /* [out] */ BMDTimeValue *frameTime,
+ /* [out] */ BMDTimeValue *frameDuration,
+ BMDTimeScale timeScale) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetHardwareReferenceTimestamp(
+ BMDTimeScale timeScale,
+ /* [out] */ BMDTimeValue *frameTime,
+ /* [out] */ BMDTimeValue *frameDuration) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkVideoInputFrame_v7_6Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkVideoInputFrame_v7_6 * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkVideoInputFrame_v7_6 * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkVideoInputFrame_v7_6 * This);
+
+ long ( STDMETHODCALLTYPE *GetWidth )(
+ IDeckLinkVideoInputFrame_v7_6 * This);
+
+ long ( STDMETHODCALLTYPE *GetHeight )(
+ IDeckLinkVideoInputFrame_v7_6 * This);
+
+ long ( STDMETHODCALLTYPE *GetRowBytes )(
+ IDeckLinkVideoInputFrame_v7_6 * This);
+
+ BMDPixelFormat ( STDMETHODCALLTYPE *GetPixelFormat )(
+ IDeckLinkVideoInputFrame_v7_6 * This);
+
+ BMDFrameFlags ( STDMETHODCALLTYPE *GetFlags )(
+ IDeckLinkVideoInputFrame_v7_6 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetBytes )(
+ IDeckLinkVideoInputFrame_v7_6 * This,
+ /* [out] */ void **buffer);
+
+ HRESULT ( STDMETHODCALLTYPE *GetTimecode )(
+ IDeckLinkVideoInputFrame_v7_6 * This,
+ BMDTimecodeFormat format,
+ /* [out] */ IDeckLinkTimecode_v7_6 **timecode);
+
+ HRESULT ( STDMETHODCALLTYPE *GetAncillaryData )(
+ IDeckLinkVideoInputFrame_v7_6 * This,
+ /* [out] */ IDeckLinkVideoFrameAncillary **ancillary);
+
+ HRESULT ( STDMETHODCALLTYPE *GetStreamTime )(
+ IDeckLinkVideoInputFrame_v7_6 * This,
+ /* [out] */ BMDTimeValue *frameTime,
+ /* [out] */ BMDTimeValue *frameDuration,
+ BMDTimeScale timeScale);
+
+ HRESULT ( STDMETHODCALLTYPE *GetHardwareReferenceTimestamp )(
+ IDeckLinkVideoInputFrame_v7_6 * This,
+ BMDTimeScale timeScale,
+ /* [out] */ BMDTimeValue *frameTime,
+ /* [out] */ BMDTimeValue *frameDuration);
+
+ END_INTERFACE
+ } IDeckLinkVideoInputFrame_v7_6Vtbl;
+
+ interface IDeckLinkVideoInputFrame_v7_6
+ {
+ CONST_VTBL struct IDeckLinkVideoInputFrame_v7_6Vtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkVideoInputFrame_v7_6_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkVideoInputFrame_v7_6_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkVideoInputFrame_v7_6_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkVideoInputFrame_v7_6_GetWidth(This) \
+ ( (This)->lpVtbl -> GetWidth(This) )
+
+#define IDeckLinkVideoInputFrame_v7_6_GetHeight(This) \
+ ( (This)->lpVtbl -> GetHeight(This) )
+
+#define IDeckLinkVideoInputFrame_v7_6_GetRowBytes(This) \
+ ( (This)->lpVtbl -> GetRowBytes(This) )
+
+#define IDeckLinkVideoInputFrame_v7_6_GetPixelFormat(This) \
+ ( (This)->lpVtbl -> GetPixelFormat(This) )
+
+#define IDeckLinkVideoInputFrame_v7_6_GetFlags(This) \
+ ( (This)->lpVtbl -> GetFlags(This) )
+
+#define IDeckLinkVideoInputFrame_v7_6_GetBytes(This,buffer) \
+ ( (This)->lpVtbl -> GetBytes(This,buffer) )
+
+#define IDeckLinkVideoInputFrame_v7_6_GetTimecode(This,format,timecode) \
+ ( (This)->lpVtbl -> GetTimecode(This,format,timecode) )
+
+#define IDeckLinkVideoInputFrame_v7_6_GetAncillaryData(This,ancillary) \
+ ( (This)->lpVtbl -> GetAncillaryData(This,ancillary) )
+
+
+#define IDeckLinkVideoInputFrame_v7_6_GetStreamTime(This,frameTime,frameDuration,timeScale) \
+ ( (This)->lpVtbl -> GetStreamTime(This,frameTime,frameDuration,timeScale) )
+
+#define IDeckLinkVideoInputFrame_v7_6_GetHardwareReferenceTimestamp(This,timeScale,frameTime,frameDuration) \
+ ( (This)->lpVtbl -> GetHardwareReferenceTimestamp(This,timeScale,frameTime,frameDuration) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkVideoInputFrame_v7_6_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkScreenPreviewCallback_v7_6_INTERFACE_DEFINED__
+#define __IDeckLinkScreenPreviewCallback_v7_6_INTERFACE_DEFINED__
+
+/* interface IDeckLinkScreenPreviewCallback_v7_6 */
+/* [helpstring][local][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkScreenPreviewCallback_v7_6;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("373F499D-4B4D-4518-AD22-6354E5A5825E")
+ IDeckLinkScreenPreviewCallback_v7_6 : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE DrawFrame(
+ /* [in] */ IDeckLinkVideoFrame_v7_6 *theFrame) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkScreenPreviewCallback_v7_6Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkScreenPreviewCallback_v7_6 * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkScreenPreviewCallback_v7_6 * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkScreenPreviewCallback_v7_6 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *DrawFrame )(
+ IDeckLinkScreenPreviewCallback_v7_6 * This,
+ /* [in] */ IDeckLinkVideoFrame_v7_6 *theFrame);
+
+ END_INTERFACE
+ } IDeckLinkScreenPreviewCallback_v7_6Vtbl;
+
+ interface IDeckLinkScreenPreviewCallback_v7_6
+ {
+ CONST_VTBL struct IDeckLinkScreenPreviewCallback_v7_6Vtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkScreenPreviewCallback_v7_6_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkScreenPreviewCallback_v7_6_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkScreenPreviewCallback_v7_6_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkScreenPreviewCallback_v7_6_DrawFrame(This,theFrame) \
+ ( (This)->lpVtbl -> DrawFrame(This,theFrame) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkScreenPreviewCallback_v7_6_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkGLScreenPreviewHelper_v7_6_INTERFACE_DEFINED__
+#define __IDeckLinkGLScreenPreviewHelper_v7_6_INTERFACE_DEFINED__
+
+/* interface IDeckLinkGLScreenPreviewHelper_v7_6 */
+/* [helpstring][local][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkGLScreenPreviewHelper_v7_6;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("BA575CD9-A15E-497B-B2C2-F9AFE7BE4EBA")
+ IDeckLinkGLScreenPreviewHelper_v7_6 : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE InitializeGL( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE PaintGL( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetFrame(
+ /* [in] */ IDeckLinkVideoFrame_v7_6 *theFrame) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkGLScreenPreviewHelper_v7_6Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkGLScreenPreviewHelper_v7_6 * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkGLScreenPreviewHelper_v7_6 * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkGLScreenPreviewHelper_v7_6 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *InitializeGL )(
+ IDeckLinkGLScreenPreviewHelper_v7_6 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *PaintGL )(
+ IDeckLinkGLScreenPreviewHelper_v7_6 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *SetFrame )(
+ IDeckLinkGLScreenPreviewHelper_v7_6 * This,
+ /* [in] */ IDeckLinkVideoFrame_v7_6 *theFrame);
+
+ END_INTERFACE
+ } IDeckLinkGLScreenPreviewHelper_v7_6Vtbl;
+
+ interface IDeckLinkGLScreenPreviewHelper_v7_6
+ {
+ CONST_VTBL struct IDeckLinkGLScreenPreviewHelper_v7_6Vtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkGLScreenPreviewHelper_v7_6_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkGLScreenPreviewHelper_v7_6_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkGLScreenPreviewHelper_v7_6_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkGLScreenPreviewHelper_v7_6_InitializeGL(This) \
+ ( (This)->lpVtbl -> InitializeGL(This) )
+
+#define IDeckLinkGLScreenPreviewHelper_v7_6_PaintGL(This) \
+ ( (This)->lpVtbl -> PaintGL(This) )
+
+#define IDeckLinkGLScreenPreviewHelper_v7_6_SetFrame(This,theFrame) \
+ ( (This)->lpVtbl -> SetFrame(This,theFrame) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkGLScreenPreviewHelper_v7_6_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkVideoConversion_v7_6_INTERFACE_DEFINED__
+#define __IDeckLinkVideoConversion_v7_6_INTERFACE_DEFINED__
+
+/* interface IDeckLinkVideoConversion_v7_6 */
+/* [helpstring][local][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkVideoConversion_v7_6;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("3EB504C9-F97D-40FE-A158-D407D48CB53B")
+ IDeckLinkVideoConversion_v7_6 : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE ConvertFrame(
+ /* [in] */ IDeckLinkVideoFrame_v7_6 *srcFrame,
+ /* [in] */ IDeckLinkVideoFrame_v7_6 *dstFrame) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkVideoConversion_v7_6Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkVideoConversion_v7_6 * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkVideoConversion_v7_6 * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkVideoConversion_v7_6 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *ConvertFrame )(
+ IDeckLinkVideoConversion_v7_6 * This,
+ /* [in] */ IDeckLinkVideoFrame_v7_6 *srcFrame,
+ /* [in] */ IDeckLinkVideoFrame_v7_6 *dstFrame);
+
+ END_INTERFACE
+ } IDeckLinkVideoConversion_v7_6Vtbl;
+
+ interface IDeckLinkVideoConversion_v7_6
+ {
+ CONST_VTBL struct IDeckLinkVideoConversion_v7_6Vtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkVideoConversion_v7_6_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkVideoConversion_v7_6_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkVideoConversion_v7_6_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkVideoConversion_v7_6_ConvertFrame(This,srcFrame,dstFrame) \
+ ( (This)->lpVtbl -> ConvertFrame(This,srcFrame,dstFrame) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkVideoConversion_v7_6_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkConfiguration_v7_6_INTERFACE_DEFINED__
+#define __IDeckLinkConfiguration_v7_6_INTERFACE_DEFINED__
+
+/* interface IDeckLinkConfiguration_v7_6 */
+/* [helpstring][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkConfiguration_v7_6;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("B8EAD569-B764-47F0-A73F-AE40DF6CBF10")
+ IDeckLinkConfiguration_v7_6 : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE GetConfigurationValidator(
+ /* [out] */ IDeckLinkConfiguration_v7_6 **configObject) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE WriteConfigurationToPreferences( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetVideoOutputFormat(
+ /* [in] */ BMDVideoConnection_v7_6 videoOutputConnection) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE IsVideoOutputActive(
+ /* [in] */ BMDVideoConnection_v7_6 videoOutputConnection,
+ /* [out] */ BOOL *active) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetAnalogVideoOutputFlags(
+ /* [in] */ BMDAnalogVideoFlags analogVideoFlags) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetAnalogVideoOutputFlags(
+ /* [out] */ BMDAnalogVideoFlags *analogVideoFlags) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE EnableFieldFlickerRemovalWhenPaused(
+ /* [in] */ BOOL enable) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE IsEnabledFieldFlickerRemovalWhenPaused(
+ /* [out] */ BOOL *enabled) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Set444And3GBpsVideoOutput(
+ /* [in] */ BOOL enable444VideoOutput,
+ /* [in] */ BOOL enable3GbsOutput) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Get444And3GBpsVideoOutput(
+ /* [out] */ BOOL *is444VideoOutputEnabled,
+ /* [out] */ BOOL *threeGbsOutputEnabled) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetVideoOutputConversionMode(
+ /* [in] */ BMDVideoOutputConversionMode conversionMode) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetVideoOutputConversionMode(
+ /* [out] */ BMDVideoOutputConversionMode *conversionMode) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Set_HD1080p24_to_HD1080i5994_Conversion(
+ /* [in] */ BOOL enable) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Get_HD1080p24_to_HD1080i5994_Conversion(
+ /* [out] */ BOOL *enabled) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetVideoInputFormat(
+ /* [in] */ BMDVideoConnection_v7_6 videoInputFormat) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetVideoInputFormat(
+ /* [out] */ BMDVideoConnection_v7_6 *videoInputFormat) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetAnalogVideoInputFlags(
+ /* [in] */ BMDAnalogVideoFlags analogVideoFlags) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetAnalogVideoInputFlags(
+ /* [out] */ BMDAnalogVideoFlags *analogVideoFlags) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetVideoInputConversionMode(
+ /* [in] */ BMDVideoInputConversionMode conversionMode) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetVideoInputConversionMode(
+ /* [out] */ BMDVideoInputConversionMode *conversionMode) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetBlackVideoOutputDuringCapture(
+ /* [in] */ BOOL blackOutInCapture) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetBlackVideoOutputDuringCapture(
+ /* [out] */ BOOL *blackOutInCapture) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Set32PulldownSequenceInitialTimecodeFrame(
+ /* [in] */ unsigned int aFrameTimecode) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE Get32PulldownSequenceInitialTimecodeFrame(
+ /* [out] */ unsigned int *aFrameTimecode) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetVancSourceLineMapping(
+ /* [in] */ unsigned int activeLine1VANCsource,
+ /* [in] */ unsigned int activeLine2VANCsource,
+ /* [in] */ unsigned int activeLine3VANCsource) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetVancSourceLineMapping(
+ /* [out] */ unsigned int *activeLine1VANCsource,
+ /* [out] */ unsigned int *activeLine2VANCsource,
+ /* [out] */ unsigned int *activeLine3VANCsource) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetAudioInputFormat(
+ /* [in] */ BMDAudioConnection_v10_2 audioInputFormat) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetAudioInputFormat(
+ /* [out] */ BMDAudioConnection_v10_2 *audioInputFormat) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkConfiguration_v7_6Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkConfiguration_v7_6 * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkConfiguration_v7_6 * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkConfiguration_v7_6 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetConfigurationValidator )(
+ IDeckLinkConfiguration_v7_6 * This,
+ /* [out] */ IDeckLinkConfiguration_v7_6 **configObject);
+
+ HRESULT ( STDMETHODCALLTYPE *WriteConfigurationToPreferences )(
+ IDeckLinkConfiguration_v7_6 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *SetVideoOutputFormat )(
+ IDeckLinkConfiguration_v7_6 * This,
+ /* [in] */ BMDVideoConnection_v7_6 videoOutputConnection);
+
+ HRESULT ( STDMETHODCALLTYPE *IsVideoOutputActive )(
+ IDeckLinkConfiguration_v7_6 * This,
+ /* [in] */ BMDVideoConnection_v7_6 videoOutputConnection,
+ /* [out] */ BOOL *active);
+
+ HRESULT ( STDMETHODCALLTYPE *SetAnalogVideoOutputFlags )(
+ IDeckLinkConfiguration_v7_6 * This,
+ /* [in] */ BMDAnalogVideoFlags analogVideoFlags);
+
+ HRESULT ( STDMETHODCALLTYPE *GetAnalogVideoOutputFlags )(
+ IDeckLinkConfiguration_v7_6 * This,
+ /* [out] */ BMDAnalogVideoFlags *analogVideoFlags);
+
+ HRESULT ( STDMETHODCALLTYPE *EnableFieldFlickerRemovalWhenPaused )(
+ IDeckLinkConfiguration_v7_6 * This,
+ /* [in] */ BOOL enable);
+
+ HRESULT ( STDMETHODCALLTYPE *IsEnabledFieldFlickerRemovalWhenPaused )(
+ IDeckLinkConfiguration_v7_6 * This,
+ /* [out] */ BOOL *enabled);
+
+ HRESULT ( STDMETHODCALLTYPE *Set444And3GBpsVideoOutput )(
+ IDeckLinkConfiguration_v7_6 * This,
+ /* [in] */ BOOL enable444VideoOutput,
+ /* [in] */ BOOL enable3GbsOutput);
+
+ HRESULT ( STDMETHODCALLTYPE *Get444And3GBpsVideoOutput )(
+ IDeckLinkConfiguration_v7_6 * This,
+ /* [out] */ BOOL *is444VideoOutputEnabled,
+ /* [out] */ BOOL *threeGbsOutputEnabled);
+
+ HRESULT ( STDMETHODCALLTYPE *SetVideoOutputConversionMode )(
+ IDeckLinkConfiguration_v7_6 * This,
+ /* [in] */ BMDVideoOutputConversionMode conversionMode);
+
+ HRESULT ( STDMETHODCALLTYPE *GetVideoOutputConversionMode )(
+ IDeckLinkConfiguration_v7_6 * This,
+ /* [out] */ BMDVideoOutputConversionMode *conversionMode);
+
+ HRESULT ( STDMETHODCALLTYPE *Set_HD1080p24_to_HD1080i5994_Conversion )(
+ IDeckLinkConfiguration_v7_6 * This,
+ /* [in] */ BOOL enable);
+
+ HRESULT ( STDMETHODCALLTYPE *Get_HD1080p24_to_HD1080i5994_Conversion )(
+ IDeckLinkConfiguration_v7_6 * This,
+ /* [out] */ BOOL *enabled);
+
+ HRESULT ( STDMETHODCALLTYPE *SetVideoInputFormat )(
+ IDeckLinkConfiguration_v7_6 * This,
+ /* [in] */ BMDVideoConnection_v7_6 videoInputFormat);
+
+ HRESULT ( STDMETHODCALLTYPE *GetVideoInputFormat )(
+ IDeckLinkConfiguration_v7_6 * This,
+ /* [out] */ BMDVideoConnection_v7_6 *videoInputFormat);
+
+ HRESULT ( STDMETHODCALLTYPE *SetAnalogVideoInputFlags )(
+ IDeckLinkConfiguration_v7_6 * This,
+ /* [in] */ BMDAnalogVideoFlags analogVideoFlags);
+
+ HRESULT ( STDMETHODCALLTYPE *GetAnalogVideoInputFlags )(
+ IDeckLinkConfiguration_v7_6 * This,
+ /* [out] */ BMDAnalogVideoFlags *analogVideoFlags);
+
+ HRESULT ( STDMETHODCALLTYPE *SetVideoInputConversionMode )(
+ IDeckLinkConfiguration_v7_6 * This,
+ /* [in] */ BMDVideoInputConversionMode conversionMode);
+
+ HRESULT ( STDMETHODCALLTYPE *GetVideoInputConversionMode )(
+ IDeckLinkConfiguration_v7_6 * This,
+ /* [out] */ BMDVideoInputConversionMode *conversionMode);
+
+ HRESULT ( STDMETHODCALLTYPE *SetBlackVideoOutputDuringCapture )(
+ IDeckLinkConfiguration_v7_6 * This,
+ /* [in] */ BOOL blackOutInCapture);
+
+ HRESULT ( STDMETHODCALLTYPE *GetBlackVideoOutputDuringCapture )(
+ IDeckLinkConfiguration_v7_6 * This,
+ /* [out] */ BOOL *blackOutInCapture);
+
+ HRESULT ( STDMETHODCALLTYPE *Set32PulldownSequenceInitialTimecodeFrame )(
+ IDeckLinkConfiguration_v7_6 * This,
+ /* [in] */ unsigned int aFrameTimecode);
+
+ HRESULT ( STDMETHODCALLTYPE *Get32PulldownSequenceInitialTimecodeFrame )(
+ IDeckLinkConfiguration_v7_6 * This,
+ /* [out] */ unsigned int *aFrameTimecode);
+
+ HRESULT ( STDMETHODCALLTYPE *SetVancSourceLineMapping )(
+ IDeckLinkConfiguration_v7_6 * This,
+ /* [in] */ unsigned int activeLine1VANCsource,
+ /* [in] */ unsigned int activeLine2VANCsource,
+ /* [in] */ unsigned int activeLine3VANCsource);
+
+ HRESULT ( STDMETHODCALLTYPE *GetVancSourceLineMapping )(
+ IDeckLinkConfiguration_v7_6 * This,
+ /* [out] */ unsigned int *activeLine1VANCsource,
+ /* [out] */ unsigned int *activeLine2VANCsource,
+ /* [out] */ unsigned int *activeLine3VANCsource);
+
+ HRESULT ( STDMETHODCALLTYPE *SetAudioInputFormat )(
+ IDeckLinkConfiguration_v7_6 * This,
+ /* [in] */ BMDAudioConnection_v10_2 audioInputFormat);
+
+ HRESULT ( STDMETHODCALLTYPE *GetAudioInputFormat )(
+ IDeckLinkConfiguration_v7_6 * This,
+ /* [out] */ BMDAudioConnection_v10_2 *audioInputFormat);
+
+ END_INTERFACE
+ } IDeckLinkConfiguration_v7_6Vtbl;
+
+ interface IDeckLinkConfiguration_v7_6
+ {
+ CONST_VTBL struct IDeckLinkConfiguration_v7_6Vtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkConfiguration_v7_6_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkConfiguration_v7_6_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkConfiguration_v7_6_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkConfiguration_v7_6_GetConfigurationValidator(This,configObject) \
+ ( (This)->lpVtbl -> GetConfigurationValidator(This,configObject) )
+
+#define IDeckLinkConfiguration_v7_6_WriteConfigurationToPreferences(This) \
+ ( (This)->lpVtbl -> WriteConfigurationToPreferences(This) )
+
+#define IDeckLinkConfiguration_v7_6_SetVideoOutputFormat(This,videoOutputConnection) \
+ ( (This)->lpVtbl -> SetVideoOutputFormat(This,videoOutputConnection) )
+
+#define IDeckLinkConfiguration_v7_6_IsVideoOutputActive(This,videoOutputConnection,active) \
+ ( (This)->lpVtbl -> IsVideoOutputActive(This,videoOutputConnection,active) )
+
+#define IDeckLinkConfiguration_v7_6_SetAnalogVideoOutputFlags(This,analogVideoFlags) \
+ ( (This)->lpVtbl -> SetAnalogVideoOutputFlags(This,analogVideoFlags) )
+
+#define IDeckLinkConfiguration_v7_6_GetAnalogVideoOutputFlags(This,analogVideoFlags) \
+ ( (This)->lpVtbl -> GetAnalogVideoOutputFlags(This,analogVideoFlags) )
+
+#define IDeckLinkConfiguration_v7_6_EnableFieldFlickerRemovalWhenPaused(This,enable) \
+ ( (This)->lpVtbl -> EnableFieldFlickerRemovalWhenPaused(This,enable) )
+
+#define IDeckLinkConfiguration_v7_6_IsEnabledFieldFlickerRemovalWhenPaused(This,enabled) \
+ ( (This)->lpVtbl -> IsEnabledFieldFlickerRemovalWhenPaused(This,enabled) )
+
+#define IDeckLinkConfiguration_v7_6_Set444And3GBpsVideoOutput(This,enable444VideoOutput,enable3GbsOutput) \
+ ( (This)->lpVtbl -> Set444And3GBpsVideoOutput(This,enable444VideoOutput,enable3GbsOutput) )
+
+#define IDeckLinkConfiguration_v7_6_Get444And3GBpsVideoOutput(This,is444VideoOutputEnabled,threeGbsOutputEnabled) \
+ ( (This)->lpVtbl -> Get444And3GBpsVideoOutput(This,is444VideoOutputEnabled,threeGbsOutputEnabled) )
+
+#define IDeckLinkConfiguration_v7_6_SetVideoOutputConversionMode(This,conversionMode) \
+ ( (This)->lpVtbl -> SetVideoOutputConversionMode(This,conversionMode) )
+
+#define IDeckLinkConfiguration_v7_6_GetVideoOutputConversionMode(This,conversionMode) \
+ ( (This)->lpVtbl -> GetVideoOutputConversionMode(This,conversionMode) )
+
+#define IDeckLinkConfiguration_v7_6_Set_HD1080p24_to_HD1080i5994_Conversion(This,enable) \
+ ( (This)->lpVtbl -> Set_HD1080p24_to_HD1080i5994_Conversion(This,enable) )
+
+#define IDeckLinkConfiguration_v7_6_Get_HD1080p24_to_HD1080i5994_Conversion(This,enabled) \
+ ( (This)->lpVtbl -> Get_HD1080p24_to_HD1080i5994_Conversion(This,enabled) )
+
+#define IDeckLinkConfiguration_v7_6_SetVideoInputFormat(This,videoInputFormat) \
+ ( (This)->lpVtbl -> SetVideoInputFormat(This,videoInputFormat) )
+
+#define IDeckLinkConfiguration_v7_6_GetVideoInputFormat(This,videoInputFormat) \
+ ( (This)->lpVtbl -> GetVideoInputFormat(This,videoInputFormat) )
+
+#define IDeckLinkConfiguration_v7_6_SetAnalogVideoInputFlags(This,analogVideoFlags) \
+ ( (This)->lpVtbl -> SetAnalogVideoInputFlags(This,analogVideoFlags) )
+
+#define IDeckLinkConfiguration_v7_6_GetAnalogVideoInputFlags(This,analogVideoFlags) \
+ ( (This)->lpVtbl -> GetAnalogVideoInputFlags(This,analogVideoFlags) )
+
+#define IDeckLinkConfiguration_v7_6_SetVideoInputConversionMode(This,conversionMode) \
+ ( (This)->lpVtbl -> SetVideoInputConversionMode(This,conversionMode) )
+
+#define IDeckLinkConfiguration_v7_6_GetVideoInputConversionMode(This,conversionMode) \
+ ( (This)->lpVtbl -> GetVideoInputConversionMode(This,conversionMode) )
+
+#define IDeckLinkConfiguration_v7_6_SetBlackVideoOutputDuringCapture(This,blackOutInCapture) \
+ ( (This)->lpVtbl -> SetBlackVideoOutputDuringCapture(This,blackOutInCapture) )
+
+#define IDeckLinkConfiguration_v7_6_GetBlackVideoOutputDuringCapture(This,blackOutInCapture) \
+ ( (This)->lpVtbl -> GetBlackVideoOutputDuringCapture(This,blackOutInCapture) )
+
+#define IDeckLinkConfiguration_v7_6_Set32PulldownSequenceInitialTimecodeFrame(This,aFrameTimecode) \
+ ( (This)->lpVtbl -> Set32PulldownSequenceInitialTimecodeFrame(This,aFrameTimecode) )
+
+#define IDeckLinkConfiguration_v7_6_Get32PulldownSequenceInitialTimecodeFrame(This,aFrameTimecode) \
+ ( (This)->lpVtbl -> Get32PulldownSequenceInitialTimecodeFrame(This,aFrameTimecode) )
+
+#define IDeckLinkConfiguration_v7_6_SetVancSourceLineMapping(This,activeLine1VANCsource,activeLine2VANCsource,activeLine3VANCsource) \
+ ( (This)->lpVtbl -> SetVancSourceLineMapping(This,activeLine1VANCsource,activeLine2VANCsource,activeLine3VANCsource) )
+
+#define IDeckLinkConfiguration_v7_6_GetVancSourceLineMapping(This,activeLine1VANCsource,activeLine2VANCsource,activeLine3VANCsource) \
+ ( (This)->lpVtbl -> GetVancSourceLineMapping(This,activeLine1VANCsource,activeLine2VANCsource,activeLine3VANCsource) )
+
+#define IDeckLinkConfiguration_v7_6_SetAudioInputFormat(This,audioInputFormat) \
+ ( (This)->lpVtbl -> SetAudioInputFormat(This,audioInputFormat) )
+
+#define IDeckLinkConfiguration_v7_6_GetAudioInputFormat(This,audioInputFormat) \
+ ( (This)->lpVtbl -> GetAudioInputFormat(This,audioInputFormat) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkConfiguration_v7_6_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkVideoOutputCallback_v7_6_INTERFACE_DEFINED__
+#define __IDeckLinkVideoOutputCallback_v7_6_INTERFACE_DEFINED__
+
+/* interface IDeckLinkVideoOutputCallback_v7_6 */
+/* [helpstring][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkVideoOutputCallback_v7_6;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("E763A626-4A3C-49D1-BF13-E7AD3692AE52")
+ IDeckLinkVideoOutputCallback_v7_6 : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE ScheduledFrameCompleted(
+ /* [in] */ IDeckLinkVideoFrame_v7_6 *completedFrame,
+ /* [in] */ BMDOutputFrameCompletionResult result) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE ScheduledPlaybackHasStopped( void) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkVideoOutputCallback_v7_6Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkVideoOutputCallback_v7_6 * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkVideoOutputCallback_v7_6 * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkVideoOutputCallback_v7_6 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *ScheduledFrameCompleted )(
+ IDeckLinkVideoOutputCallback_v7_6 * This,
+ /* [in] */ IDeckLinkVideoFrame_v7_6 *completedFrame,
+ /* [in] */ BMDOutputFrameCompletionResult result);
+
+ HRESULT ( STDMETHODCALLTYPE *ScheduledPlaybackHasStopped )(
+ IDeckLinkVideoOutputCallback_v7_6 * This);
+
+ END_INTERFACE
+ } IDeckLinkVideoOutputCallback_v7_6Vtbl;
+
+ interface IDeckLinkVideoOutputCallback_v7_6
+ {
+ CONST_VTBL struct IDeckLinkVideoOutputCallback_v7_6Vtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkVideoOutputCallback_v7_6_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkVideoOutputCallback_v7_6_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkVideoOutputCallback_v7_6_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkVideoOutputCallback_v7_6_ScheduledFrameCompleted(This,completedFrame,result) \
+ ( (This)->lpVtbl -> ScheduledFrameCompleted(This,completedFrame,result) )
+
+#define IDeckLinkVideoOutputCallback_v7_6_ScheduledPlaybackHasStopped(This) \
+ ( (This)->lpVtbl -> ScheduledPlaybackHasStopped(This) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkVideoOutputCallback_v7_6_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkInputCallback_v7_6_INTERFACE_DEFINED__
+#define __IDeckLinkInputCallback_v7_6_INTERFACE_DEFINED__
+
+/* interface IDeckLinkInputCallback_v7_6 */
+/* [helpstring][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkInputCallback_v7_6;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("31D28EE7-88B6-4CB1-897A-CDBF79A26414")
+ IDeckLinkInputCallback_v7_6 : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE VideoInputFormatChanged(
+ /* [in] */ BMDVideoInputFormatChangedEvents notificationEvents,
+ /* [in] */ IDeckLinkDisplayMode_v7_6 *newDisplayMode,
+ /* [in] */ BMDDetectedVideoInputFormatFlags detectedSignalFlags) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE VideoInputFrameArrived(
+ /* [in] */ IDeckLinkVideoInputFrame_v7_6 *videoFrame,
+ /* [in] */ IDeckLinkAudioInputPacket *audioPacket) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkInputCallback_v7_6Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkInputCallback_v7_6 * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkInputCallback_v7_6 * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkInputCallback_v7_6 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *VideoInputFormatChanged )(
+ IDeckLinkInputCallback_v7_6 * This,
+ /* [in] */ BMDVideoInputFormatChangedEvents notificationEvents,
+ /* [in] */ IDeckLinkDisplayMode_v7_6 *newDisplayMode,
+ /* [in] */ BMDDetectedVideoInputFormatFlags detectedSignalFlags);
+
+ HRESULT ( STDMETHODCALLTYPE *VideoInputFrameArrived )(
+ IDeckLinkInputCallback_v7_6 * This,
+ /* [in] */ IDeckLinkVideoInputFrame_v7_6 *videoFrame,
+ /* [in] */ IDeckLinkAudioInputPacket *audioPacket);
+
+ END_INTERFACE
+ } IDeckLinkInputCallback_v7_6Vtbl;
+
+ interface IDeckLinkInputCallback_v7_6
+ {
+ CONST_VTBL struct IDeckLinkInputCallback_v7_6Vtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkInputCallback_v7_6_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkInputCallback_v7_6_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkInputCallback_v7_6_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkInputCallback_v7_6_VideoInputFormatChanged(This,notificationEvents,newDisplayMode,detectedSignalFlags) \
+ ( (This)->lpVtbl -> VideoInputFormatChanged(This,notificationEvents,newDisplayMode,detectedSignalFlags) )
+
+#define IDeckLinkInputCallback_v7_6_VideoInputFrameArrived(This,videoFrame,audioPacket) \
+ ( (This)->lpVtbl -> VideoInputFrameArrived(This,videoFrame,audioPacket) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkInputCallback_v7_6_INTERFACE_DEFINED__ */
+
+
+EXTERN_C const CLSID CLSID_CDeckLinkGLScreenPreviewHelper_v7_6;
+
+#ifdef __cplusplus
+
+class DECLSPEC_UUID("D398CEE7-4434-4CA3-9BA6-5AE34556B905")
+CDeckLinkGLScreenPreviewHelper_v7_6;
+#endif
+
+EXTERN_C const CLSID CLSID_CDeckLinkVideoConversion_v7_6;
+
+#ifdef __cplusplus
+
+class DECLSPEC_UUID("FFA84F77-73BE-4FB7-B03E-B5E44B9F759B")
+CDeckLinkVideoConversion_v7_6;
+#endif
+
+#ifndef __IDeckLinkInputCallback_v7_3_INTERFACE_DEFINED__
+#define __IDeckLinkInputCallback_v7_3_INTERFACE_DEFINED__
+
+/* interface IDeckLinkInputCallback_v7_3 */
+/* [helpstring][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkInputCallback_v7_3;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("FD6F311D-4D00-444B-9ED4-1F25B5730AD0")
+ IDeckLinkInputCallback_v7_3 : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE VideoInputFormatChanged(
+ /* [in] */ BMDVideoInputFormatChangedEvents notificationEvents,
+ /* [in] */ IDeckLinkDisplayMode_v7_6 *newDisplayMode,
+ /* [in] */ BMDDetectedVideoInputFormatFlags detectedSignalFlags) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE VideoInputFrameArrived(
+ /* [in] */ IDeckLinkVideoInputFrame_v7_3 *videoFrame,
+ /* [in] */ IDeckLinkAudioInputPacket *audioPacket) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkInputCallback_v7_3Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkInputCallback_v7_3 * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkInputCallback_v7_3 * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkInputCallback_v7_3 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *VideoInputFormatChanged )(
+ IDeckLinkInputCallback_v7_3 * This,
+ /* [in] */ BMDVideoInputFormatChangedEvents notificationEvents,
+ /* [in] */ IDeckLinkDisplayMode_v7_6 *newDisplayMode,
+ /* [in] */ BMDDetectedVideoInputFormatFlags detectedSignalFlags);
+
+ HRESULT ( STDMETHODCALLTYPE *VideoInputFrameArrived )(
+ IDeckLinkInputCallback_v7_3 * This,
+ /* [in] */ IDeckLinkVideoInputFrame_v7_3 *videoFrame,
+ /* [in] */ IDeckLinkAudioInputPacket *audioPacket);
+
+ END_INTERFACE
+ } IDeckLinkInputCallback_v7_3Vtbl;
+
+ interface IDeckLinkInputCallback_v7_3
+ {
+ CONST_VTBL struct IDeckLinkInputCallback_v7_3Vtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkInputCallback_v7_3_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkInputCallback_v7_3_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkInputCallback_v7_3_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkInputCallback_v7_3_VideoInputFormatChanged(This,notificationEvents,newDisplayMode,detectedSignalFlags) \
+ ( (This)->lpVtbl -> VideoInputFormatChanged(This,notificationEvents,newDisplayMode,detectedSignalFlags) )
+
+#define IDeckLinkInputCallback_v7_3_VideoInputFrameArrived(This,videoFrame,audioPacket) \
+ ( (This)->lpVtbl -> VideoInputFrameArrived(This,videoFrame,audioPacket) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkInputCallback_v7_3_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkOutput_v7_3_INTERFACE_DEFINED__
+#define __IDeckLinkOutput_v7_3_INTERFACE_DEFINED__
+
+/* interface IDeckLinkOutput_v7_3 */
+/* [helpstring][local][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkOutput_v7_3;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("271C65E3-C323-4344-A30F-D908BCB20AA3")
+ IDeckLinkOutput_v7_3 : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE DoesSupportVideoMode(
+ BMDDisplayMode displayMode,
+ BMDPixelFormat pixelFormat,
+ /* [out] */ BMDDisplayModeSupport *result) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetDisplayModeIterator(
+ /* [out] */ IDeckLinkDisplayModeIterator_v7_6 **iterator) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetScreenPreviewCallback(
+ /* [in] */ IDeckLinkScreenPreviewCallback *previewCallback) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE EnableVideoOutput(
+ BMDDisplayMode displayMode,
+ BMDVideoOutputFlags flags) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE DisableVideoOutput( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetVideoOutputFrameMemoryAllocator(
+ /* [in] */ IDeckLinkMemoryAllocator *theAllocator) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE CreateVideoFrame(
+ int width,
+ int height,
+ int rowBytes,
+ BMDPixelFormat pixelFormat,
+ BMDFrameFlags flags,
+ /* [out] */ IDeckLinkMutableVideoFrame_v7_6 **outFrame) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE CreateAncillaryData(
+ BMDPixelFormat pixelFormat,
+ /* [out] */ IDeckLinkVideoFrameAncillary **outBuffer) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE DisplayVideoFrameSync(
+ /* [in] */ IDeckLinkVideoFrame_v7_6 *theFrame) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE ScheduleVideoFrame(
+ /* [in] */ IDeckLinkVideoFrame_v7_6 *theFrame,
+ BMDTimeValue displayTime,
+ BMDTimeValue displayDuration,
+ BMDTimeScale timeScale) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetScheduledFrameCompletionCallback(
+ /* [in] */ IDeckLinkVideoOutputCallback *theCallback) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetBufferedVideoFrameCount(
+ /* [out] */ unsigned int *bufferedFrameCount) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE EnableAudioOutput(
+ BMDAudioSampleRate sampleRate,
+ BMDAudioSampleType sampleType,
+ unsigned int channelCount,
+ BMDAudioOutputStreamType streamType) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE DisableAudioOutput( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE WriteAudioSamplesSync(
+ /* [in] */ void *buffer,
+ unsigned int sampleFrameCount,
+ /* [out] */ unsigned int *sampleFramesWritten) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE BeginAudioPreroll( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE EndAudioPreroll( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE ScheduleAudioSamples(
+ /* [in] */ void *buffer,
+ unsigned int sampleFrameCount,
+ BMDTimeValue streamTime,
+ BMDTimeScale timeScale,
+ /* [out] */ unsigned int *sampleFramesWritten) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetBufferedAudioSampleFrameCount(
+ /* [out] */ unsigned int *bufferedSampleFrameCount) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE FlushBufferedAudioSamples( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetAudioCallback(
+ /* [in] */ IDeckLinkAudioOutputCallback *theCallback) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE StartScheduledPlayback(
+ BMDTimeValue playbackStartTime,
+ BMDTimeScale timeScale,
+ double playbackSpeed) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE StopScheduledPlayback(
+ BMDTimeValue stopPlaybackAtTime,
+ /* [out] */ BMDTimeValue *actualStopTime,
+ BMDTimeScale timeScale) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE IsScheduledPlaybackRunning(
+ /* [out] */ BOOL *active) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetHardwareReferenceClock(
+ BMDTimeScale desiredTimeScale,
+ /* [out] */ BMDTimeValue *elapsedTimeSinceSchedulerBegan) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkOutput_v7_3Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkOutput_v7_3 * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkOutput_v7_3 * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkOutput_v7_3 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *DoesSupportVideoMode )(
+ IDeckLinkOutput_v7_3 * This,
+ BMDDisplayMode displayMode,
+ BMDPixelFormat pixelFormat,
+ /* [out] */ BMDDisplayModeSupport *result);
+
+ HRESULT ( STDMETHODCALLTYPE *GetDisplayModeIterator )(
+ IDeckLinkOutput_v7_3 * This,
+ /* [out] */ IDeckLinkDisplayModeIterator_v7_6 **iterator);
+
+ HRESULT ( STDMETHODCALLTYPE *SetScreenPreviewCallback )(
+ IDeckLinkOutput_v7_3 * This,
+ /* [in] */ IDeckLinkScreenPreviewCallback *previewCallback);
+
+ HRESULT ( STDMETHODCALLTYPE *EnableVideoOutput )(
+ IDeckLinkOutput_v7_3 * This,
+ BMDDisplayMode displayMode,
+ BMDVideoOutputFlags flags);
+
+ HRESULT ( STDMETHODCALLTYPE *DisableVideoOutput )(
+ IDeckLinkOutput_v7_3 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *SetVideoOutputFrameMemoryAllocator )(
+ IDeckLinkOutput_v7_3 * This,
+ /* [in] */ IDeckLinkMemoryAllocator *theAllocator);
+
+ HRESULT ( STDMETHODCALLTYPE *CreateVideoFrame )(
+ IDeckLinkOutput_v7_3 * This,
+ int width,
+ int height,
+ int rowBytes,
+ BMDPixelFormat pixelFormat,
+ BMDFrameFlags flags,
+ /* [out] */ IDeckLinkMutableVideoFrame_v7_6 **outFrame);
+
+ HRESULT ( STDMETHODCALLTYPE *CreateAncillaryData )(
+ IDeckLinkOutput_v7_3 * This,
+ BMDPixelFormat pixelFormat,
+ /* [out] */ IDeckLinkVideoFrameAncillary **outBuffer);
+
+ HRESULT ( STDMETHODCALLTYPE *DisplayVideoFrameSync )(
+ IDeckLinkOutput_v7_3 * This,
+ /* [in] */ IDeckLinkVideoFrame_v7_6 *theFrame);
+
+ HRESULT ( STDMETHODCALLTYPE *ScheduleVideoFrame )(
+ IDeckLinkOutput_v7_3 * This,
+ /* [in] */ IDeckLinkVideoFrame_v7_6 *theFrame,
+ BMDTimeValue displayTime,
+ BMDTimeValue displayDuration,
+ BMDTimeScale timeScale);
+
+ HRESULT ( STDMETHODCALLTYPE *SetScheduledFrameCompletionCallback )(
+ IDeckLinkOutput_v7_3 * This,
+ /* [in] */ IDeckLinkVideoOutputCallback *theCallback);
+
+ HRESULT ( STDMETHODCALLTYPE *GetBufferedVideoFrameCount )(
+ IDeckLinkOutput_v7_3 * This,
+ /* [out] */ unsigned int *bufferedFrameCount);
+
+ HRESULT ( STDMETHODCALLTYPE *EnableAudioOutput )(
+ IDeckLinkOutput_v7_3 * This,
+ BMDAudioSampleRate sampleRate,
+ BMDAudioSampleType sampleType,
+ unsigned int channelCount,
+ BMDAudioOutputStreamType streamType);
+
+ HRESULT ( STDMETHODCALLTYPE *DisableAudioOutput )(
+ IDeckLinkOutput_v7_3 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *WriteAudioSamplesSync )(
+ IDeckLinkOutput_v7_3 * This,
+ /* [in] */ void *buffer,
+ unsigned int sampleFrameCount,
+ /* [out] */ unsigned int *sampleFramesWritten);
+
+ HRESULT ( STDMETHODCALLTYPE *BeginAudioPreroll )(
+ IDeckLinkOutput_v7_3 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *EndAudioPreroll )(
+ IDeckLinkOutput_v7_3 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *ScheduleAudioSamples )(
+ IDeckLinkOutput_v7_3 * This,
+ /* [in] */ void *buffer,
+ unsigned int sampleFrameCount,
+ BMDTimeValue streamTime,
+ BMDTimeScale timeScale,
+ /* [out] */ unsigned int *sampleFramesWritten);
+
+ HRESULT ( STDMETHODCALLTYPE *GetBufferedAudioSampleFrameCount )(
+ IDeckLinkOutput_v7_3 * This,
+ /* [out] */ unsigned int *bufferedSampleFrameCount);
+
+ HRESULT ( STDMETHODCALLTYPE *FlushBufferedAudioSamples )(
+ IDeckLinkOutput_v7_3 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *SetAudioCallback )(
+ IDeckLinkOutput_v7_3 * This,
+ /* [in] */ IDeckLinkAudioOutputCallback *theCallback);
+
+ HRESULT ( STDMETHODCALLTYPE *StartScheduledPlayback )(
+ IDeckLinkOutput_v7_3 * This,
+ BMDTimeValue playbackStartTime,
+ BMDTimeScale timeScale,
+ double playbackSpeed);
+
+ HRESULT ( STDMETHODCALLTYPE *StopScheduledPlayback )(
+ IDeckLinkOutput_v7_3 * This,
+ BMDTimeValue stopPlaybackAtTime,
+ /* [out] */ BMDTimeValue *actualStopTime,
+ BMDTimeScale timeScale);
+
+ HRESULT ( STDMETHODCALLTYPE *IsScheduledPlaybackRunning )(
+ IDeckLinkOutput_v7_3 * This,
+ /* [out] */ BOOL *active);
+
+ HRESULT ( STDMETHODCALLTYPE *GetHardwareReferenceClock )(
+ IDeckLinkOutput_v7_3 * This,
+ BMDTimeScale desiredTimeScale,
+ /* [out] */ BMDTimeValue *elapsedTimeSinceSchedulerBegan);
+
+ END_INTERFACE
+ } IDeckLinkOutput_v7_3Vtbl;
+
+ interface IDeckLinkOutput_v7_3
+ {
+ CONST_VTBL struct IDeckLinkOutput_v7_3Vtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkOutput_v7_3_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkOutput_v7_3_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkOutput_v7_3_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkOutput_v7_3_DoesSupportVideoMode(This,displayMode,pixelFormat,result) \
+ ( (This)->lpVtbl -> DoesSupportVideoMode(This,displayMode,pixelFormat,result) )
+
+#define IDeckLinkOutput_v7_3_GetDisplayModeIterator(This,iterator) \
+ ( (This)->lpVtbl -> GetDisplayModeIterator(This,iterator) )
+
+#define IDeckLinkOutput_v7_3_SetScreenPreviewCallback(This,previewCallback) \
+ ( (This)->lpVtbl -> SetScreenPreviewCallback(This,previewCallback) )
+
+#define IDeckLinkOutput_v7_3_EnableVideoOutput(This,displayMode,flags) \
+ ( (This)->lpVtbl -> EnableVideoOutput(This,displayMode,flags) )
+
+#define IDeckLinkOutput_v7_3_DisableVideoOutput(This) \
+ ( (This)->lpVtbl -> DisableVideoOutput(This) )
+
+#define IDeckLinkOutput_v7_3_SetVideoOutputFrameMemoryAllocator(This,theAllocator) \
+ ( (This)->lpVtbl -> SetVideoOutputFrameMemoryAllocator(This,theAllocator) )
+
+#define IDeckLinkOutput_v7_3_CreateVideoFrame(This,width,height,rowBytes,pixelFormat,flags,outFrame) \
+ ( (This)->lpVtbl -> CreateVideoFrame(This,width,height,rowBytes,pixelFormat,flags,outFrame) )
+
+#define IDeckLinkOutput_v7_3_CreateAncillaryData(This,pixelFormat,outBuffer) \
+ ( (This)->lpVtbl -> CreateAncillaryData(This,pixelFormat,outBuffer) )
+
+#define IDeckLinkOutput_v7_3_DisplayVideoFrameSync(This,theFrame) \
+ ( (This)->lpVtbl -> DisplayVideoFrameSync(This,theFrame) )
+
+#define IDeckLinkOutput_v7_3_ScheduleVideoFrame(This,theFrame,displayTime,displayDuration,timeScale) \
+ ( (This)->lpVtbl -> ScheduleVideoFrame(This,theFrame,displayTime,displayDuration,timeScale) )
+
+#define IDeckLinkOutput_v7_3_SetScheduledFrameCompletionCallback(This,theCallback) \
+ ( (This)->lpVtbl -> SetScheduledFrameCompletionCallback(This,theCallback) )
+
+#define IDeckLinkOutput_v7_3_GetBufferedVideoFrameCount(This,bufferedFrameCount) \
+ ( (This)->lpVtbl -> GetBufferedVideoFrameCount(This,bufferedFrameCount) )
+
+#define IDeckLinkOutput_v7_3_EnableAudioOutput(This,sampleRate,sampleType,channelCount,streamType) \
+ ( (This)->lpVtbl -> EnableAudioOutput(This,sampleRate,sampleType,channelCount,streamType) )
+
+#define IDeckLinkOutput_v7_3_DisableAudioOutput(This) \
+ ( (This)->lpVtbl -> DisableAudioOutput(This) )
+
+#define IDeckLinkOutput_v7_3_WriteAudioSamplesSync(This,buffer,sampleFrameCount,sampleFramesWritten) \
+ ( (This)->lpVtbl -> WriteAudioSamplesSync(This,buffer,sampleFrameCount,sampleFramesWritten) )
+
+#define IDeckLinkOutput_v7_3_BeginAudioPreroll(This) \
+ ( (This)->lpVtbl -> BeginAudioPreroll(This) )
+
+#define IDeckLinkOutput_v7_3_EndAudioPreroll(This) \
+ ( (This)->lpVtbl -> EndAudioPreroll(This) )
+
+#define IDeckLinkOutput_v7_3_ScheduleAudioSamples(This,buffer,sampleFrameCount,streamTime,timeScale,sampleFramesWritten) \
+ ( (This)->lpVtbl -> ScheduleAudioSamples(This,buffer,sampleFrameCount,streamTime,timeScale,sampleFramesWritten) )
+
+#define IDeckLinkOutput_v7_3_GetBufferedAudioSampleFrameCount(This,bufferedSampleFrameCount) \
+ ( (This)->lpVtbl -> GetBufferedAudioSampleFrameCount(This,bufferedSampleFrameCount) )
+
+#define IDeckLinkOutput_v7_3_FlushBufferedAudioSamples(This) \
+ ( (This)->lpVtbl -> FlushBufferedAudioSamples(This) )
+
+#define IDeckLinkOutput_v7_3_SetAudioCallback(This,theCallback) \
+ ( (This)->lpVtbl -> SetAudioCallback(This,theCallback) )
+
+#define IDeckLinkOutput_v7_3_StartScheduledPlayback(This,playbackStartTime,timeScale,playbackSpeed) \
+ ( (This)->lpVtbl -> StartScheduledPlayback(This,playbackStartTime,timeScale,playbackSpeed) )
+
+#define IDeckLinkOutput_v7_3_StopScheduledPlayback(This,stopPlaybackAtTime,actualStopTime,timeScale) \
+ ( (This)->lpVtbl -> StopScheduledPlayback(This,stopPlaybackAtTime,actualStopTime,timeScale) )
+
+#define IDeckLinkOutput_v7_3_IsScheduledPlaybackRunning(This,active) \
+ ( (This)->lpVtbl -> IsScheduledPlaybackRunning(This,active) )
+
+#define IDeckLinkOutput_v7_3_GetHardwareReferenceClock(This,desiredTimeScale,elapsedTimeSinceSchedulerBegan) \
+ ( (This)->lpVtbl -> GetHardwareReferenceClock(This,desiredTimeScale,elapsedTimeSinceSchedulerBegan) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkOutput_v7_3_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkInput_v7_3_INTERFACE_DEFINED__
+#define __IDeckLinkInput_v7_3_INTERFACE_DEFINED__
+
+/* interface IDeckLinkInput_v7_3 */
+/* [helpstring][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkInput_v7_3;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("4973F012-9925-458C-871C-18774CDBBECB")
+ IDeckLinkInput_v7_3 : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE DoesSupportVideoMode(
+ BMDDisplayMode displayMode,
+ BMDPixelFormat pixelFormat,
+ /* [out] */ BMDDisplayModeSupport *result) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetDisplayModeIterator(
+ /* [out] */ IDeckLinkDisplayModeIterator_v7_6 **iterator) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetScreenPreviewCallback(
+ /* [in] */ IDeckLinkScreenPreviewCallback *previewCallback) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE EnableVideoInput(
+ BMDDisplayMode displayMode,
+ BMDPixelFormat pixelFormat,
+ BMDVideoInputFlags flags) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE DisableVideoInput( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetAvailableVideoFrameCount(
+ /* [out] */ unsigned int *availableFrameCount) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE EnableAudioInput(
+ BMDAudioSampleRate sampleRate,
+ BMDAudioSampleType sampleType,
+ unsigned int channelCount) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE DisableAudioInput( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetAvailableAudioSampleFrameCount(
+ /* [out] */ unsigned int *availableSampleFrameCount) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE StartStreams( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE StopStreams( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE PauseStreams( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE FlushStreams( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetCallback(
+ /* [in] */ IDeckLinkInputCallback_v7_3 *theCallback) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkInput_v7_3Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkInput_v7_3 * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkInput_v7_3 * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkInput_v7_3 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *DoesSupportVideoMode )(
+ IDeckLinkInput_v7_3 * This,
+ BMDDisplayMode displayMode,
+ BMDPixelFormat pixelFormat,
+ /* [out] */ BMDDisplayModeSupport *result);
+
+ HRESULT ( STDMETHODCALLTYPE *GetDisplayModeIterator )(
+ IDeckLinkInput_v7_3 * This,
+ /* [out] */ IDeckLinkDisplayModeIterator_v7_6 **iterator);
+
+ HRESULT ( STDMETHODCALLTYPE *SetScreenPreviewCallback )(
+ IDeckLinkInput_v7_3 * This,
+ /* [in] */ IDeckLinkScreenPreviewCallback *previewCallback);
+
+ HRESULT ( STDMETHODCALLTYPE *EnableVideoInput )(
+ IDeckLinkInput_v7_3 * This,
+ BMDDisplayMode displayMode,
+ BMDPixelFormat pixelFormat,
+ BMDVideoInputFlags flags);
+
+ HRESULT ( STDMETHODCALLTYPE *DisableVideoInput )(
+ IDeckLinkInput_v7_3 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetAvailableVideoFrameCount )(
+ IDeckLinkInput_v7_3 * This,
+ /* [out] */ unsigned int *availableFrameCount);
+
+ HRESULT ( STDMETHODCALLTYPE *EnableAudioInput )(
+ IDeckLinkInput_v7_3 * This,
+ BMDAudioSampleRate sampleRate,
+ BMDAudioSampleType sampleType,
+ unsigned int channelCount);
+
+ HRESULT ( STDMETHODCALLTYPE *DisableAudioInput )(
+ IDeckLinkInput_v7_3 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetAvailableAudioSampleFrameCount )(
+ IDeckLinkInput_v7_3 * This,
+ /* [out] */ unsigned int *availableSampleFrameCount);
+
+ HRESULT ( STDMETHODCALLTYPE *StartStreams )(
+ IDeckLinkInput_v7_3 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *StopStreams )(
+ IDeckLinkInput_v7_3 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *PauseStreams )(
+ IDeckLinkInput_v7_3 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *FlushStreams )(
+ IDeckLinkInput_v7_3 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *SetCallback )(
+ IDeckLinkInput_v7_3 * This,
+ /* [in] */ IDeckLinkInputCallback_v7_3 *theCallback);
+
+ END_INTERFACE
+ } IDeckLinkInput_v7_3Vtbl;
+
+ interface IDeckLinkInput_v7_3
+ {
+ CONST_VTBL struct IDeckLinkInput_v7_3Vtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkInput_v7_3_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkInput_v7_3_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkInput_v7_3_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkInput_v7_3_DoesSupportVideoMode(This,displayMode,pixelFormat,result) \
+ ( (This)->lpVtbl -> DoesSupportVideoMode(This,displayMode,pixelFormat,result) )
+
+#define IDeckLinkInput_v7_3_GetDisplayModeIterator(This,iterator) \
+ ( (This)->lpVtbl -> GetDisplayModeIterator(This,iterator) )
+
+#define IDeckLinkInput_v7_3_SetScreenPreviewCallback(This,previewCallback) \
+ ( (This)->lpVtbl -> SetScreenPreviewCallback(This,previewCallback) )
+
+#define IDeckLinkInput_v7_3_EnableVideoInput(This,displayMode,pixelFormat,flags) \
+ ( (This)->lpVtbl -> EnableVideoInput(This,displayMode,pixelFormat,flags) )
+
+#define IDeckLinkInput_v7_3_DisableVideoInput(This) \
+ ( (This)->lpVtbl -> DisableVideoInput(This) )
+
+#define IDeckLinkInput_v7_3_GetAvailableVideoFrameCount(This,availableFrameCount) \
+ ( (This)->lpVtbl -> GetAvailableVideoFrameCount(This,availableFrameCount) )
+
+#define IDeckLinkInput_v7_3_EnableAudioInput(This,sampleRate,sampleType,channelCount) \
+ ( (This)->lpVtbl -> EnableAudioInput(This,sampleRate,sampleType,channelCount) )
+
+#define IDeckLinkInput_v7_3_DisableAudioInput(This) \
+ ( (This)->lpVtbl -> DisableAudioInput(This) )
+
+#define IDeckLinkInput_v7_3_GetAvailableAudioSampleFrameCount(This,availableSampleFrameCount) \
+ ( (This)->lpVtbl -> GetAvailableAudioSampleFrameCount(This,availableSampleFrameCount) )
+
+#define IDeckLinkInput_v7_3_StartStreams(This) \
+ ( (This)->lpVtbl -> StartStreams(This) )
+
+#define IDeckLinkInput_v7_3_StopStreams(This) \
+ ( (This)->lpVtbl -> StopStreams(This) )
+
+#define IDeckLinkInput_v7_3_PauseStreams(This) \
+ ( (This)->lpVtbl -> PauseStreams(This) )
+
+#define IDeckLinkInput_v7_3_FlushStreams(This) \
+ ( (This)->lpVtbl -> FlushStreams(This) )
+
+#define IDeckLinkInput_v7_3_SetCallback(This,theCallback) \
+ ( (This)->lpVtbl -> SetCallback(This,theCallback) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkInput_v7_3_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkVideoInputFrame_v7_3_INTERFACE_DEFINED__
+#define __IDeckLinkVideoInputFrame_v7_3_INTERFACE_DEFINED__
+
+/* interface IDeckLinkVideoInputFrame_v7_3 */
+/* [helpstring][local][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkVideoInputFrame_v7_3;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("CF317790-2894-11DE-8C30-0800200C9A66")
+ IDeckLinkVideoInputFrame_v7_3 : public IDeckLinkVideoFrame_v7_6
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE GetStreamTime(
+ /* [out] */ BMDTimeValue *frameTime,
+ /* [out] */ BMDTimeValue *frameDuration,
+ BMDTimeScale timeScale) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkVideoInputFrame_v7_3Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkVideoInputFrame_v7_3 * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkVideoInputFrame_v7_3 * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkVideoInputFrame_v7_3 * This);
+
+ long ( STDMETHODCALLTYPE *GetWidth )(
+ IDeckLinkVideoInputFrame_v7_3 * This);
+
+ long ( STDMETHODCALLTYPE *GetHeight )(
+ IDeckLinkVideoInputFrame_v7_3 * This);
+
+ long ( STDMETHODCALLTYPE *GetRowBytes )(
+ IDeckLinkVideoInputFrame_v7_3 * This);
+
+ BMDPixelFormat ( STDMETHODCALLTYPE *GetPixelFormat )(
+ IDeckLinkVideoInputFrame_v7_3 * This);
+
+ BMDFrameFlags ( STDMETHODCALLTYPE *GetFlags )(
+ IDeckLinkVideoInputFrame_v7_3 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetBytes )(
+ IDeckLinkVideoInputFrame_v7_3 * This,
+ /* [out] */ void **buffer);
+
+ HRESULT ( STDMETHODCALLTYPE *GetTimecode )(
+ IDeckLinkVideoInputFrame_v7_3 * This,
+ BMDTimecodeFormat format,
+ /* [out] */ IDeckLinkTimecode_v7_6 **timecode);
+
+ HRESULT ( STDMETHODCALLTYPE *GetAncillaryData )(
+ IDeckLinkVideoInputFrame_v7_3 * This,
+ /* [out] */ IDeckLinkVideoFrameAncillary **ancillary);
+
+ HRESULT ( STDMETHODCALLTYPE *GetStreamTime )(
+ IDeckLinkVideoInputFrame_v7_3 * This,
+ /* [out] */ BMDTimeValue *frameTime,
+ /* [out] */ BMDTimeValue *frameDuration,
+ BMDTimeScale timeScale);
+
+ END_INTERFACE
+ } IDeckLinkVideoInputFrame_v7_3Vtbl;
+
+ interface IDeckLinkVideoInputFrame_v7_3
+ {
+ CONST_VTBL struct IDeckLinkVideoInputFrame_v7_3Vtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkVideoInputFrame_v7_3_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkVideoInputFrame_v7_3_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkVideoInputFrame_v7_3_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkVideoInputFrame_v7_3_GetWidth(This) \
+ ( (This)->lpVtbl -> GetWidth(This) )
+
+#define IDeckLinkVideoInputFrame_v7_3_GetHeight(This) \
+ ( (This)->lpVtbl -> GetHeight(This) )
+
+#define IDeckLinkVideoInputFrame_v7_3_GetRowBytes(This) \
+ ( (This)->lpVtbl -> GetRowBytes(This) )
+
+#define IDeckLinkVideoInputFrame_v7_3_GetPixelFormat(This) \
+ ( (This)->lpVtbl -> GetPixelFormat(This) )
+
+#define IDeckLinkVideoInputFrame_v7_3_GetFlags(This) \
+ ( (This)->lpVtbl -> GetFlags(This) )
+
+#define IDeckLinkVideoInputFrame_v7_3_GetBytes(This,buffer) \
+ ( (This)->lpVtbl -> GetBytes(This,buffer) )
+
+#define IDeckLinkVideoInputFrame_v7_3_GetTimecode(This,format,timecode) \
+ ( (This)->lpVtbl -> GetTimecode(This,format,timecode) )
+
+#define IDeckLinkVideoInputFrame_v7_3_GetAncillaryData(This,ancillary) \
+ ( (This)->lpVtbl -> GetAncillaryData(This,ancillary) )
+
+
+#define IDeckLinkVideoInputFrame_v7_3_GetStreamTime(This,frameTime,frameDuration,timeScale) \
+ ( (This)->lpVtbl -> GetStreamTime(This,frameTime,frameDuration,timeScale) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkVideoInputFrame_v7_3_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkDisplayModeIterator_v7_1_INTERFACE_DEFINED__
+#define __IDeckLinkDisplayModeIterator_v7_1_INTERFACE_DEFINED__
+
+/* interface IDeckLinkDisplayModeIterator_v7_1 */
+/* [helpstring][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkDisplayModeIterator_v7_1;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("B28131B6-59AC-4857-B5AC-CD75D5883E2F")
+ IDeckLinkDisplayModeIterator_v7_1 : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Next(
+ /* [out] */ IDeckLinkDisplayMode_v7_1 **deckLinkDisplayMode) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkDisplayModeIterator_v7_1Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkDisplayModeIterator_v7_1 * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkDisplayModeIterator_v7_1 * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkDisplayModeIterator_v7_1 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Next )(
+ IDeckLinkDisplayModeIterator_v7_1 * This,
+ /* [out] */ IDeckLinkDisplayMode_v7_1 **deckLinkDisplayMode);
+
+ END_INTERFACE
+ } IDeckLinkDisplayModeIterator_v7_1Vtbl;
+
+ interface IDeckLinkDisplayModeIterator_v7_1
+ {
+ CONST_VTBL struct IDeckLinkDisplayModeIterator_v7_1Vtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkDisplayModeIterator_v7_1_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkDisplayModeIterator_v7_1_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkDisplayModeIterator_v7_1_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkDisplayModeIterator_v7_1_Next(This,deckLinkDisplayMode) \
+ ( (This)->lpVtbl -> Next(This,deckLinkDisplayMode) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkDisplayModeIterator_v7_1_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkDisplayMode_v7_1_INTERFACE_DEFINED__
+#define __IDeckLinkDisplayMode_v7_1_INTERFACE_DEFINED__
+
+/* interface IDeckLinkDisplayMode_v7_1 */
+/* [helpstring][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkDisplayMode_v7_1;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("AF0CD6D5-8376-435E-8433-54F9DD530AC3")
+ IDeckLinkDisplayMode_v7_1 : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE GetName(
+ /* [out] */ BSTR *name) = 0;
+
+ virtual BMDDisplayMode STDMETHODCALLTYPE GetDisplayMode( void) = 0;
+
+ virtual long STDMETHODCALLTYPE GetWidth( void) = 0;
+
+ virtual long STDMETHODCALLTYPE GetHeight( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetFrameRate(
+ /* [out] */ BMDTimeValue *frameDuration,
+ /* [out] */ BMDTimeScale *timeScale) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkDisplayMode_v7_1Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkDisplayMode_v7_1 * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkDisplayMode_v7_1 * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkDisplayMode_v7_1 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetName )(
+ IDeckLinkDisplayMode_v7_1 * This,
+ /* [out] */ BSTR *name);
+
+ BMDDisplayMode ( STDMETHODCALLTYPE *GetDisplayMode )(
+ IDeckLinkDisplayMode_v7_1 * This);
+
+ long ( STDMETHODCALLTYPE *GetWidth )(
+ IDeckLinkDisplayMode_v7_1 * This);
+
+ long ( STDMETHODCALLTYPE *GetHeight )(
+ IDeckLinkDisplayMode_v7_1 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetFrameRate )(
+ IDeckLinkDisplayMode_v7_1 * This,
+ /* [out] */ BMDTimeValue *frameDuration,
+ /* [out] */ BMDTimeScale *timeScale);
+
+ END_INTERFACE
+ } IDeckLinkDisplayMode_v7_1Vtbl;
+
+ interface IDeckLinkDisplayMode_v7_1
+ {
+ CONST_VTBL struct IDeckLinkDisplayMode_v7_1Vtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkDisplayMode_v7_1_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkDisplayMode_v7_1_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkDisplayMode_v7_1_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkDisplayMode_v7_1_GetName(This,name) \
+ ( (This)->lpVtbl -> GetName(This,name) )
+
+#define IDeckLinkDisplayMode_v7_1_GetDisplayMode(This) \
+ ( (This)->lpVtbl -> GetDisplayMode(This) )
+
+#define IDeckLinkDisplayMode_v7_1_GetWidth(This) \
+ ( (This)->lpVtbl -> GetWidth(This) )
+
+#define IDeckLinkDisplayMode_v7_1_GetHeight(This) \
+ ( (This)->lpVtbl -> GetHeight(This) )
+
+#define IDeckLinkDisplayMode_v7_1_GetFrameRate(This,frameDuration,timeScale) \
+ ( (This)->lpVtbl -> GetFrameRate(This,frameDuration,timeScale) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkDisplayMode_v7_1_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkVideoFrame_v7_1_INTERFACE_DEFINED__
+#define __IDeckLinkVideoFrame_v7_1_INTERFACE_DEFINED__
+
+/* interface IDeckLinkVideoFrame_v7_1 */
+/* [helpstring][local][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkVideoFrame_v7_1;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("333F3A10-8C2D-43CF-B79D-46560FEEA1CE")
+ IDeckLinkVideoFrame_v7_1 : public IUnknown
+ {
+ public:
+ virtual long STDMETHODCALLTYPE GetWidth( void) = 0;
+
+ virtual long STDMETHODCALLTYPE GetHeight( void) = 0;
+
+ virtual long STDMETHODCALLTYPE GetRowBytes( void) = 0;
+
+ virtual BMDPixelFormat STDMETHODCALLTYPE GetPixelFormat( void) = 0;
+
+ virtual BMDFrameFlags STDMETHODCALLTYPE GetFlags( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetBytes(
+ void **buffer) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkVideoFrame_v7_1Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkVideoFrame_v7_1 * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkVideoFrame_v7_1 * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkVideoFrame_v7_1 * This);
+
+ long ( STDMETHODCALLTYPE *GetWidth )(
+ IDeckLinkVideoFrame_v7_1 * This);
+
+ long ( STDMETHODCALLTYPE *GetHeight )(
+ IDeckLinkVideoFrame_v7_1 * This);
+
+ long ( STDMETHODCALLTYPE *GetRowBytes )(
+ IDeckLinkVideoFrame_v7_1 * This);
+
+ BMDPixelFormat ( STDMETHODCALLTYPE *GetPixelFormat )(
+ IDeckLinkVideoFrame_v7_1 * This);
+
+ BMDFrameFlags ( STDMETHODCALLTYPE *GetFlags )(
+ IDeckLinkVideoFrame_v7_1 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetBytes )(
+ IDeckLinkVideoFrame_v7_1 * This,
+ void **buffer);
+
+ END_INTERFACE
+ } IDeckLinkVideoFrame_v7_1Vtbl;
+
+ interface IDeckLinkVideoFrame_v7_1
+ {
+ CONST_VTBL struct IDeckLinkVideoFrame_v7_1Vtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkVideoFrame_v7_1_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkVideoFrame_v7_1_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkVideoFrame_v7_1_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkVideoFrame_v7_1_GetWidth(This) \
+ ( (This)->lpVtbl -> GetWidth(This) )
+
+#define IDeckLinkVideoFrame_v7_1_GetHeight(This) \
+ ( (This)->lpVtbl -> GetHeight(This) )
+
+#define IDeckLinkVideoFrame_v7_1_GetRowBytes(This) \
+ ( (This)->lpVtbl -> GetRowBytes(This) )
+
+#define IDeckLinkVideoFrame_v7_1_GetPixelFormat(This) \
+ ( (This)->lpVtbl -> GetPixelFormat(This) )
+
+#define IDeckLinkVideoFrame_v7_1_GetFlags(This) \
+ ( (This)->lpVtbl -> GetFlags(This) )
+
+#define IDeckLinkVideoFrame_v7_1_GetBytes(This,buffer) \
+ ( (This)->lpVtbl -> GetBytes(This,buffer) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkVideoFrame_v7_1_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkVideoInputFrame_v7_1_INTERFACE_DEFINED__
+#define __IDeckLinkVideoInputFrame_v7_1_INTERFACE_DEFINED__
+
+/* interface IDeckLinkVideoInputFrame_v7_1 */
+/* [helpstring][local][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkVideoInputFrame_v7_1;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("C8B41D95-8848-40EE-9B37-6E3417FB114B")
+ IDeckLinkVideoInputFrame_v7_1 : public IDeckLinkVideoFrame_v7_1
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE GetFrameTime(
+ BMDTimeValue *frameTime,
+ BMDTimeValue *frameDuration,
+ BMDTimeScale timeScale) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkVideoInputFrame_v7_1Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkVideoInputFrame_v7_1 * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkVideoInputFrame_v7_1 * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkVideoInputFrame_v7_1 * This);
+
+ long ( STDMETHODCALLTYPE *GetWidth )(
+ IDeckLinkVideoInputFrame_v7_1 * This);
+
+ long ( STDMETHODCALLTYPE *GetHeight )(
+ IDeckLinkVideoInputFrame_v7_1 * This);
+
+ long ( STDMETHODCALLTYPE *GetRowBytes )(
+ IDeckLinkVideoInputFrame_v7_1 * This);
+
+ BMDPixelFormat ( STDMETHODCALLTYPE *GetPixelFormat )(
+ IDeckLinkVideoInputFrame_v7_1 * This);
+
+ BMDFrameFlags ( STDMETHODCALLTYPE *GetFlags )(
+ IDeckLinkVideoInputFrame_v7_1 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetBytes )(
+ IDeckLinkVideoInputFrame_v7_1 * This,
+ void **buffer);
+
+ HRESULT ( STDMETHODCALLTYPE *GetFrameTime )(
+ IDeckLinkVideoInputFrame_v7_1 * This,
+ BMDTimeValue *frameTime,
+ BMDTimeValue *frameDuration,
+ BMDTimeScale timeScale);
+
+ END_INTERFACE
+ } IDeckLinkVideoInputFrame_v7_1Vtbl;
+
+ interface IDeckLinkVideoInputFrame_v7_1
+ {
+ CONST_VTBL struct IDeckLinkVideoInputFrame_v7_1Vtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkVideoInputFrame_v7_1_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkVideoInputFrame_v7_1_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkVideoInputFrame_v7_1_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkVideoInputFrame_v7_1_GetWidth(This) \
+ ( (This)->lpVtbl -> GetWidth(This) )
+
+#define IDeckLinkVideoInputFrame_v7_1_GetHeight(This) \
+ ( (This)->lpVtbl -> GetHeight(This) )
+
+#define IDeckLinkVideoInputFrame_v7_1_GetRowBytes(This) \
+ ( (This)->lpVtbl -> GetRowBytes(This) )
+
+#define IDeckLinkVideoInputFrame_v7_1_GetPixelFormat(This) \
+ ( (This)->lpVtbl -> GetPixelFormat(This) )
+
+#define IDeckLinkVideoInputFrame_v7_1_GetFlags(This) \
+ ( (This)->lpVtbl -> GetFlags(This) )
+
+#define IDeckLinkVideoInputFrame_v7_1_GetBytes(This,buffer) \
+ ( (This)->lpVtbl -> GetBytes(This,buffer) )
+
+
+#define IDeckLinkVideoInputFrame_v7_1_GetFrameTime(This,frameTime,frameDuration,timeScale) \
+ ( (This)->lpVtbl -> GetFrameTime(This,frameTime,frameDuration,timeScale) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkVideoInputFrame_v7_1_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkAudioInputPacket_v7_1_INTERFACE_DEFINED__
+#define __IDeckLinkAudioInputPacket_v7_1_INTERFACE_DEFINED__
+
+/* interface IDeckLinkAudioInputPacket_v7_1 */
+/* [helpstring][local][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkAudioInputPacket_v7_1;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("C86DE4F6-A29F-42E3-AB3A-1363E29F0788")
+ IDeckLinkAudioInputPacket_v7_1 : public IUnknown
+ {
+ public:
+ virtual long STDMETHODCALLTYPE GetSampleCount( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetBytes(
+ void **buffer) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetAudioPacketTime(
+ BMDTimeValue *packetTime,
+ BMDTimeScale timeScale) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkAudioInputPacket_v7_1Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkAudioInputPacket_v7_1 * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkAudioInputPacket_v7_1 * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkAudioInputPacket_v7_1 * This);
+
+ long ( STDMETHODCALLTYPE *GetSampleCount )(
+ IDeckLinkAudioInputPacket_v7_1 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetBytes )(
+ IDeckLinkAudioInputPacket_v7_1 * This,
+ void **buffer);
+
+ HRESULT ( STDMETHODCALLTYPE *GetAudioPacketTime )(
+ IDeckLinkAudioInputPacket_v7_1 * This,
+ BMDTimeValue *packetTime,
+ BMDTimeScale timeScale);
+
+ END_INTERFACE
+ } IDeckLinkAudioInputPacket_v7_1Vtbl;
+
+ interface IDeckLinkAudioInputPacket_v7_1
+ {
+ CONST_VTBL struct IDeckLinkAudioInputPacket_v7_1Vtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkAudioInputPacket_v7_1_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkAudioInputPacket_v7_1_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkAudioInputPacket_v7_1_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkAudioInputPacket_v7_1_GetSampleCount(This) \
+ ( (This)->lpVtbl -> GetSampleCount(This) )
+
+#define IDeckLinkAudioInputPacket_v7_1_GetBytes(This,buffer) \
+ ( (This)->lpVtbl -> GetBytes(This,buffer) )
+
+#define IDeckLinkAudioInputPacket_v7_1_GetAudioPacketTime(This,packetTime,timeScale) \
+ ( (This)->lpVtbl -> GetAudioPacketTime(This,packetTime,timeScale) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkAudioInputPacket_v7_1_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkVideoOutputCallback_v7_1_INTERFACE_DEFINED__
+#define __IDeckLinkVideoOutputCallback_v7_1_INTERFACE_DEFINED__
+
+/* interface IDeckLinkVideoOutputCallback_v7_1 */
+/* [helpstring][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkVideoOutputCallback_v7_1;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("EBD01AFA-E4B0-49C6-A01D-EDB9D1B55FD9")
+ IDeckLinkVideoOutputCallback_v7_1 : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE ScheduledFrameCompleted(
+ /* [in] */ IDeckLinkVideoFrame_v7_1 *completedFrame,
+ /* [in] */ BMDOutputFrameCompletionResult result) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkVideoOutputCallback_v7_1Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkVideoOutputCallback_v7_1 * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkVideoOutputCallback_v7_1 * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkVideoOutputCallback_v7_1 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *ScheduledFrameCompleted )(
+ IDeckLinkVideoOutputCallback_v7_1 * This,
+ /* [in] */ IDeckLinkVideoFrame_v7_1 *completedFrame,
+ /* [in] */ BMDOutputFrameCompletionResult result);
+
+ END_INTERFACE
+ } IDeckLinkVideoOutputCallback_v7_1Vtbl;
+
+ interface IDeckLinkVideoOutputCallback_v7_1
+ {
+ CONST_VTBL struct IDeckLinkVideoOutputCallback_v7_1Vtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkVideoOutputCallback_v7_1_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkVideoOutputCallback_v7_1_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkVideoOutputCallback_v7_1_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkVideoOutputCallback_v7_1_ScheduledFrameCompleted(This,completedFrame,result) \
+ ( (This)->lpVtbl -> ScheduledFrameCompleted(This,completedFrame,result) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkVideoOutputCallback_v7_1_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkInputCallback_v7_1_INTERFACE_DEFINED__
+#define __IDeckLinkInputCallback_v7_1_INTERFACE_DEFINED__
+
+/* interface IDeckLinkInputCallback_v7_1 */
+/* [helpstring][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkInputCallback_v7_1;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("7F94F328-5ED4-4E9F-9729-76A86BDC99CC")
+ IDeckLinkInputCallback_v7_1 : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE VideoInputFrameArrived(
+ /* [in] */ IDeckLinkVideoInputFrame_v7_1 *videoFrame,
+ /* [in] */ IDeckLinkAudioInputPacket_v7_1 *audioPacket) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkInputCallback_v7_1Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkInputCallback_v7_1 * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkInputCallback_v7_1 * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkInputCallback_v7_1 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *VideoInputFrameArrived )(
+ IDeckLinkInputCallback_v7_1 * This,
+ /* [in] */ IDeckLinkVideoInputFrame_v7_1 *videoFrame,
+ /* [in] */ IDeckLinkAudioInputPacket_v7_1 *audioPacket);
+
+ END_INTERFACE
+ } IDeckLinkInputCallback_v7_1Vtbl;
+
+ interface IDeckLinkInputCallback_v7_1
+ {
+ CONST_VTBL struct IDeckLinkInputCallback_v7_1Vtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkInputCallback_v7_1_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkInputCallback_v7_1_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkInputCallback_v7_1_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkInputCallback_v7_1_VideoInputFrameArrived(This,videoFrame,audioPacket) \
+ ( (This)->lpVtbl -> VideoInputFrameArrived(This,videoFrame,audioPacket) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkInputCallback_v7_1_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkOutput_v7_1_INTERFACE_DEFINED__
+#define __IDeckLinkOutput_v7_1_INTERFACE_DEFINED__
+
+/* interface IDeckLinkOutput_v7_1 */
+/* [helpstring][local][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkOutput_v7_1;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("AE5B3E9B-4E1E-4535-B6E8-480FF52F6CE5")
+ IDeckLinkOutput_v7_1 : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE DoesSupportVideoMode(
+ BMDDisplayMode displayMode,
+ BMDPixelFormat pixelFormat,
+ /* [out] */ BMDDisplayModeSupport *result) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetDisplayModeIterator(
+ /* [out] */ IDeckLinkDisplayModeIterator_v7_1 **iterator) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE EnableVideoOutput(
+ BMDDisplayMode displayMode) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE DisableVideoOutput( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetVideoOutputFrameMemoryAllocator(
+ /* [in] */ IDeckLinkMemoryAllocator *theAllocator) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE CreateVideoFrame(
+ int width,
+ int height,
+ int rowBytes,
+ BMDPixelFormat pixelFormat,
+ BMDFrameFlags flags,
+ IDeckLinkVideoFrame_v7_1 **outFrame) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE CreateVideoFrameFromBuffer(
+ void *buffer,
+ int width,
+ int height,
+ int rowBytes,
+ BMDPixelFormat pixelFormat,
+ BMDFrameFlags flags,
+ IDeckLinkVideoFrame_v7_1 **outFrame) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE DisplayVideoFrameSync(
+ IDeckLinkVideoFrame_v7_1 *theFrame) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE ScheduleVideoFrame(
+ IDeckLinkVideoFrame_v7_1 *theFrame,
+ BMDTimeValue displayTime,
+ BMDTimeValue displayDuration,
+ BMDTimeScale timeScale) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetScheduledFrameCompletionCallback(
+ /* [in] */ IDeckLinkVideoOutputCallback_v7_1 *theCallback) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE EnableAudioOutput(
+ BMDAudioSampleRate sampleRate,
+ BMDAudioSampleType sampleType,
+ unsigned int channelCount) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE DisableAudioOutput( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE WriteAudioSamplesSync(
+ void *buffer,
+ unsigned int sampleFrameCount,
+ /* [out] */ unsigned int *sampleFramesWritten) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE BeginAudioPreroll( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE EndAudioPreroll( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE ScheduleAudioSamples(
+ void *buffer,
+ unsigned int sampleFrameCount,
+ BMDTimeValue streamTime,
+ BMDTimeScale timeScale,
+ /* [out] */ unsigned int *sampleFramesWritten) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetBufferedAudioSampleFrameCount(
+ /* [out] */ unsigned int *bufferedSampleCount) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE FlushBufferedAudioSamples( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetAudioCallback(
+ /* [in] */ IDeckLinkAudioOutputCallback *theCallback) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE StartScheduledPlayback(
+ BMDTimeValue playbackStartTime,
+ BMDTimeScale timeScale,
+ double playbackSpeed) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE StopScheduledPlayback(
+ BMDTimeValue stopPlaybackAtTime,
+ BMDTimeValue *actualStopTime,
+ BMDTimeScale timeScale) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetHardwareReferenceClock(
+ BMDTimeScale desiredTimeScale,
+ BMDTimeValue *elapsedTimeSinceSchedulerBegan) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkOutput_v7_1Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkOutput_v7_1 * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkOutput_v7_1 * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkOutput_v7_1 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *DoesSupportVideoMode )(
+ IDeckLinkOutput_v7_1 * This,
+ BMDDisplayMode displayMode,
+ BMDPixelFormat pixelFormat,
+ /* [out] */ BMDDisplayModeSupport *result);
+
+ HRESULT ( STDMETHODCALLTYPE *GetDisplayModeIterator )(
+ IDeckLinkOutput_v7_1 * This,
+ /* [out] */ IDeckLinkDisplayModeIterator_v7_1 **iterator);
+
+ HRESULT ( STDMETHODCALLTYPE *EnableVideoOutput )(
+ IDeckLinkOutput_v7_1 * This,
+ BMDDisplayMode displayMode);
+
+ HRESULT ( STDMETHODCALLTYPE *DisableVideoOutput )(
+ IDeckLinkOutput_v7_1 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *SetVideoOutputFrameMemoryAllocator )(
+ IDeckLinkOutput_v7_1 * This,
+ /* [in] */ IDeckLinkMemoryAllocator *theAllocator);
+
+ HRESULT ( STDMETHODCALLTYPE *CreateVideoFrame )(
+ IDeckLinkOutput_v7_1 * This,
+ int width,
+ int height,
+ int rowBytes,
+ BMDPixelFormat pixelFormat,
+ BMDFrameFlags flags,
+ IDeckLinkVideoFrame_v7_1 **outFrame);
+
+ HRESULT ( STDMETHODCALLTYPE *CreateVideoFrameFromBuffer )(
+ IDeckLinkOutput_v7_1 * This,
+ void *buffer,
+ int width,
+ int height,
+ int rowBytes,
+ BMDPixelFormat pixelFormat,
+ BMDFrameFlags flags,
+ IDeckLinkVideoFrame_v7_1 **outFrame);
+
+ HRESULT ( STDMETHODCALLTYPE *DisplayVideoFrameSync )(
+ IDeckLinkOutput_v7_1 * This,
+ IDeckLinkVideoFrame_v7_1 *theFrame);
+
+ HRESULT ( STDMETHODCALLTYPE *ScheduleVideoFrame )(
+ IDeckLinkOutput_v7_1 * This,
+ IDeckLinkVideoFrame_v7_1 *theFrame,
+ BMDTimeValue displayTime,
+ BMDTimeValue displayDuration,
+ BMDTimeScale timeScale);
+
+ HRESULT ( STDMETHODCALLTYPE *SetScheduledFrameCompletionCallback )(
+ IDeckLinkOutput_v7_1 * This,
+ /* [in] */ IDeckLinkVideoOutputCallback_v7_1 *theCallback);
+
+ HRESULT ( STDMETHODCALLTYPE *EnableAudioOutput )(
+ IDeckLinkOutput_v7_1 * This,
+ BMDAudioSampleRate sampleRate,
+ BMDAudioSampleType sampleType,
+ unsigned int channelCount);
+
+ HRESULT ( STDMETHODCALLTYPE *DisableAudioOutput )(
+ IDeckLinkOutput_v7_1 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *WriteAudioSamplesSync )(
+ IDeckLinkOutput_v7_1 * This,
+ void *buffer,
+ unsigned int sampleFrameCount,
+ /* [out] */ unsigned int *sampleFramesWritten);
+
+ HRESULT ( STDMETHODCALLTYPE *BeginAudioPreroll )(
+ IDeckLinkOutput_v7_1 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *EndAudioPreroll )(
+ IDeckLinkOutput_v7_1 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *ScheduleAudioSamples )(
+ IDeckLinkOutput_v7_1 * This,
+ void *buffer,
+ unsigned int sampleFrameCount,
+ BMDTimeValue streamTime,
+ BMDTimeScale timeScale,
+ /* [out] */ unsigned int *sampleFramesWritten);
+
+ HRESULT ( STDMETHODCALLTYPE *GetBufferedAudioSampleFrameCount )(
+ IDeckLinkOutput_v7_1 * This,
+ /* [out] */ unsigned int *bufferedSampleCount);
+
+ HRESULT ( STDMETHODCALLTYPE *FlushBufferedAudioSamples )(
+ IDeckLinkOutput_v7_1 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *SetAudioCallback )(
+ IDeckLinkOutput_v7_1 * This,
+ /* [in] */ IDeckLinkAudioOutputCallback *theCallback);
+
+ HRESULT ( STDMETHODCALLTYPE *StartScheduledPlayback )(
+ IDeckLinkOutput_v7_1 * This,
+ BMDTimeValue playbackStartTime,
+ BMDTimeScale timeScale,
+ double playbackSpeed);
+
+ HRESULT ( STDMETHODCALLTYPE *StopScheduledPlayback )(
+ IDeckLinkOutput_v7_1 * This,
+ BMDTimeValue stopPlaybackAtTime,
+ BMDTimeValue *actualStopTime,
+ BMDTimeScale timeScale);
+
+ HRESULT ( STDMETHODCALLTYPE *GetHardwareReferenceClock )(
+ IDeckLinkOutput_v7_1 * This,
+ BMDTimeScale desiredTimeScale,
+ BMDTimeValue *elapsedTimeSinceSchedulerBegan);
+
+ END_INTERFACE
+ } IDeckLinkOutput_v7_1Vtbl;
+
+ interface IDeckLinkOutput_v7_1
+ {
+ CONST_VTBL struct IDeckLinkOutput_v7_1Vtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkOutput_v7_1_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkOutput_v7_1_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkOutput_v7_1_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkOutput_v7_1_DoesSupportVideoMode(This,displayMode,pixelFormat,result) \
+ ( (This)->lpVtbl -> DoesSupportVideoMode(This,displayMode,pixelFormat,result) )
+
+#define IDeckLinkOutput_v7_1_GetDisplayModeIterator(This,iterator) \
+ ( (This)->lpVtbl -> GetDisplayModeIterator(This,iterator) )
+
+#define IDeckLinkOutput_v7_1_EnableVideoOutput(This,displayMode) \
+ ( (This)->lpVtbl -> EnableVideoOutput(This,displayMode) )
+
+#define IDeckLinkOutput_v7_1_DisableVideoOutput(This) \
+ ( (This)->lpVtbl -> DisableVideoOutput(This) )
+
+#define IDeckLinkOutput_v7_1_SetVideoOutputFrameMemoryAllocator(This,theAllocator) \
+ ( (This)->lpVtbl -> SetVideoOutputFrameMemoryAllocator(This,theAllocator) )
+
+#define IDeckLinkOutput_v7_1_CreateVideoFrame(This,width,height,rowBytes,pixelFormat,flags,outFrame) \
+ ( (This)->lpVtbl -> CreateVideoFrame(This,width,height,rowBytes,pixelFormat,flags,outFrame) )
+
+#define IDeckLinkOutput_v7_1_CreateVideoFrameFromBuffer(This,buffer,width,height,rowBytes,pixelFormat,flags,outFrame) \
+ ( (This)->lpVtbl -> CreateVideoFrameFromBuffer(This,buffer,width,height,rowBytes,pixelFormat,flags,outFrame) )
+
+#define IDeckLinkOutput_v7_1_DisplayVideoFrameSync(This,theFrame) \
+ ( (This)->lpVtbl -> DisplayVideoFrameSync(This,theFrame) )
+
+#define IDeckLinkOutput_v7_1_ScheduleVideoFrame(This,theFrame,displayTime,displayDuration,timeScale) \
+ ( (This)->lpVtbl -> ScheduleVideoFrame(This,theFrame,displayTime,displayDuration,timeScale) )
+
+#define IDeckLinkOutput_v7_1_SetScheduledFrameCompletionCallback(This,theCallback) \
+ ( (This)->lpVtbl -> SetScheduledFrameCompletionCallback(This,theCallback) )
+
+#define IDeckLinkOutput_v7_1_EnableAudioOutput(This,sampleRate,sampleType,channelCount) \
+ ( (This)->lpVtbl -> EnableAudioOutput(This,sampleRate,sampleType,channelCount) )
+
+#define IDeckLinkOutput_v7_1_DisableAudioOutput(This) \
+ ( (This)->lpVtbl -> DisableAudioOutput(This) )
+
+#define IDeckLinkOutput_v7_1_WriteAudioSamplesSync(This,buffer,sampleFrameCount,sampleFramesWritten) \
+ ( (This)->lpVtbl -> WriteAudioSamplesSync(This,buffer,sampleFrameCount,sampleFramesWritten) )
+
+#define IDeckLinkOutput_v7_1_BeginAudioPreroll(This) \
+ ( (This)->lpVtbl -> BeginAudioPreroll(This) )
+
+#define IDeckLinkOutput_v7_1_EndAudioPreroll(This) \
+ ( (This)->lpVtbl -> EndAudioPreroll(This) )
+
+#define IDeckLinkOutput_v7_1_ScheduleAudioSamples(This,buffer,sampleFrameCount,streamTime,timeScale,sampleFramesWritten) \
+ ( (This)->lpVtbl -> ScheduleAudioSamples(This,buffer,sampleFrameCount,streamTime,timeScale,sampleFramesWritten) )
+
+#define IDeckLinkOutput_v7_1_GetBufferedAudioSampleFrameCount(This,bufferedSampleCount) \
+ ( (This)->lpVtbl -> GetBufferedAudioSampleFrameCount(This,bufferedSampleCount) )
+
+#define IDeckLinkOutput_v7_1_FlushBufferedAudioSamples(This) \
+ ( (This)->lpVtbl -> FlushBufferedAudioSamples(This) )
+
+#define IDeckLinkOutput_v7_1_SetAudioCallback(This,theCallback) \
+ ( (This)->lpVtbl -> SetAudioCallback(This,theCallback) )
+
+#define IDeckLinkOutput_v7_1_StartScheduledPlayback(This,playbackStartTime,timeScale,playbackSpeed) \
+ ( (This)->lpVtbl -> StartScheduledPlayback(This,playbackStartTime,timeScale,playbackSpeed) )
+
+#define IDeckLinkOutput_v7_1_StopScheduledPlayback(This,stopPlaybackAtTime,actualStopTime,timeScale) \
+ ( (This)->lpVtbl -> StopScheduledPlayback(This,stopPlaybackAtTime,actualStopTime,timeScale) )
+
+#define IDeckLinkOutput_v7_1_GetHardwareReferenceClock(This,desiredTimeScale,elapsedTimeSinceSchedulerBegan) \
+ ( (This)->lpVtbl -> GetHardwareReferenceClock(This,desiredTimeScale,elapsedTimeSinceSchedulerBegan) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkOutput_v7_1_INTERFACE_DEFINED__ */
+
+
+#ifndef __IDeckLinkInput_v7_1_INTERFACE_DEFINED__
+#define __IDeckLinkInput_v7_1_INTERFACE_DEFINED__
+
+/* interface IDeckLinkInput_v7_1 */
+/* [helpstring][uuid][object] */
+
+
+EXTERN_C const IID IID_IDeckLinkInput_v7_1;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("2B54EDEF-5B32-429F-BA11-BB990596EACD")
+ IDeckLinkInput_v7_1 : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE DoesSupportVideoMode(
+ BMDDisplayMode displayMode,
+ BMDPixelFormat pixelFormat,
+ /* [out] */ BMDDisplayModeSupport *result) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetDisplayModeIterator(
+ /* [out] */ IDeckLinkDisplayModeIterator_v7_1 **iterator) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE EnableVideoInput(
+ BMDDisplayMode displayMode,
+ BMDPixelFormat pixelFormat,
+ BMDVideoInputFlags flags) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE DisableVideoInput( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE EnableAudioInput(
+ BMDAudioSampleRate sampleRate,
+ BMDAudioSampleType sampleType,
+ unsigned int channelCount) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE DisableAudioInput( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE ReadAudioSamples(
+ void *buffer,
+ unsigned int sampleFrameCount,
+ /* [out] */ unsigned int *sampleFramesRead,
+ /* [out] */ BMDTimeValue *audioPacketTime,
+ BMDTimeScale timeScale) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetBufferedAudioSampleFrameCount(
+ /* [out] */ unsigned int *bufferedSampleCount) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE StartStreams( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE StopStreams( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE PauseStreams( void) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetCallback(
+ /* [in] */ IDeckLinkInputCallback_v7_1 *theCallback) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct IDeckLinkInput_v7_1Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ IDeckLinkInput_v7_1 * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ IDeckLinkInput_v7_1 * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ IDeckLinkInput_v7_1 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *DoesSupportVideoMode )(
+ IDeckLinkInput_v7_1 * This,
+ BMDDisplayMode displayMode,
+ BMDPixelFormat pixelFormat,
+ /* [out] */ BMDDisplayModeSupport *result);
+
+ HRESULT ( STDMETHODCALLTYPE *GetDisplayModeIterator )(
+ IDeckLinkInput_v7_1 * This,
+ /* [out] */ IDeckLinkDisplayModeIterator_v7_1 **iterator);
+
+ HRESULT ( STDMETHODCALLTYPE *EnableVideoInput )(
+ IDeckLinkInput_v7_1 * This,
+ BMDDisplayMode displayMode,
+ BMDPixelFormat pixelFormat,
+ BMDVideoInputFlags flags);
+
+ HRESULT ( STDMETHODCALLTYPE *DisableVideoInput )(
+ IDeckLinkInput_v7_1 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *EnableAudioInput )(
+ IDeckLinkInput_v7_1 * This,
+ BMDAudioSampleRate sampleRate,
+ BMDAudioSampleType sampleType,
+ unsigned int channelCount);
+
+ HRESULT ( STDMETHODCALLTYPE *DisableAudioInput )(
+ IDeckLinkInput_v7_1 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *ReadAudioSamples )(
+ IDeckLinkInput_v7_1 * This,
+ void *buffer,
+ unsigned int sampleFrameCount,
+ /* [out] */ unsigned int *sampleFramesRead,
+ /* [out] */ BMDTimeValue *audioPacketTime,
+ BMDTimeScale timeScale);
+
+ HRESULT ( STDMETHODCALLTYPE *GetBufferedAudioSampleFrameCount )(
+ IDeckLinkInput_v7_1 * This,
+ /* [out] */ unsigned int *bufferedSampleCount);
+
+ HRESULT ( STDMETHODCALLTYPE *StartStreams )(
+ IDeckLinkInput_v7_1 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *StopStreams )(
+ IDeckLinkInput_v7_1 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *PauseStreams )(
+ IDeckLinkInput_v7_1 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *SetCallback )(
+ IDeckLinkInput_v7_1 * This,
+ /* [in] */ IDeckLinkInputCallback_v7_1 *theCallback);
+
+ END_INTERFACE
+ } IDeckLinkInput_v7_1Vtbl;
+
+ interface IDeckLinkInput_v7_1
+ {
+ CONST_VTBL struct IDeckLinkInput_v7_1Vtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define IDeckLinkInput_v7_1_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define IDeckLinkInput_v7_1_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define IDeckLinkInput_v7_1_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define IDeckLinkInput_v7_1_DoesSupportVideoMode(This,displayMode,pixelFormat,result) \
+ ( (This)->lpVtbl -> DoesSupportVideoMode(This,displayMode,pixelFormat,result) )
+
+#define IDeckLinkInput_v7_1_GetDisplayModeIterator(This,iterator) \
+ ( (This)->lpVtbl -> GetDisplayModeIterator(This,iterator) )
+
+#define IDeckLinkInput_v7_1_EnableVideoInput(This,displayMode,pixelFormat,flags) \
+ ( (This)->lpVtbl -> EnableVideoInput(This,displayMode,pixelFormat,flags) )
+
+#define IDeckLinkInput_v7_1_DisableVideoInput(This) \
+ ( (This)->lpVtbl -> DisableVideoInput(This) )
+
+#define IDeckLinkInput_v7_1_EnableAudioInput(This,sampleRate,sampleType,channelCount) \
+ ( (This)->lpVtbl -> EnableAudioInput(This,sampleRate,sampleType,channelCount) )
+
+#define IDeckLinkInput_v7_1_DisableAudioInput(This) \
+ ( (This)->lpVtbl -> DisableAudioInput(This) )
+
+#define IDeckLinkInput_v7_1_ReadAudioSamples(This,buffer,sampleFrameCount,sampleFramesRead,audioPacketTime,timeScale) \
+ ( (This)->lpVtbl -> ReadAudioSamples(This,buffer,sampleFrameCount,sampleFramesRead,audioPacketTime,timeScale) )
+
+#define IDeckLinkInput_v7_1_GetBufferedAudioSampleFrameCount(This,bufferedSampleCount) \
+ ( (This)->lpVtbl -> GetBufferedAudioSampleFrameCount(This,bufferedSampleCount) )
+
+#define IDeckLinkInput_v7_1_StartStreams(This) \
+ ( (This)->lpVtbl -> StartStreams(This) )
+
+#define IDeckLinkInput_v7_1_StopStreams(This) \
+ ( (This)->lpVtbl -> StopStreams(This) )
+
+#define IDeckLinkInput_v7_1_PauseStreams(This) \
+ ( (This)->lpVtbl -> PauseStreams(This) )
+
+#define IDeckLinkInput_v7_1_SetCallback(This,theCallback) \
+ ( (This)->lpVtbl -> SetCallback(This,theCallback) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __IDeckLinkInput_v7_1_INTERFACE_DEFINED__ */
+
+#endif /* __DeckLinkAPI_LIBRARY_DEFINED__ */
+
+/* Additional Prototypes for ALL interfaces */
+
+/* end of Additional Prototypes */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
diff --git a/intern/decklink/win/DeckLinkAPI_i.c b/intern/decklink/win/DeckLinkAPI_i.c
new file mode 100644
index 00000000000..a13d486aae8
--- /dev/null
+++ b/intern/decklink/win/DeckLinkAPI_i.c
@@ -0,0 +1,343 @@
+
+
+/* this ALWAYS GENERATED file contains the IIDs and CLSIDs */
+
+/* link this file in with the server and any clients */
+
+
+ /* File created by MIDL compiler version 8.00.0603 */
+/* at Mon Apr 13 20:57:05 2015
+ */
+/* Compiler settings for ..\..\include\DeckLinkAPI.idl:
+ Oicf, W1, Zp8, env=Win64 (32b run), target_arch=AMD64 8.00.0603
+ protocol : dce , ms_ext, c_ext, robust
+ error checks: allocation ref bounds_check enum stub_data
+ VC __declspec() decoration level:
+ __declspec(uuid()), __declspec(selectany), __declspec(novtable)
+ DECLSPEC_UUID(), MIDL_INTERFACE()
+*/
+/* @@MIDL_FILE_HEADING( ) */
+
+#pragma warning( disable: 4049 ) /* more than 64k source lines */
+
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+
+#include <rpc.h>
+#include <rpcndr.h>
+
+#ifdef _MIDL_USE_GUIDDEF_
+
+#ifndef INITGUID
+#define INITGUID
+#include <guiddef.h>
+#undef INITGUID
+#else
+#include <guiddef.h>
+#endif
+
+#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \
+ DEFINE_GUID(name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8)
+
+#else // !_MIDL_USE_GUIDDEF_
+
+#ifndef __IID_DEFINED__
+#define __IID_DEFINED__
+
+typedef struct _IID
+{
+ unsigned long x;
+ unsigned short s1;
+ unsigned short s2;
+ unsigned char c[8];
+} IID;
+
+#endif // __IID_DEFINED__
+
+#ifndef CLSID_DEFINED
+#define CLSID_DEFINED
+typedef IID CLSID;
+#endif // CLSID_DEFINED
+
+#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \
+ const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}
+
+#endif !_MIDL_USE_GUIDDEF_
+
+MIDL_DEFINE_GUID(IID, LIBID_DeckLinkAPI,0xD864517A,0xEDD5,0x466D,0x86,0x7D,0xC8,0x19,0xF1,0xC0,0x52,0xBB);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkTimecode,0xBC6CFBD3,0x8317,0x4325,0xAC,0x1C,0x12,0x16,0x39,0x1E,0x93,0x40);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkDisplayModeIterator,0x9C88499F,0xF601,0x4021,0xB8,0x0B,0x03,0x2E,0x4E,0xB4,0x1C,0x35);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkDisplayMode,0x3EB2C1AB,0x0A3D,0x4523,0xA3,0xAD,0xF4,0x0D,0x7F,0xB1,0x4E,0x78);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLink,0xC418FBDD,0x0587,0x48ED,0x8F,0xE5,0x64,0x0F,0x0A,0x14,0xAF,0x91);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkConfiguration,0x1E69FCF6,0x4203,0x4936,0x80,0x76,0x2A,0x9F,0x4C,0xFD,0x50,0xCB);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkDeckControlStatusCallback,0x53436FFB,0xB434,0x4906,0xBA,0xDC,0xAE,0x30,0x60,0xFF,0xE8,0xEF);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkDeckControl,0x8E1C3ACE,0x19C7,0x4E00,0x8B,0x92,0xD8,0x04,0x31,0xD9,0x58,0xBE);
+
+
+MIDL_DEFINE_GUID(IID, IID_IBMDStreamingDeviceNotificationCallback,0xF9531D64,0x3305,0x4B29,0xA3,0x87,0x7F,0x74,0xBB,0x0D,0x0E,0x84);
+
+
+MIDL_DEFINE_GUID(IID, IID_IBMDStreamingH264InputCallback,0x823C475F,0x55AE,0x46F9,0x89,0x0C,0x53,0x7C,0xC5,0xCE,0xDC,0xCA);
+
+
+MIDL_DEFINE_GUID(IID, IID_IBMDStreamingDiscovery,0x2C837444,0xF989,0x4D87,0x90,0x1A,0x47,0xC8,0xA3,0x6D,0x09,0x6D);
+
+
+MIDL_DEFINE_GUID(IID, IID_IBMDStreamingVideoEncodingMode,0x1AB8035B,0xCD13,0x458D,0xB6,0xDF,0x5E,0x8F,0x7C,0x21,0x41,0xD9);
+
+
+MIDL_DEFINE_GUID(IID, IID_IBMDStreamingMutableVideoEncodingMode,0x19BF7D90,0x1E0A,0x400D,0xB2,0xC6,0xFF,0xC4,0xE7,0x8A,0xD4,0x9D);
+
+
+MIDL_DEFINE_GUID(IID, IID_IBMDStreamingVideoEncodingModePresetIterator,0x7AC731A3,0xC950,0x4AD0,0x80,0x4A,0x83,0x77,0xAA,0x51,0xC6,0xC4);
+
+
+MIDL_DEFINE_GUID(IID, IID_IBMDStreamingDeviceInput,0x24B6B6EC,0x1727,0x44BB,0x98,0x18,0x34,0xFF,0x08,0x6A,0xCF,0x98);
+
+
+MIDL_DEFINE_GUID(IID, IID_IBMDStreamingH264NALPacket,0xE260E955,0x14BE,0x4395,0x97,0x75,0x9F,0x02,0xCC,0x0A,0x9D,0x89);
+
+
+MIDL_DEFINE_GUID(IID, IID_IBMDStreamingAudioPacket,0xD9EB5902,0x1AD2,0x43F4,0x9E,0x2C,0x3C,0xFA,0x50,0xB5,0xEE,0x19);
+
+
+MIDL_DEFINE_GUID(IID, IID_IBMDStreamingMPEG2TSPacket,0x91810D1C,0x4FB3,0x4AAA,0xAE,0x56,0xFA,0x30,0x1D,0x3D,0xFA,0x4C);
+
+
+MIDL_DEFINE_GUID(IID, IID_IBMDStreamingH264NALParser,0x5867F18C,0x5BFA,0x4CCC,0xB2,0xA7,0x9D,0xFD,0x14,0x04,0x17,0xD2);
+
+
+MIDL_DEFINE_GUID(CLSID, CLSID_CBMDStreamingDiscovery,0x0CAA31F6,0x8A26,0x40B0,0x86,0xA4,0xBF,0x58,0xDC,0xCA,0x71,0x0C);
+
+
+MIDL_DEFINE_GUID(CLSID, CLSID_CBMDStreamingH264NALParser,0x7753EFBD,0x951C,0x407C,0x97,0xA5,0x23,0xC7,0x37,0xB7,0x3B,0x52);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkVideoOutputCallback,0x20AA5225,0x1958,0x47CB,0x82,0x0B,0x80,0xA8,0xD5,0x21,0xA6,0xEE);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkInputCallback,0xDD04E5EC,0x7415,0x42AB,0xAE,0x4A,0xE8,0x0C,0x4D,0xFC,0x04,0x4A);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkMemoryAllocator,0xB36EB6E7,0x9D29,0x4AA8,0x92,0xEF,0x84,0x3B,0x87,0xA2,0x89,0xE8);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkAudioOutputCallback,0x403C681B,0x7F46,0x4A12,0xB9,0x93,0x2B,0xB1,0x27,0x08,0x4E,0xE6);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkIterator,0x50FB36CD,0x3063,0x4B73,0xBD,0xBB,0x95,0x80,0x87,0xF2,0xD8,0xBA);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkAPIInformation,0x7BEA3C68,0x730D,0x4322,0xAF,0x34,0x8A,0x71,0x52,0xB5,0x32,0xA4);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkOutput,0xCC5C8A6E,0x3F2F,0x4B3A,0x87,0xEA,0xFD,0x78,0xAF,0x30,0x05,0x64);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkInput,0xAF22762B,0xDFAC,0x4846,0xAA,0x79,0xFA,0x88,0x83,0x56,0x09,0x95);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkVideoFrame,0x3F716FE0,0xF023,0x4111,0xBE,0x5D,0xEF,0x44,0x14,0xC0,0x5B,0x17);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkMutableVideoFrame,0x69E2639F,0x40DA,0x4E19,0xB6,0xF2,0x20,0xAC,0xE8,0x15,0xC3,0x90);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkVideoFrame3DExtensions,0xDA0F7E4A,0xEDC7,0x48A8,0x9C,0xDD,0x2D,0xB5,0x1C,0x72,0x9C,0xD7);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkVideoInputFrame,0x05CFE374,0x537C,0x4094,0x9A,0x57,0x68,0x05,0x25,0x11,0x8F,0x44);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkVideoFrameAncillary,0x732E723C,0xD1A4,0x4E29,0x9E,0x8E,0x4A,0x88,0x79,0x7A,0x00,0x04);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkAudioInputPacket,0xE43D5870,0x2894,0x11DE,0x8C,0x30,0x08,0x00,0x20,0x0C,0x9A,0x66);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkScreenPreviewCallback,0xB1D3F49A,0x85FE,0x4C5D,0x95,0xC8,0x0B,0x5D,0x5D,0xCC,0xD4,0x38);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkGLScreenPreviewHelper,0x504E2209,0xCAC7,0x4C1A,0x9F,0xB4,0xC5,0xBB,0x62,0x74,0xD2,0x2F);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkDX9ScreenPreviewHelper,0x2094B522,0xD1A1,0x40C0,0x9A,0xC7,0x1C,0x01,0x22,0x18,0xEF,0x02);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkNotificationCallback,0xb002a1ec,0x070d,0x4288,0x82,0x89,0xbd,0x5d,0x36,0xe5,0xff,0x0d);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkNotification,0x0a1fb207,0xe215,0x441b,0x9b,0x19,0x6f,0xa1,0x57,0x59,0x46,0xc5);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkAttributes,0xABC11843,0xD966,0x44CB,0x96,0xE2,0xA1,0xCB,0x5D,0x31,0x35,0xC4);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkKeyer,0x89AFCAF5,0x65F8,0x421E,0x98,0xF7,0x96,0xFE,0x5F,0x5B,0xFB,0xA3);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkVideoConversion,0x3BBCB8A2,0xDA2C,0x42D9,0xB5,0xD8,0x88,0x08,0x36,0x44,0xE9,0x9A);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkDeviceNotificationCallback,0x4997053B,0x0ADF,0x4CC8,0xAC,0x70,0x7A,0x50,0xC4,0xBE,0x72,0x8F);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkDiscovery,0xCDBF631C,0xBC76,0x45FA,0xB4,0x4D,0xC5,0x50,0x59,0xBC,0x61,0x01);
+
+
+MIDL_DEFINE_GUID(CLSID, CLSID_CDeckLinkIterator,0x1F2E109A,0x8F4F,0x49E4,0x92,0x03,0x13,0x55,0x95,0xCB,0x6F,0xA5);
+
+
+MIDL_DEFINE_GUID(CLSID, CLSID_CDeckLinkAPIInformation,0x263CA19F,0xED09,0x482E,0x9F,0x9D,0x84,0x00,0x57,0x83,0xA2,0x37);
+
+
+MIDL_DEFINE_GUID(CLSID, CLSID_CDeckLinkGLScreenPreviewHelper,0xF63E77C7,0xB655,0x4A4A,0x9A,0xD0,0x3C,0xA8,0x5D,0x39,0x43,0x43);
+
+
+MIDL_DEFINE_GUID(CLSID, CLSID_CDeckLinkDX9ScreenPreviewHelper,0xCC010023,0xE01D,0x4525,0x9D,0x59,0x80,0xC8,0xAB,0x3D,0xC7,0xA0);
+
+
+MIDL_DEFINE_GUID(CLSID, CLSID_CDeckLinkVideoConversion,0x7DBBBB11,0x5B7B,0x467D,0xAE,0xA4,0xCE,0xA4,0x68,0xFD,0x36,0x8C);
+
+
+MIDL_DEFINE_GUID(CLSID, CLSID_CDeckLinkDiscovery,0x1073A05C,0xD885,0x47E9,0xB3,0xC6,0x12,0x9B,0x3F,0x9F,0x64,0x8B);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkConfiguration_v10_2,0xC679A35B,0x610C,0x4D09,0xB7,0x48,0x1D,0x04,0x78,0x10,0x0F,0xC0);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkOutput_v9_9,0xA3EF0963,0x0862,0x44ED,0x92,0xA9,0xEE,0x89,0xAB,0xF4,0x31,0xC7);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkInput_v9_2,0x6D40EF78,0x28B9,0x4E21,0x99,0x0D,0x95,0xBB,0x77,0x50,0xA0,0x4F);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkDeckControlStatusCallback_v8_1,0xE5F693C1,0x4283,0x4716,0xB1,0x8F,0xC1,0x43,0x15,0x21,0x95,0x5B);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkDeckControl_v8_1,0x522A9E39,0x0F3C,0x4742,0x94,0xEE,0xD8,0x0D,0xE3,0x35,0xDA,0x1D);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLink_v8_0,0x62BFF75D,0x6569,0x4E55,0x8D,0x4D,0x66,0xAA,0x03,0x82,0x9A,0xBC);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkIterator_v8_0,0x74E936FC,0xCC28,0x4A67,0x81,0xA0,0x1E,0x94,0xE5,0x2D,0x4E,0x69);
+
+
+MIDL_DEFINE_GUID(CLSID, CLSID_CDeckLinkIterator_v8_0,0xD9EDA3B3,0x2887,0x41FA,0xB7,0x24,0x01,0x7C,0xF1,0xEB,0x1D,0x37);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkDeckControl_v7_9,0xA4D81043,0x0619,0x42B7,0x8E,0xD6,0x60,0x2D,0x29,0x04,0x1D,0xF7);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkDisplayModeIterator_v7_6,0x455D741F,0x1779,0x4800,0x86,0xF5,0x0B,0x5D,0x13,0xD7,0x97,0x51);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkDisplayMode_v7_6,0x87451E84,0x2B7E,0x439E,0xA6,0x29,0x43,0x93,0xEA,0x4A,0x85,0x50);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkOutput_v7_6,0x29228142,0xEB8C,0x4141,0xA6,0x21,0xF7,0x40,0x26,0x45,0x09,0x55);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkInput_v7_6,0x300C135A,0x9F43,0x48E2,0x99,0x06,0x6D,0x79,0x11,0xD9,0x3C,0xF1);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkTimecode_v7_6,0xEFB9BCA6,0xA521,0x44F7,0xBD,0x69,0x23,0x32,0xF2,0x4D,0x9E,0xE6);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkVideoFrame_v7_6,0xA8D8238E,0x6B18,0x4196,0x99,0xE1,0x5A,0xF7,0x17,0xB8,0x3D,0x32);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkMutableVideoFrame_v7_6,0x46FCEE00,0xB4E6,0x43D0,0x91,0xC0,0x02,0x3A,0x7F,0xCE,0xB3,0x4F);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkVideoInputFrame_v7_6,0x9A74FA41,0xAE9F,0x47AC,0x8C,0xF4,0x01,0xF4,0x2D,0xD5,0x99,0x65);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkScreenPreviewCallback_v7_6,0x373F499D,0x4B4D,0x4518,0xAD,0x22,0x63,0x54,0xE5,0xA5,0x82,0x5E);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkGLScreenPreviewHelper_v7_6,0xBA575CD9,0xA15E,0x497B,0xB2,0xC2,0xF9,0xAF,0xE7,0xBE,0x4E,0xBA);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkVideoConversion_v7_6,0x3EB504C9,0xF97D,0x40FE,0xA1,0x58,0xD4,0x07,0xD4,0x8C,0xB5,0x3B);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkConfiguration_v7_6,0xB8EAD569,0xB764,0x47F0,0xA7,0x3F,0xAE,0x40,0xDF,0x6C,0xBF,0x10);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkVideoOutputCallback_v7_6,0xE763A626,0x4A3C,0x49D1,0xBF,0x13,0xE7,0xAD,0x36,0x92,0xAE,0x52);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkInputCallback_v7_6,0x31D28EE7,0x88B6,0x4CB1,0x89,0x7A,0xCD,0xBF,0x79,0xA2,0x64,0x14);
+
+
+MIDL_DEFINE_GUID(CLSID, CLSID_CDeckLinkGLScreenPreviewHelper_v7_6,0xD398CEE7,0x4434,0x4CA3,0x9B,0xA6,0x5A,0xE3,0x45,0x56,0xB9,0x05);
+
+
+MIDL_DEFINE_GUID(CLSID, CLSID_CDeckLinkVideoConversion_v7_6,0xFFA84F77,0x73BE,0x4FB7,0xB0,0x3E,0xB5,0xE4,0x4B,0x9F,0x75,0x9B);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkInputCallback_v7_3,0xFD6F311D,0x4D00,0x444B,0x9E,0xD4,0x1F,0x25,0xB5,0x73,0x0A,0xD0);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkOutput_v7_3,0x271C65E3,0xC323,0x4344,0xA3,0x0F,0xD9,0x08,0xBC,0xB2,0x0A,0xA3);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkInput_v7_3,0x4973F012,0x9925,0x458C,0x87,0x1C,0x18,0x77,0x4C,0xDB,0xBE,0xCB);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkVideoInputFrame_v7_3,0xCF317790,0x2894,0x11DE,0x8C,0x30,0x08,0x00,0x20,0x0C,0x9A,0x66);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkDisplayModeIterator_v7_1,0xB28131B6,0x59AC,0x4857,0xB5,0xAC,0xCD,0x75,0xD5,0x88,0x3E,0x2F);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkDisplayMode_v7_1,0xAF0CD6D5,0x8376,0x435E,0x84,0x33,0x54,0xF9,0xDD,0x53,0x0A,0xC3);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkVideoFrame_v7_1,0x333F3A10,0x8C2D,0x43CF,0xB7,0x9D,0x46,0x56,0x0F,0xEE,0xA1,0xCE);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkVideoInputFrame_v7_1,0xC8B41D95,0x8848,0x40EE,0x9B,0x37,0x6E,0x34,0x17,0xFB,0x11,0x4B);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkAudioInputPacket_v7_1,0xC86DE4F6,0xA29F,0x42E3,0xAB,0x3A,0x13,0x63,0xE2,0x9F,0x07,0x88);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkVideoOutputCallback_v7_1,0xEBD01AFA,0xE4B0,0x49C6,0xA0,0x1D,0xED,0xB9,0xD1,0xB5,0x5F,0xD9);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkInputCallback_v7_1,0x7F94F328,0x5ED4,0x4E9F,0x97,0x29,0x76,0xA8,0x6B,0xDC,0x99,0xCC);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkOutput_v7_1,0xAE5B3E9B,0x4E1E,0x4535,0xB6,0xE8,0x48,0x0F,0xF5,0x2F,0x6C,0xE5);
+
+
+MIDL_DEFINE_GUID(IID, IID_IDeckLinkInput_v7_1,0x2B54EDEF,0x5B32,0x429F,0xBA,0x11,0xBB,0x99,0x05,0x96,0xEA,0xCD);
+
+#undef MIDL_DEFINE_GUID
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt
index d31e9472168..e549a48d4b9 100644
--- a/intern/ghost/CMakeLists.txt
+++ b/intern/ghost/CMakeLists.txt
@@ -223,6 +223,10 @@ elseif(WITH_X11)
)
endif()
+ if(WITH_X11_ALPHA)
+ add_definitions(-DWITH_X11_ALPHA)
+ endif()
+
if(WITH_INPUT_NDOF)
list(APPEND SRC
intern/GHOST_NDOFManagerUnix.cpp
diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h
index 4c48473c7b8..08045b93db9 100644
--- a/intern/ghost/GHOST_ISystem.h
+++ b/intern/ghost/GHOST_ISystem.h
@@ -277,7 +277,7 @@ public:
*/
virtual GHOST_TSuccess beginFullScreen(
const GHOST_DisplaySetting& setting, GHOST_IWindow **window,
- const bool stereoVisual, const GHOST_TUns16 numOfAASamples = 0) = 0;
+ const bool stereoVisual, const bool alphaBackground = 0, const GHOST_TUns16 numOfAASamples = 0) = 0;
/**
* Updates the resolution while in fullscreen mode.
diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h
index b3e560ab4b4..0dd5d15b011 100644
--- a/intern/ghost/GHOST_Types.h
+++ b/intern/ghost/GHOST_Types.h
@@ -57,7 +57,8 @@ typedef struct {
typedef enum {
GHOST_glStereoVisual = (1 << 0),
- GHOST_glDebugContext = (1 << 1)
+ GHOST_glDebugContext = (1 << 1),
+ GHOST_glAlphaBackground = (1 << 2),
} GHOST_GLFlags;
@@ -529,7 +530,7 @@ typedef struct {
#ifdef _WIN32
-typedef long GHOST_TEmbedderWindowID;
+typedef void* GHOST_TEmbedderWindowID;
#endif // _WIN32
#ifndef _WIN32
diff --git a/intern/ghost/intern/GHOST_ContextGLX.cpp b/intern/ghost/intern/GHOST_ContextGLX.cpp
index 90d810b7986..9ac61db4041 100644
--- a/intern/ghost/intern/GHOST_ContextGLX.cpp
+++ b/intern/ghost/intern/GHOST_ContextGLX.cpp
@@ -62,6 +62,7 @@ GHOST_ContextGLX::GHOST_ContextGLX(
Window window,
Display *display,
XVisualInfo *visualInfo,
+ GLXFBConfig fbconfig,
int contextProfileMask,
int contextMajorVersion,
int contextMinorVersion,
@@ -70,6 +71,7 @@ GHOST_ContextGLX::GHOST_ContextGLX(
: GHOST_Context(stereoVisual, numOfAASamples),
m_display(display),
m_visualInfo(visualInfo),
+ m_fbconfig(fbconfig),
m_window(window),
m_contextProfileMask(contextProfileMask),
m_contextMajorVersion(contextMajorVersion),
@@ -153,15 +155,7 @@ void GHOST_ContextGLX::initContextGLXEW()
GHOST_TSuccess GHOST_ContextGLX::initializeDrawingContext()
{
-#ifdef WITH_X11_XINPUT
- /* use our own event handlers to avoid exiting blender,
- * this would happen for eg:
- * if you open blender, unplug a tablet, then open a new window. */
- XErrorHandler old_handler = XSetErrorHandler (GHOST_X11_ApplicationErrorHandler );
- XIOErrorHandler old_handler_io = XSetIOErrorHandler(GHOST_X11_ApplicationIOErrorHandler);
-#endif
-
-
+ GHOST_X11_ERROR_HANDLERS_OVERRIDE(handler_store);
/* -------------------------------------------------------------------- */
/* Begin Inline Glew */
@@ -285,19 +279,24 @@ const bool GLXEW_ARB_create_context_robustness =
attribs[i++] = 0;
/* Create a GL 3.x context */
- GLXFBConfig *framebuffer_config = NULL;
- {
- int glx_attribs[64];
- int fbcount = 0;
+ if (m_fbconfig) {
+ m_context = glXCreateContextAttribsARB(m_display, m_fbconfig, s_sharedContext, true, attribs);
+ }
+ else {
+ GLXFBConfig *framebuffer_config = NULL;
+ {
+ int glx_attribs[64];
+ int fbcount = 0;
- GHOST_X11_GL_GetAttributes(glx_attribs, 64, m_numOfAASamples, m_stereoVisual, true);
+ GHOST_X11_GL_GetAttributes(glx_attribs, 64, m_numOfAASamples, m_stereoVisual, false, true);
- framebuffer_config = glXChooseFBConfig(m_display, DefaultScreen(m_display), glx_attribs, &fbcount);
- }
+ framebuffer_config = glXChooseFBConfig(m_display, DefaultScreen(m_display), glx_attribs, &fbcount);
+ }
- if (framebuffer_config) {
- m_context = glXCreateContextAttribsARB(m_display, framebuffer_config[0], s_sharedContext, True, attribs);
- XFree(framebuffer_config);
+ if (framebuffer_config) {
+ m_context = glXCreateContextAttribsARB(m_display, framebuffer_config[0], s_sharedContext, True, attribs);
+ XFree(framebuffer_config);
+ }
}
}
else {
@@ -343,11 +342,8 @@ const bool GLXEW_ARB_create_context_robustness =
success = GHOST_kFailure;
}
-#ifdef WITH_X11_XINPUT
- /* Restore handler */
- XSetErrorHandler (old_handler);
- XSetIOErrorHandler(old_handler_io);
-#endif
+
+ GHOST_X11_ERROR_HANDLERS_RESTORE(handler_store);
return success;
}
@@ -401,16 +397,11 @@ GHOST_TSuccess GHOST_ContextGLX::getSwapInterval(int &intervalOut)
int GHOST_X11_GL_GetAttributes(
int *attribs, int attribs_max,
int samples, bool is_stereo_visual,
+ bool need_alpha,
bool for_fb_config)
{
int i = 0;
-#ifdef GHOST_OPENGL_ALPHA
- const bool need_alpha = true;
-#else
- const bool need_alpha = false;
-#endif
-
#ifdef GHOST_OPENGL_STENCIL
const bool need_stencil = true;
#else
diff --git a/intern/ghost/intern/GHOST_ContextGLX.h b/intern/ghost/intern/GHOST_ContextGLX.h
index 8c2231a0b01..f0f010d1942 100644
--- a/intern/ghost/intern/GHOST_ContextGLX.h
+++ b/intern/ghost/intern/GHOST_ContextGLX.h
@@ -66,6 +66,7 @@ public:
Window window,
Display *display,
XVisualInfo *visualInfo,
+ GLXFBConfig fbconfig,
int contextProfileMask,
int contextMajorVersion,
int contextMinorVersion,
@@ -128,6 +129,7 @@ private:
Display *m_display;
XVisualInfo *m_visualInfo;
+ GLXFBConfig m_fbconfig;
Window m_window;
const int m_contextProfileMask;
@@ -151,6 +153,7 @@ private:
int GHOST_X11_GL_GetAttributes(
int *attribs, int attribs_max,
int samples, bool is_stereo_visual,
+ bool need_alpha,
bool for_fb_config);
#endif // __GHOST_CONTEXTGLX_H__
diff --git a/intern/ghost/intern/GHOST_ContextWGL.cpp b/intern/ghost/intern/GHOST_ContextWGL.cpp
index cb580f60bd7..abce3ea6588 100644
--- a/intern/ghost/intern/GHOST_ContextWGL.cpp
+++ b/intern/ghost/intern/GHOST_ContextWGL.cpp
@@ -63,6 +63,7 @@ static bool is_crappy_intel_card()
GHOST_ContextWGL::GHOST_ContextWGL(
bool stereoVisual,
+ bool alphaBackground,
GHOST_TUns16 numOfAASamples,
HWND hWnd,
HDC hDC,
@@ -78,6 +79,7 @@ GHOST_ContextWGL::GHOST_ContextWGL(
m_contextMajorVersion(contextMajorVersion),
m_contextMinorVersion(contextMinorVersion),
m_contextFlags(contextFlags),
+ m_alphaBackground(alphaBackground),
m_contextResetNotificationStrategy(contextResetNotificationStrategy),
m_hGLRC(NULL)
#ifdef WITH_GLEW_MX
@@ -168,7 +170,7 @@ GHOST_TSuccess GHOST_ContextWGL::activateDrawingContext()
/* Ron Fosner's code for weighting pixel formats and forcing software.
* See http://www.opengl.org/resources/faq/technical/weight.cpp
*/
-static int weight_pixel_format(PIXELFORMATDESCRIPTOR &pfd)
+static int weight_pixel_format(PIXELFORMATDESCRIPTOR &pfd, PIXELFORMATDESCRIPTOR &preferredPFD)
{
int weight = 0;
@@ -194,11 +196,12 @@ static int weight_pixel_format(PIXELFORMATDESCRIPTOR &pfd)
weight += pfd.cColorBits - 8;
-#ifdef GHOST_OPENGL_ALPHA
- if (pfd.cAlphaBits > 0)
+ if (preferredPFD.cAlphaBits > 0 && pfd.cAlphaBits > 0)
+ weight++;
+#ifdef WIN32_COMPOSITING
+ if ((preferredPFD.dwFlags & PFD_SUPPORT_COMPOSITION) && (pfd.dwFlags & PFD_SUPPORT_COMPOSITION))
weight++;
#endif
-
#ifdef GHOST_OPENGL_STENCIL
if (pfd.cStencilBits >= 8)
weight++;
@@ -239,7 +242,7 @@ static int choose_pixel_format_legacy(HDC hDC, PIXELFORMATDESCRIPTOR &preferredP
WIN32_CHK(check == lastPFD);
- int w = weight_pixel_format(pfd);
+ int w = weight_pixel_format(pfd, preferredPFD);
if (w > weight) {
weight = w;
@@ -496,7 +499,10 @@ int GHOST_ContextWGL::_choose_pixel_format_arb_2(
{
std::vector<int> iAttributes;
+#define _MAX_PIXEL_FORMATS 32
+
int iPixelFormat = 0;
+ int iPixelFormats[_MAX_PIXEL_FORMATS];
int samples;
@@ -521,8 +527,31 @@ int GHOST_ContextWGL::_choose_pixel_format_arb_2(
sRGB);
UINT nNumFormats;
- WIN32_CHK(wglChoosePixelFormatARB(m_hDC, &(iAttributes[0]), NULL, 1, &iPixelFormat, &nNumFormats));
-
+ WIN32_CHK(wglChoosePixelFormatARB(m_hDC, &(iAttributes[0]), NULL, _MAX_PIXEL_FORMATS, iPixelFormats, &nNumFormats));
+
+#ifdef WIN32_COMPOSITING
+ if (needAlpha && nNumFormats) {
+ // scan through all pixel format to make sure one supports compositing
+ PIXELFORMATDESCRIPTOR pfd;
+ int i;
+
+ for (i = 0; i < nNumFormats; i++) {
+ if (DescribePixelFormat(m_hDC, iPixelFormats[i], sizeof(PIXELFORMATDESCRIPTOR), &pfd)) {
+ if (pfd.dwFlags & PFD_SUPPORT_COMPOSITION) {
+ iPixelFormat = iPixelFormats[i];
+ break;
+ }
+ }
+ }
+ if (i == nNumFormats) {
+ fprintf(stderr,
+ "Warning! Unable to find a pixel format with compositing capability.\n");
+ iPixelFormat = iPixelFormats[0];
+ }
+ }
+ else
+#endif
+ iPixelFormat = iPixelFormats[0];
/* total number of formats that match (regardless of size of iPixelFormat array)
* see: WGL_ARB_pixel_format extension spec */
if (nNumFormats > 0)
@@ -538,7 +567,7 @@ int GHOST_ContextWGL::_choose_pixel_format_arb_2(
// check how many samples were actually gotten
if (iPixelFormat != 0) {
int iQuery[] = { WGL_SAMPLES_ARB };
- int actualSamples;
+ int actualSamples, alphaBits;
wglGetPixelFormatAttribivARB(m_hDC, iPixelFormat, 0, 1, iQuery, &actualSamples);
if (actualSamples != *numOfAASamples) {
@@ -549,6 +578,14 @@ int GHOST_ContextWGL::_choose_pixel_format_arb_2(
*numOfAASamples = actualSamples; // set context property to actual value
}
+ if (needAlpha) {
+ iQuery[0] = WGL_ALPHA_BITS_ARB;
+ wglGetPixelFormatAttribivARB(m_hDC, iPixelFormat, 0, 1, iQuery, &alphaBits);
+ if (alphaBits == 0) {
+ fprintf(stderr,
+ "Warning! Unable to find a frame buffer with alpha channel.\n");
+ }
+ }
}
else {
*numOfAASamples = 0;
@@ -670,20 +707,27 @@ int GHOST_ContextWGL::choose_pixel_format(
PIXELFORMATDESCRIPTOR preferredPFD = {
sizeof(PIXELFORMATDESCRIPTOR), /* size */
1, /* version */
+ (DWORD) (
PFD_SUPPORT_OPENGL |
PFD_DRAW_TO_WINDOW |
PFD_SWAP_COPY | /* support swap copy */
PFD_DOUBLEBUFFER | /* support double-buffering */
- (stereoVisual ? PFD_STEREO : 0), /* support stereo */
+ (stereoVisual ? PFD_STEREO : 0) |/* support stereo */
+ (
+#ifdef WIN32_COMPOSITING
+ needAlpha ? PFD_SUPPORT_COMPOSITION : /* support composition for transparent background */
+#endif
+ 0
+ )),
PFD_TYPE_RGBA, /* color type */
- 24, /* preferred color depth */
+ (BYTE) (needAlpha ? 32 : 24), /* preferred color depth */
0, 0, 0, 0, 0, 0, /* color bits (ignored) */
- needAlpha ? 8 : 0, /* alpha buffer */
+ (BYTE) (needAlpha ? 8 : 0), /* alpha buffer */
0, /* alpha shift (ignored) */
0, /* no accumulation buffer */
0, 0, 0, 0, /* accum bits (ignored) */
24, /* depth buffer */
- needStencil ? 8 : 0, /* stencil buffer */
+ (BYTE) (needStencil ? 8 : 0), /* stencil buffer */
0, /* no auxiliary buffers */
PFD_MAIN_PLANE, /* main layer */
0, /* reserved */
@@ -727,11 +771,7 @@ static void reportContextString(const char *name, const char *dummy, const char
GHOST_TSuccess GHOST_ContextWGL::initializeDrawingContext()
{
-#ifdef GHOST_OPENGL_ALPHA
- const bool needAlpha = true;
-#else
- const bool needAlpha = false;
-#endif
+ const bool needAlpha = m_alphaBackground;
#ifdef GHOST_OPENGL_STENCIL
const bool needStencil = true;
diff --git a/intern/ghost/intern/GHOST_ContextWGL.h b/intern/ghost/intern/GHOST_ContextWGL.h
index 3b04a33b662..580b4dcb82f 100644
--- a/intern/ghost/intern/GHOST_ContextWGL.h
+++ b/intern/ghost/intern/GHOST_ContextWGL.h
@@ -32,6 +32,8 @@
#ifndef __GHOST_CONTEXTWGL_H__
#define __GHOST_CONTEXTWGL_H__
+//#define WIN32_COMPOSITING
+
#include "GHOST_Context.h"
#ifdef WITH_GLEW_MX
@@ -65,6 +67,7 @@ public:
*/
GHOST_ContextWGL(
bool stereoVisual,
+ bool alphaBackground,
GHOST_TUns16 numOfAASamples,
HWND hWnd,
HDC hDC,
@@ -164,6 +167,7 @@ private:
const int m_contextMajorVersion;
const int m_contextMinorVersion;
const int m_contextFlags;
+ const bool m_alphaBackground;
const int m_contextResetNotificationStrategy;
HGLRC m_hGLRC;
diff --git a/intern/ghost/intern/GHOST_DropTargetWin32.cpp b/intern/ghost/intern/GHOST_DropTargetWin32.cpp
index 96ff79aa65a..cbf37bf1b16 100644
--- a/intern/ghost/intern/GHOST_DropTargetWin32.cpp
+++ b/intern/ghost/intern/GHOST_DropTargetWin32.cpp
@@ -125,8 +125,7 @@ HRESULT __stdcall GHOST_DropTargetWin32::DragEnter(IDataObject *pDataObject, DWO
*/
HRESULT __stdcall GHOST_DropTargetWin32::DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
{
- if (m_window->canAcceptDragOperation())
- {
+ if (m_window->canAcceptDragOperation()) {
*pdwEffect = allowedDropEffect(*pdwEffect);
}
else {
@@ -154,8 +153,7 @@ HRESULT __stdcall GHOST_DropTargetWin32::DragLeave(void)
HRESULT __stdcall GHOST_DropTargetWin32::Drop(IDataObject *pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
{
void *data = getGhostData(pDataObject);
- if (m_window->canAcceptDragOperation())
- {
+ if (m_window->canAcceptDragOperation()) {
*pdwEffect = allowedDropEffect(*pdwEffect);
}
@@ -189,15 +187,13 @@ GHOST_TDragnDropTypes GHOST_DropTargetWin32::getGhostType(IDataObject *pDataObje
* conversion, but we do the conversion ourself with WC_NO_BEST_FIT_CHARS.
*/
FORMATETC fmtetc = { CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
- if (pDataObject->QueryGetData(&fmtetc) == S_OK)
- {
+ if (pDataObject->QueryGetData(&fmtetc) == S_OK) {
return GHOST_kDragnDropTypeString;
}
// Filesnames
fmtetc.cfFormat = CF_HDROP;
- if (pDataObject->QueryGetData(&fmtetc) == S_OK)
- {
+ if (pDataObject->QueryGetData(&fmtetc) == S_OK) {
return GHOST_kDragnDropTypeFilenames;
}
diff --git a/intern/ghost/intern/GHOST_EventManager.cpp b/intern/ghost/intern/GHOST_EventManager.cpp
index bc531bd515b..0675ac734ed 100644
--- a/intern/ghost/intern/GHOST_EventManager.cpp
+++ b/intern/ghost/intern/GHOST_EventManager.cpp
@@ -167,11 +167,9 @@ void GHOST_EventManager::removeWindowEvents(GHOST_IWindow *window)
{
TEventStack::iterator iter;
iter = m_events.begin();
- while (iter != m_events.end())
- {
+ while (iter != m_events.end()) {
GHOST_IEvent *event = *iter;
- if (event->getWindow() == window)
- {
+ if (event->getWindow() == window) {
GHOST_PRINT("GHOST_EventManager::removeWindowEvents(): removing event\n");
/*
* Found an event for this window, remove it.
@@ -191,11 +189,9 @@ void GHOST_EventManager::removeTypeEvents(GHOST_TEventType type, GHOST_IWindow *
{
TEventStack::iterator iter;
iter = m_events.begin();
- while (iter != m_events.end())
- {
+ while (iter != m_events.end()) {
GHOST_IEvent *event = *iter;
- if ((event->getType() == type) && (!window || (event->getWindow() == window)))
- {
+ if ((event->getType() == type) && (!window || (event->getWindow() == window))) {
GHOST_PRINT("GHOST_EventManager::removeTypeEvents(): removing event\n");
/*
* Found an event of this type for the window, remove it.
diff --git a/intern/ghost/intern/GHOST_ImeWin32.cpp b/intern/ghost/intern/GHOST_ImeWin32.cpp
index af5a2ed7097..96bd12faef8 100644
--- a/intern/ghost/intern/GHOST_ImeWin32.cpp
+++ b/intern/ghost/intern/GHOST_ImeWin32.cpp
@@ -64,7 +64,7 @@ bool GHOST_ImeWin32::SetInputLanguage()
* while composing a text.
*/
HKL keyboard_layout = ::GetKeyboardLayout(0);
- input_language_id_ = reinterpret_cast<LANGID>(keyboard_layout);
+ input_language_id_ = LOWORD(keyboard_layout);
ime_status_ = ::ImmIsIME(keyboard_layout);
return ime_status_;
}
diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp
index 27285e49e9e..c8e14ad357f 100644
--- a/intern/ghost/intern/GHOST_NDOFManager.cpp
+++ b/intern/ghost/intern/GHOST_NDOFManager.cpp
@@ -299,6 +299,12 @@ bool GHOST_NDOFManager::setDevice(unsigned short vendor_id, unsigned short produ
m_buttonMask = 0x07C0F137;
m_hidMap = Modern3Dx_HID_map;
break;
+ case 0xC633:
+ puts("ndof: using SpaceMouse Enterprise");
+ m_deviceType = NDOF_SpaceMouseEnterprise;
+ m_buttonCount = 31;
+ m_hidMap = Modern3Dx_HID_map;
+ break;
default:
printf("ndof: unknown 3Dconnexion product %04hx\n", product_id);
@@ -372,8 +378,7 @@ void GHOST_NDOFManager::updateButton(int button_number, bool press, GHOST_TUns64
NDOF_ButtonT button = (button_number < m_buttonCount) ? m_hidMap[button_number] : NDOF_BUTTON_NONE;
- switch (button)
- {
+ switch (button) {
case NDOF_BUTTON_NONE:
#ifdef DEBUG_NDOF_BUTTONS
printf("discarded\n");
diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h
index ba82f37bb2a..d3c70bbac50 100644
--- a/intern/ghost/intern/GHOST_NDOFManager.h
+++ b/intern/ghost/intern/GHOST_NDOFManager.h
@@ -40,6 +40,7 @@ typedef enum {
NDOF_SpaceMousePro,
NDOF_SpaceMouseWireless,
NDOF_SpaceMouseProWireless,
+ NDOF_SpaceMouseEnterprise,
// older devices
NDOF_SpacePilot,
diff --git a/intern/ghost/intern/GHOST_System.cpp b/intern/ghost/intern/GHOST_System.cpp
index 639ce451d23..c53580818e6 100644
--- a/intern/ghost/intern/GHOST_System.cpp
+++ b/intern/ghost/intern/GHOST_System.cpp
@@ -140,7 +140,7 @@ bool GHOST_System::validWindow(GHOST_IWindow *window)
GHOST_TSuccess GHOST_System::beginFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow **window,
- const bool stereoVisual, const GHOST_TUns16 numOfAASamples)
+ const bool stereoVisual, const bool alphaBackground, const GHOST_TUns16 numOfAASamples)
{
GHOST_TSuccess success = GHOST_kFailure;
GHOST_ASSERT(m_windowManager, "GHOST_System::beginFullScreen(): invalid window manager");
@@ -152,7 +152,7 @@ GHOST_TSuccess GHOST_System::beginFullScreen(const GHOST_DisplaySetting& setting
success = m_displayManager->setCurrentDisplaySetting(GHOST_DisplayManager::kMainDisplay, setting);
if (success == GHOST_kSuccess) {
//GHOST_PRINT("GHOST_System::beginFullScreen(): creating full-screen window\n");
- success = createFullScreenWindow((GHOST_Window **)window, setting, stereoVisual, numOfAASamples);
+ success = createFullScreenWindow((GHOST_Window **)window, setting, stereoVisual, alphaBackground, numOfAASamples);
if (success == GHOST_kSuccess) {
m_windowManager->beginFullScreen(*window, stereoVisual);
}
@@ -349,12 +349,14 @@ GHOST_TSuccess GHOST_System::exit()
}
GHOST_TSuccess GHOST_System::createFullScreenWindow(GHOST_Window **window, const GHOST_DisplaySetting &settings,
- const bool stereoVisual, const GHOST_TUns16 numOfAASamples)
+ const bool stereoVisual, const bool alphaBackground, const GHOST_TUns16 numOfAASamples)
{
GHOST_GLSettings glSettings = {0};
if (stereoVisual)
glSettings.flags |= GHOST_glStereoVisual;
+ if (alphaBackground)
+ glSettings.flags |= GHOST_glAlphaBackground;
glSettings.numOfAASamples = numOfAASamples;
/* note: don't use getCurrentDisplaySetting() because on X11 we may
diff --git a/intern/ghost/intern/GHOST_System.h b/intern/ghost/intern/GHOST_System.h
index c4951adb4fd..a10259bc9e9 100644
--- a/intern/ghost/intern/GHOST_System.h
+++ b/intern/ghost/intern/GHOST_System.h
@@ -144,8 +144,8 @@ public:
* \return Indication of success.
*/
GHOST_TSuccess beginFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow **window,
- const bool stereoVisual, const GHOST_TUns16 numOfAASamples = 0);
-
+ const bool stereoVisual, const bool alphaBackground, const GHOST_TUns16 numOfAASamples = 0);
+
/**
* Updates the resolution while in fullscreen mode.
* \param setting The new setting of the display.
@@ -336,7 +336,7 @@ protected:
* \return Indication of success.
*/
GHOST_TSuccess createFullScreenWindow(GHOST_Window **window, const GHOST_DisplaySetting &settings,
- const bool stereoVisual, const GHOST_TUns16 numOfAASamples = 0);
+ const bool stereoVisual, const bool alphaBackground = 0, const GHOST_TUns16 numOfAASamples = 0);
/** The display manager (platform dependent). */
GHOST_DisplayManager *m_displayManager;
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm
index c9855cfdf7e..bce390732fe 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.mm
+++ b/intern/ghost/intern/GHOST_SystemCocoa.mm
@@ -830,7 +830,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleWindowEvent(GHOST_TEventType eventType,
window->updateDrawingContext();
pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window) );
//Mouse up event is trapped by the resizing event loop, so send it anyway to the window manager
- pushEvent(new GHOST_EventButton(getMilliSeconds(), GHOST_kEventButtonUp, window, convertButton(0)));
+ pushEvent(new GHOST_EventButton(getMilliSeconds(), GHOST_kEventButtonUp, window, GHOST_kButtonMaskLeft));
//m_ignoreWindowSizedMessages = true;
}
break;
@@ -1278,19 +1278,29 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
switch ([event type]) {
case NSLeftMouseDown:
+ pushEvent(new GHOST_EventButton([event timestamp] * 1000, GHOST_kEventButtonDown, window, GHOST_kButtonMaskLeft));
+ handleTabletEvent(event); //Handle tablet events combined with mouse events
+ break;
case NSRightMouseDown:
+ pushEvent(new GHOST_EventButton([event timestamp] * 1000, GHOST_kEventButtonDown, window, GHOST_kButtonMaskRight));
+ handleTabletEvent(event); //Handle tablet events combined with mouse events
+ break;
case NSOtherMouseDown:
pushEvent(new GHOST_EventButton([event timestamp] * 1000, GHOST_kEventButtonDown, window, convertButton([event buttonNumber])));
- //Handle tablet events combined with mouse events
- handleTabletEvent(event);
+ handleTabletEvent(event); //Handle tablet events combined with mouse events
break;
case NSLeftMouseUp:
+ pushEvent(new GHOST_EventButton([event timestamp] * 1000, GHOST_kEventButtonUp, window, GHOST_kButtonMaskLeft));
+ handleTabletEvent(event); //Handle tablet events combined with mouse events
+ break;
case NSRightMouseUp:
+ pushEvent(new GHOST_EventButton([event timestamp] * 1000, GHOST_kEventButtonUp, window, GHOST_kButtonMaskRight));
+ handleTabletEvent(event); //Handle tablet events combined with mouse events
+ break;
case NSOtherMouseUp:
pushEvent(new GHOST_EventButton([event timestamp] * 1000, GHOST_kEventButtonUp, window, convertButton([event buttonNumber])));
- //Handle tablet events combined with mouse events
- handleTabletEvent(event);
+ handleTabletEvent(event); //Handle tablet events combined with mouse events
break;
case NSLeftMouseDragged:
diff --git a/intern/ghost/intern/GHOST_SystemPathsWin32.cpp b/intern/ghost/intern/GHOST_SystemPathsWin32.cpp
index 2bd380050f1..7d0ce5158fe 100644
--- a/intern/ghost/intern/GHOST_SystemPathsWin32.cpp
+++ b/intern/ghost/intern/GHOST_SystemPathsWin32.cpp
@@ -76,8 +76,7 @@ const GHOST_TUns8 *GHOST_SystemPathsWin32::getSystemDir(int, const char *version
HRESULT hResult = SHGetFolderPathW(NULL, CSIDL_COMMON_APPDATA, NULL, SHGFP_TYPE_CURRENT, knownpath_16);
- if (hResult == S_OK)
- {
+ if (hResult == S_OK) {
conv_utf_16_to_8(knownpath_16, knownpath, MAX_PATH * 3);
strcat(knownpath, "\\Blender Foundation\\Blender\\");
strcat(knownpath, versionstr);
@@ -94,8 +93,7 @@ const GHOST_TUns8 *GHOST_SystemPathsWin32::getUserDir(int, const char *versionst
HRESULT hResult = SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, knownpath_16);
- if (hResult == S_OK)
- {
+ if (hResult == S_OK) {
conv_utf_16_to_8(knownpath_16, knownpath, MAX_PATH * 3);
strcat(knownpath, "\\Blender Foundation\\Blender\\");
strcat(knownpath, versionstr);
diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp
index 43fb5dc4205..1ce8002520f 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.cpp
+++ b/intern/ghost/intern/GHOST_SystemWin32.cpp
@@ -241,6 +241,7 @@ GHOST_IWindow *GHOST_SystemWin32::createWindow(
state,
type,
((glSettings.flags & GHOST_glStereoVisual) != 0),
+ ((glSettings.flags & GHOST_glAlphaBackground) != 0),
glSettings.numOfAASamples,
parentWindow,
((glSettings.flags & GHOST_glDebugContext) != 0));
@@ -408,7 +409,11 @@ GHOST_TSuccess GHOST_SystemWin32::init()
::LoadIcon(NULL, IDI_APPLICATION);
}
wc.hCursor = ::LoadCursor(0, IDC_ARROW);
- wc.hbrBackground = 0;
+ wc.hbrBackground =
+#ifdef INW32_COMPISITING
+ (HBRUSH)CreateSolidBrush
+#endif
+ (0x00000000);
wc.lpszMenuName = 0;
wc.lpszClassName = L"GHOST_WindowClass";
@@ -1540,8 +1545,7 @@ static bool isStartedFromCommandPrompt()
int GHOST_SystemWin32::toggleConsole(int action)
{
- switch (action)
- {
+ switch (action) {
case 3: // startup: hide if not started from command prompt
{
if (isStartedFromCommandPrompt()) {
diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp
index c9946c13122..727bc9a01fb 100644
--- a/intern/ghost/intern/GHOST_SystemX11.cpp
+++ b/intern/ghost/intern/GHOST_SystemX11.cpp
@@ -61,6 +61,11 @@
#include <X11/XF86keysym.h>
#endif
+/* for XIWarpPointer */
+#ifdef WITH_X11_XINPUT
+# include <X11/extensions/XInput2.h>
+#endif
+
/* For timing */
#include <sys/time.h>
#include <unistd.h>
@@ -73,6 +78,10 @@
/* for debugging - so we can breakpoint X11 errors */
// #define USE_X11_ERROR_HANDLERS
+#ifdef WITH_X11_XINPUT
+# define USE_XINPUT_HOTPLUG
+#endif
+
/* see [#34039] Fix Alt key glitch on Unity desktop */
#define USE_UNITY_WORKAROUND
@@ -169,11 +178,36 @@ GHOST_SystemX11(
}
#ifdef WITH_X11_XINPUT
+ /* detect if we have xinput (for reuse) */
+ {
+ memset(&m_xinput_version, 0, sizeof(m_xinput_version));
+ XExtensionVersion *version = XGetExtensionVersion(m_display, INAME);
+ if (version && (version != (XExtensionVersion *)NoSuchExtension)) {
+ if (version->present) {
+ m_xinput_version = *version;
+ }
+ XFree(version);
+ }
+ }
+
+#ifdef USE_XINPUT_HOTPLUG
+ if (m_xinput_version.present) {
+ XEventClass class_presence;
+ int xi_presence;
+ DevicePresence(m_display, xi_presence, class_presence);
+ XSelectExtensionEvent(
+ m_display,
+ RootWindow(m_display, DefaultScreen(m_display)),
+ &class_presence, 1);
+ (void)xi_presence;
+ }
+#endif /* USE_XINPUT_HOTPLUG */
+
/* initialize incase X11 fails to load */
memset(&m_xtablet, 0, sizeof(m_xtablet));
- initXInputDevices();
-#endif
+ refreshXInputDevices();
+#endif /* WITH_X11_XINPUT */
}
GHOST_SystemX11::
@@ -310,6 +344,7 @@ createWindow(const STR_String& title,
left, top, width, height,
state, parentWindow, type,
((glSettings.flags & GHOST_glStereoVisual) != 0), exclusive,
+ ((glSettings.flags & GHOST_glAlphaBackground) != 0),
glSettings.numOfAASamples, (glSettings.flags & GHOST_glDebugContext) != 0);
if (window) {
@@ -419,8 +454,7 @@ static Bool init_timestamp_scanner(Display *, XEvent *event, XPointer arg)
{
init_timestamp_data *data =
reinterpret_cast<init_timestamp_data *>(arg);
- switch (event->type)
- {
+ switch (event->type) {
case ButtonPress:
case ButtonRelease:
data->timestamp = event->xbutton.time;
@@ -627,8 +661,13 @@ static bool checkTabletProximity(Display *display, XDevice *device)
return false;
}
+ /* needed since unplugging will abort() without this */
+ GHOST_X11_ERROR_HANDLERS_OVERRIDE(handler_store);
+
state = XQueryDeviceState(display, device);
+ GHOST_X11_ERROR_HANDLERS_RESTORE(handler_store);
+
if (state) {
XInputClass *cls = state->data;
// printf("%d class%s :\n", state->num_classes,
@@ -661,6 +700,41 @@ GHOST_SystemX11::processEvent(XEvent *xe)
GHOST_WindowX11 *window = findGhostWindow(xe->xany.window);
GHOST_Event *g_event = NULL;
+#ifdef USE_XINPUT_HOTPLUG
+ /* Hot-Plug support */
+ if (m_xinput_version.present) {
+ XEventClass class_presence;
+ int xi_presence;
+
+ DevicePresence(m_display, xi_presence, class_presence);
+ (void)class_presence;
+
+ if (xe->type == xi_presence) {
+ XDevicePresenceNotifyEvent *notify_event = (XDevicePresenceNotifyEvent *)xe;
+ if ((notify_event->devchange == DeviceEnabled) ||
+ (notify_event->devchange == DeviceDisabled) ||
+ (notify_event->devchange == DeviceAdded) ||
+ (notify_event->devchange == DeviceRemoved))
+ {
+ refreshXInputDevices();
+
+ /* update all window events */
+ {
+ vector<GHOST_IWindow *> & win_vec = m_windowManager->getWindows();
+ vector<GHOST_IWindow *>::iterator win_it = win_vec.begin();
+ vector<GHOST_IWindow *>::const_iterator win_end = win_vec.end();
+
+ for (; win_it != win_end; ++win_it) {
+ GHOST_WindowX11 *window = static_cast<GHOST_WindowX11 *>(*win_it);
+ window->refreshXInputDevices();
+ }
+ }
+ }
+ }
+ }
+#endif /* USE_XINPUT_HOTPLUG */
+
+
if (!window) {
return;
}
@@ -680,7 +754,6 @@ GHOST_SystemX11::processEvent(XEvent *xe)
}
}
#endif /* WITH_X11_XINPUT */
-
switch (xe->type) {
case Expose:
{
@@ -1401,7 +1474,22 @@ setCursorPosition(
int relx = x - cx;
int rely = y - cy;
- XWarpPointer(m_display, None, None, 0, 0, 0, 0, relx, rely);
+#ifdef WITH_X11_XINPUT
+ if ((m_xinput_version.present) &&
+ (m_xinput_version.major_version >= 2))
+ {
+ /* Needed to account for XInput "Coordinate Transformation Matrix", see T48901 */
+ int device_id;
+ if (XIGetClientPointer(m_display, None, &device_id) != False) {
+ XIWarpPointer(m_display, device_id, None, None, 0, 0, 0, 0, relx, rely);
+ }
+ }
+ else
+#endif
+ {
+ XWarpPointer(m_display, None, None, 0, 0, 0, 0, relx, rely);
+ }
+
XSync(m_display, 0); /* Sync to process all requests */
return GHOST_kSuccess;
@@ -1917,11 +2005,8 @@ GHOST_TSuccess GHOST_SystemX11::pushDragDropEvent(GHOST_TEventType eventType,
);
}
#endif
-
-#if defined(USE_X11_ERROR_HANDLERS) || defined(WITH_X11_XINPUT)
-/*
+/**
* These callbacks can be used for debugging, so we can breakpoint on an X11 error.
-
*
* Dummy function to get around IO Handler exiting if device invalid
* Basically it will not crash blender now if you have a X device that
@@ -1952,7 +2037,6 @@ int GHOST_X11_ApplicationIOErrorHandler(Display * /*display*/)
/* No exit! - but keep lint happy */
return 0;
}
-#endif
#ifdef WITH_X11_XINPUT
/* These C functions are copied from Wine 1.1.13's wintab.c */
@@ -1963,8 +2047,7 @@ int GHOST_X11_ApplicationIOErrorHandler(Display * /*display*/)
static bool match_token(const char *haystack, const char *needle)
{
const char *p, *q;
- for (p = haystack; *p; )
- {
+ for (p = haystack; *p; ) {
while (*p && isspace(*p))
p++;
if (!*p)
@@ -2050,23 +2133,27 @@ static BOOL is_eraser(const char *name, const char *type)
#undef FALSE
/* end code copied from wine */
-void GHOST_SystemX11::initXInputDevices()
+void GHOST_SystemX11::refreshXInputDevices()
{
- static XErrorHandler old_handler = (XErrorHandler) 0;
- static XIOErrorHandler old_handler_io = (XIOErrorHandler) 0;
+ if (m_xinput_version.present) {
- XExtensionVersion *version = XGetExtensionVersion(m_display, INAME);
+ if (m_xtablet.StylusDevice) {
+ XCloseDevice(m_display, m_xtablet.StylusDevice);
+ m_xtablet.StylusDevice = NULL;
+ }
+
+ if (m_xtablet.EraserDevice) {
+ XCloseDevice(m_display, m_xtablet.EraserDevice);
+ m_xtablet.EraserDevice = NULL;
+ }
- if (version && (version != (XExtensionVersion *)NoSuchExtension)) {
- if (version->present) {
+ /* Install our error handler to override Xlib's termination behavior */
+ GHOST_X11_ERROR_HANDLERS_OVERRIDE(handler_store);
+
+ {
int device_count;
XDeviceInfo *device_info = XListInputDevices(m_display, &device_count);
- m_xtablet.StylusDevice = NULL;
- m_xtablet.EraserDevice = NULL;
- /* Install our error handler to override Xlib's termination behavior */
- old_handler = XSetErrorHandler(GHOST_X11_ApplicationErrorHandler);
- old_handler_io = XSetIOErrorHandler(GHOST_X11_ApplicationIOErrorHandler);
for (int i = 0; i < device_count; ++i) {
char *device_type = device_info[i].type ? XGetAtomName(m_display, device_info[i].type) : NULL;
@@ -2125,13 +2212,10 @@ void GHOST_SystemX11::initXInputDevices()
}
}
- /* Restore handler */
- (void) XSetErrorHandler(old_handler);
- (void) XSetIOErrorHandler(old_handler_io);
-
XFreeDeviceList(device_info);
}
- XFree(version);
+
+ GHOST_X11_ERROR_HANDLERS_RESTORE(handler_store);
}
}
diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h
index a0088dbe8f0..e60cab6a194 100644
--- a/intern/ghost/intern/GHOST_SystemX11.h
+++ b/intern/ghost/intern/GHOST_SystemX11.h
@@ -52,6 +52,20 @@
int GHOST_X11_ApplicationErrorHandler(Display *display, XErrorEvent *theEvent);
int GHOST_X11_ApplicationIOErrorHandler(Display *display);
+#define GHOST_X11_ERROR_HANDLERS_OVERRIDE(var) \
+ struct { \
+ XErrorHandler handler; \
+ XIOErrorHandler handler_io; \
+ } var = { \
+ XSetErrorHandler(GHOST_X11_ApplicationErrorHandler), \
+ XSetIOErrorHandler(GHOST_X11_ApplicationIOErrorHandler), \
+ }
+
+#define GHOST_X11_ERROR_HANDLERS_RESTORE(var) \
+ { \
+ (void)XSetErrorHandler(var.handler); \
+ (void)XSetIOErrorHandler(var.handler_io); \
+ } ((void)0)
class GHOST_WindowX11;
@@ -328,6 +342,10 @@ public:
#endif
} m_atom;
+#ifdef WITH_X11_XINPUT
+ XExtensionVersion m_xinput_version;
+#endif
+
private:
Display *m_display;
@@ -367,7 +385,7 @@ private:
#endif
#ifdef WITH_X11_XINPUT
- void initXInputDevices();
+ void refreshXInputDevices();
#endif
GHOST_WindowX11 *
diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp
index 81c08f4fc06..6a27d7aadf9 100644
--- a/intern/ghost/intern/GHOST_WindowWin32.cpp
+++ b/intern/ghost/intern/GHOST_WindowWin32.cpp
@@ -43,7 +43,9 @@
#else
# include "GHOST_ContextWGL.h"
#endif
-
+#ifdef WIN32_COMPOSITING
+#include <Dwmapi.h>
+#endif
#include <math.h>
#include <string.h>
@@ -70,7 +72,8 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
GHOST_TUns32 height,
GHOST_TWindowState state,
GHOST_TDrawingContextType type,
- bool wantStereoVisual,
+ bool wantStereoVisual,
+ bool alphaBackground,
GHOST_TUns16 wantNumOfAASamples,
GHOST_TEmbedderWindowID parentwindowhwnd,
bool is_debug)
@@ -83,6 +86,7 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
m_hasGrabMouse(false),
m_nPressedButtons(0),
m_customCursor(0),
+ m_wantAlphaBackground(alphaBackground),
m_wintab(NULL),
m_tabletData(NULL),
m_tablet(0),
@@ -91,31 +95,6 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
m_parentWindowHwnd(parentwindowhwnd),
m_debug_context(is_debug)
{
- OSVERSIONINFOEX versionInfo;
- bool hasMinVersionForTaskbar = false;
-
- ZeroMemory(&versionInfo, sizeof(OSVERSIONINFOEX));
-
- versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
-
- if (!GetVersionEx((OSVERSIONINFO *)&versionInfo)) {
- versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
- if (GetVersionEx((OSVERSIONINFO *)&versionInfo)) {
- if ((versionInfo.dwMajorVersion == 6 && versionInfo.dwMinorVersion >= 1) ||
- (versionInfo.dwMajorVersion >= 7))
- {
- hasMinVersionForTaskbar = true;
- }
- }
- }
- else {
- if ((versionInfo.dwMajorVersion == 6 && versionInfo.dwMinorVersion >= 1) ||
- (versionInfo.dwMajorVersion >= 7))
- {
- hasMinVersionForTaskbar = true;
- }
- }
-
if (state != GHOST_kWindowStateFullScreen) {
RECT rect;
MONITORINFO monitor;
@@ -181,17 +160,17 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
wchar_t *title_16 = alloc_utf16_from_8((char *)(const char *)title, 0);
m_hWnd = ::CreateWindowW(
- s_windowClassName, // pointer to registered class name
- title_16, // pointer to window name
- wintype, // window style
- left, // horizontal position of window
- top, // vertical position of window
- width, // window width
- height, // window height
- (HWND) m_parentWindowHwnd, // handle to parent or owner window
- 0, // handle to menu or child-window identifier
- ::GetModuleHandle(0), // handle to application instance
- 0); // pointer to window-creation data
+ s_windowClassName, // pointer to registered class name
+ title_16, // pointer to window name
+ wintype, // window style
+ left, // horizontal position of window
+ top, // vertical position of window
+ width, // window width
+ height, // window height
+ (HWND)m_parentWindowHwnd, // handle to parent or owner window
+ 0, // handle to menu or child-window identifier
+ ::GetModuleHandle(0), // handle to application instance
+ 0); // pointer to window-creation data
free(title_16);
}
else {
@@ -243,6 +222,24 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
}
::ShowWindow(m_hWnd, nCmdShow);
+#ifdef WIN32_COMPOSITING
+ if (alphaBackground && parentwindowhwnd == 0) {
+
+ HRESULT hr = S_OK;
+
+ // Create and populate the Blur Behind structure
+ DWM_BLURBEHIND bb = { 0 };
+
+ // Enable Blur Behind and apply to the entire client area
+ bb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
+ bb.fEnable = true;
+ bb.hRgnBlur = CreateRectRgn(0, 0, -1, -1);
+
+ // Apply Blur Behind
+ hr = DwmEnableBlurBehindWindow(m_hWnd, &bb);
+ DeleteObject(bb.hRgnBlur);
+ }
+#endif
// Force an initial paint of the window
::UpdateWindow(m_hWnd);
}
@@ -319,11 +316,7 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
}
}
}
-
- if (hasMinVersionForTaskbar)
- CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_ITaskbarList, (LPVOID *)&m_Bar);
- else
- m_Bar = NULL;
+ CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_ITaskbarList3, (LPVOID *)&m_Bar);
}
@@ -622,6 +615,7 @@ GHOST_Context *GHOST_WindowWin32::newDrawingContext(GHOST_TDrawingContextType ty
#if defined(WITH_GL_PROFILE_CORE)
GHOST_Context *context = new GHOST_ContextWGL(
m_wantStereoVisual,
+ m_wantAlphaBackground,
m_wantNumOfAASamples,
m_hWnd,
m_hDC,
@@ -632,6 +626,7 @@ GHOST_Context *GHOST_WindowWin32::newDrawingContext(GHOST_TDrawingContextType ty
#elif defined(WITH_GL_PROFILE_ES20)
GHOST_Context *context = new GHOST_ContextWGL(
m_wantStereoVisual,
+ m_wantAlphaBackground,
m_wantNumOfAASamples,
m_hWnd,
m_hDC,
@@ -642,6 +637,7 @@ GHOST_Context *GHOST_WindowWin32::newDrawingContext(GHOST_TDrawingContextType ty
#elif defined(WITH_GL_PROFILE_COMPAT)
GHOST_Context *context = new GHOST_ContextWGL(
m_wantStereoVisual,
+ m_wantAlphaBackground,
m_wantNumOfAASamples,
m_hWnd,
m_hDC,
diff --git a/intern/ghost/intern/GHOST_WindowWin32.h b/intern/ghost/intern/GHOST_WindowWin32.h
index b508c2f37df..a1cf58c9ceb 100644
--- a/intern/ghost/intern/GHOST_WindowWin32.h
+++ b/intern/ghost/intern/GHOST_WindowWin32.h
@@ -89,6 +89,7 @@ public:
GHOST_TWindowState state,
GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone,
bool wantStereoVisual = false,
+ bool alphaBackground = false,
GHOST_TUns16 wantNumOfAASamples = 0,
GHOST_TEmbedderWindowID parentWindowHwnd = 0,
bool is_debug = false);
@@ -328,6 +329,8 @@ private:
int m_nPressedButtons;
/** HCURSOR structure of the custom cursor */
HCURSOR m_customCursor;
+ /** request GL context aith alpha channel */
+ bool m_wantAlphaBackground;
/** ITaskbarList3 structure for progress bar*/
ITaskbarList3 *m_Bar;
diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp
index e68e0901dab..ec2b65e67d0 100644
--- a/intern/ghost/intern/GHOST_WindowX11.cpp
+++ b/intern/ghost/intern/GHOST_WindowX11.cpp
@@ -33,7 +33,9 @@
#include <X11/cursorfont.h>
#include <X11/Xatom.h>
#include <X11/Xutil.h>
-
+#ifdef WITH_X11_ALPHA
+#include <X11/extensions/Xrender.h>
+#endif
#include "GHOST_WindowX11.h"
#include "GHOST_SystemX11.h"
#include "STR_String.h"
@@ -49,6 +51,11 @@
# include "GHOST_ContextGLX.h"
#endif
+/* for XIWarpPointer */
+#ifdef WITH_X11_XINPUT
+# include <X11/extensions/XInput2.h>
+#endif
+
#if defined(__sun__) || defined(__sun) || defined(__sparc) || defined(__sparc__) || defined(_AIX)
# include <strings.h>
#endif
@@ -164,15 +171,21 @@ static const unsigned long BLENDER_ICON_48x48x32[] = {
static XVisualInfo *x11_visualinfo_from_glx(
Display *display,
- bool stereoVisual, GHOST_TUns16 *r_numOfAASamples)
+ bool stereoVisual,
+ GHOST_TUns16 *r_numOfAASamples,
+ bool needAlpha,
+ GLXFBConfig *fbconfig)
{
- XVisualInfo *visualInfo = NULL;
+ XVisualInfo *visual = NULL;
GHOST_TUns16 numOfAASamples = *r_numOfAASamples;
+ int glx_major, glx_minor, glx_version; /* GLX version: major.minor */
GHOST_TUns16 actualSamples;
+ int glx_attribs[64];
+
+ *fbconfig = NULL;
/* Set up the minimum attributes that we require and see if
* X can find us a visual matching those requirements. */
- int glx_major, glx_minor; /* GLX version: major.minor */
if (!glXQueryVersion(display, &glx_major, &glx_minor)) {
fprintf(stderr,
@@ -182,53 +195,118 @@ static XVisualInfo *x11_visualinfo_from_glx(
return NULL;
}
+ glx_version = glx_major*100 + glx_minor;
- /* GLX >= 1.4 required for multi-sample */
- if ((glx_major > 1) || (glx_major == 1 && glx_minor >= 4)) {
+ if (glx_version >= 104) {
actualSamples = numOfAASamples;
}
else {
numOfAASamples = 0;
actualSamples = 0;
}
+
+#ifdef WITH_X11_ALPHA
+ if ( needAlpha
+ && glx_version >= 103
+ && (glXChooseFBConfig ||
+ (glXChooseFBConfig = (PFNGLXCHOOSEFBCONFIGPROC)glXGetProcAddressARB((const GLubyte *)"glXChooseFBConfig")) != NULL)
+ && (glXGetVisualFromFBConfig ||
+ (glXGetVisualFromFBConfig = (PFNGLXGETVISUALFROMFBCONFIGPROC)glXGetProcAddressARB((const GLubyte *)"glXGetVisualFromFBConfig")) != NULL)
+ ) {
+ GLXFBConfig *fbconfigs;
+ int nbfbconfig;
+ int i;
+
+ for (;;) {
+
+ GHOST_X11_GL_GetAttributes(glx_attribs, 64, actualSamples, stereoVisual, needAlpha, true);
+
+ fbconfigs = glXChooseFBConfig(display, DefaultScreen(display), glx_attribs, &nbfbconfig);
+
+ /* Any sample level or even zero, which means oversampling disabled, is good
+ * but we need a valid visual to continue */
+ if (nbfbconfig > 0) {
+ /* take a frame buffer config that has alpha cap */
+ for (i=0 ;i<nbfbconfig; i++) {
+ visual = (XVisualInfo*)glXGetVisualFromFBConfig(display, fbconfigs[i]);
+ if (!visual)
+ continue;
+ /* if we don't need a alpha background, the first config will do, otherwise
+ * test the alphaMask as it won't necessarily be present */
+ if (needAlpha) {
+ XRenderPictFormat *pict_format = XRenderFindVisualFormat(display, visual->visual);
+ if (!pict_format)
+ continue;
+ if (pict_format->direct.alphaMask <= 0)
+ continue;
+ }
+ *fbconfig = fbconfigs[i];
+ break;
+ }
+ XFree(fbconfigs);
+ if (i<nbfbconfig) {
+ if (actualSamples < numOfAASamples) {
+ fprintf(stderr,
+ "Warning! Unable to find a multisample pixel format that supports exactly %d samples. "
+ "Substituting one that uses %d samples.\n",
+ numOfAASamples, actualSamples);
+ }
+ break;
+ }
+ visual = NULL;
+ }
- /* Find the display with highest samples, starting at level requested */
- for (;;) {
- int glx_attribs[64];
-
- GHOST_X11_GL_GetAttributes(glx_attribs, 64, actualSamples, stereoVisual, false);
-
- visualInfo = glXChooseVisual(display, DefaultScreen(display), glx_attribs);
-
- /* Any sample level or even zero, which means oversampling disabled, is good
- * but we need a valid visual to continue */
- if (visualInfo != NULL) {
- if (actualSamples < numOfAASamples) {
+ if (actualSamples == 0) {
+ /* All options exhausted, cannot continue */
fprintf(stderr,
- "Warning! Unable to find a multisample pixel format that supports exactly %d samples. "
- "Substituting one that uses %d samples.\n",
- numOfAASamples, actualSamples);
+ "%s:%d: X11 glXChooseVisual() failed, "
+ "verify working openGL system!\n",
+ __FILE__, __LINE__);
+
+ return NULL;
+ }
+ else {
+ --actualSamples;
}
- break;
}
+ }
+ else
+#endif
+ {
+ /* legacy, don't use extension */
+ for (;;) {
+ GHOST_X11_GL_GetAttributes(glx_attribs, 64, actualSamples, stereoVisual, needAlpha, false);
+
+ visual = glXChooseVisual(display, DefaultScreen(display), glx_attribs);
+
+ /* Any sample level or even zero, which means oversampling disabled, is good
+ * but we need a valid visual to continue */
+ if (visual != NULL) {
+ if (actualSamples < numOfAASamples) {
+ fprintf(stderr,
+ "Warning! Unable to find a multisample pixel format that supports exactly %d samples. "
+ "Substituting one that uses %d samples.\n",
+ numOfAASamples, actualSamples);
+ }
+ break;
+ }
- if (actualSamples == 0) {
- /* All options exhausted, cannot continue */
- fprintf(stderr,
- "%s:%d: X11 glXChooseVisual() failed, "
- "verify working openGL system!\n",
- __FILE__, __LINE__);
+ if (actualSamples == 0) {
+ /* All options exhausted, cannot continue */
+ fprintf(stderr,
+ "%s:%d: X11 glXChooseVisual() failed, "
+ "verify working openGL system!\n",
+ __FILE__, __LINE__);
- return NULL;
- }
- else {
- --actualSamples;
+ return NULL;
+ }
+ else {
+ --actualSamples;
+ }
}
}
-
*r_numOfAASamples = actualSamples;
-
- return visualInfo;
+ return visual;
}
GHOST_WindowX11::
@@ -244,10 +322,12 @@ GHOST_WindowX11(GHOST_SystemX11 *system,
GHOST_TDrawingContextType type,
const bool stereoVisual,
const bool exclusive,
+ const bool alphaBackground,
const GHOST_TUns16 numOfAASamples, const bool is_debug)
: GHOST_Window(width, height, state, stereoVisual, exclusive, numOfAASamples),
m_display(display),
m_visualInfo(NULL),
+ m_fbconfig(NULL),
m_normal_state(GHOST_kWindowStateNormal),
m_system(system),
m_invalid_window(false),
@@ -264,7 +344,7 @@ GHOST_WindowX11(GHOST_SystemX11 *system,
m_is_debug_context(is_debug)
{
if (type == GHOST_kDrawingContextTypeOpenGL) {
- m_visualInfo = x11_visualinfo_from_glx(m_display, stereoVisual, &m_wantNumOfAASamples);
+ m_visualInfo = x11_visualinfo_from_glx(m_display, stereoVisual, &m_wantNumOfAASamples, alphaBackground, (GLXFBConfig*)&m_fbconfig);
}
else {
XVisualInfo tmp = {0};
@@ -491,7 +571,7 @@ GHOST_WindowX11(GHOST_SystemX11 *system,
}
#ifdef WITH_X11_XINPUT
- initXInputDevices();
+ refreshXInputDevices();
m_tabletData.Active = GHOST_kTabletModeNone;
#endif
@@ -558,45 +638,40 @@ bool GHOST_WindowX11::createX11_XIC()
#endif
#ifdef WITH_X11_XINPUT
-void GHOST_WindowX11::initXInputDevices()
+void GHOST_WindowX11::refreshXInputDevices()
{
- XExtensionVersion *version = XGetExtensionVersion(m_display, INAME);
-
- if (version && (version != (XExtensionVersion *)NoSuchExtension)) {
- if (version->present) {
- GHOST_SystemX11::GHOST_TabletX11 &xtablet = m_system->GetXTablet();
- XEventClass xevents[8], ev;
- int dcount = 0;
-
- /* With modern XInput (xlib 1.6.2 at least and/or evdev 2.9.0) and some 'no-name' tablets
- * like 'UC-LOGIC Tablet WP5540U', we also need to 'select' ButtonPress for motion event,
- * otherwise we do not get any tablet motion event once pen is pressed... See T43367.
- */
-
- if (xtablet.StylusDevice) {
- DeviceMotionNotify(xtablet.StylusDevice, xtablet.MotionEvent, ev);
- if (ev) xevents[dcount++] = ev;
- DeviceButtonPress(xtablet.StylusDevice, xtablet.PressEvent, ev);
- if (ev) xevents[dcount++] = ev;
- ProximityIn(xtablet.StylusDevice, xtablet.ProxInEvent, ev);
- if (ev) xevents[dcount++] = ev;
- ProximityOut(xtablet.StylusDevice, xtablet.ProxOutEvent, ev);
- if (ev) xevents[dcount++] = ev;
- }
- if (xtablet.EraserDevice) {
- DeviceMotionNotify(xtablet.EraserDevice, xtablet.MotionEventEraser, ev);
- if (ev) xevents[dcount++] = ev;
- DeviceButtonPress(xtablet.EraserDevice, xtablet.PressEventEraser, ev);
- if (ev) xevents[dcount++] = ev;
- ProximityIn(xtablet.EraserDevice, xtablet.ProxInEventEraser, ev);
- if (ev) xevents[dcount++] = ev;
- ProximityOut(xtablet.EraserDevice, xtablet.ProxOutEventEraser, ev);
- if (ev) xevents[dcount++] = ev;
- }
+ if (m_system->m_xinput_version.present) {
+ GHOST_SystemX11::GHOST_TabletX11 &xtablet = m_system->GetXTablet();
+ XEventClass xevents[8], ev;
+ int dcount = 0;
+
+ /* With modern XInput (xlib 1.6.2 at least and/or evdev 2.9.0) and some 'no-name' tablets
+ * like 'UC-LOGIC Tablet WP5540U', we also need to 'select' ButtonPress for motion event,
+ * otherwise we do not get any tablet motion event once pen is pressed... See T43367.
+ */
- XSelectExtensionEvent(m_display, m_window, xevents, dcount);
+ if (xtablet.StylusDevice) {
+ DeviceMotionNotify(xtablet.StylusDevice, xtablet.MotionEvent, ev);
+ if (ev) xevents[dcount++] = ev;
+ DeviceButtonPress(xtablet.StylusDevice, xtablet.PressEvent, ev);
+ if (ev) xevents[dcount++] = ev;
+ ProximityIn(xtablet.StylusDevice, xtablet.ProxInEvent, ev);
+ if (ev) xevents[dcount++] = ev;
+ ProximityOut(xtablet.StylusDevice, xtablet.ProxOutEvent, ev);
+ if (ev) xevents[dcount++] = ev;
+ }
+ if (xtablet.EraserDevice) {
+ DeviceMotionNotify(xtablet.EraserDevice, xtablet.MotionEventEraser, ev);
+ if (ev) xevents[dcount++] = ev;
+ DeviceButtonPress(xtablet.EraserDevice, xtablet.PressEventEraser, ev);
+ if (ev) xevents[dcount++] = ev;
+ ProximityIn(xtablet.EraserDevice, xtablet.ProxInEventEraser, ev);
+ if (ev) xevents[dcount++] = ev;
+ ProximityOut(xtablet.EraserDevice, xtablet.ProxOutEventEraser, ev);
+ if (ev) xevents[dcount++] = ev;
}
- XFree(version);
+
+ XSelectExtensionEvent(m_display, m_window, xevents, dcount);
}
}
@@ -1240,6 +1315,7 @@ GHOST_Context *GHOST_WindowX11::newDrawingContext(GHOST_TDrawingContextType type
m_window,
m_display,
m_visualInfo,
+ (GLXFBConfig)m_fbconfig,
GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
3, 2,
GHOST_OPENGL_GLX_CONTEXT_FLAGS | (m_is_debug_context ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
@@ -1251,6 +1327,7 @@ GHOST_Context *GHOST_WindowX11::newDrawingContext(GHOST_TDrawingContextType type
m_window,
m_display,
m_visualInfo,
+ (GLXFBConfig)m_fbconfig,
GLX_CONTEXT_ES2_PROFILE_BIT_EXT,
2, 0,
GHOST_OPENGL_GLX_CONTEXT_FLAGS | (m_is_debug_context ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
@@ -1262,6 +1339,7 @@ GHOST_Context *GHOST_WindowX11::newDrawingContext(GHOST_TDrawingContextType type
m_window,
m_display,
m_visualInfo,
+ (GLXFBConfig)m_fbconfig,
0, // profile bit
0, 0,
GHOST_OPENGL_GLX_CONTEXT_FLAGS | (m_is_debug_context ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
@@ -1447,7 +1525,21 @@ setWindowCursorGrab(
/* use to generate a mouse move event, otherwise the last event
* blender gets can be outside the screen causing menus not to show
* properly unless the user moves the mouse */
- XWarpPointer(m_display, None, None, 0, 0, 0, 0, 0, 0);
+
+#ifdef WITH_X11_XINPUT
+ if ((m_system->m_xinput_version.present) &&
+ (m_system->m_xinput_version.major_version >= 2))
+ {
+ int device_id;
+ if (XIGetClientPointer(m_display, None, &device_id) != False) {
+ XIWarpPointer(m_display, device_id, None, None, 0, 0, 0, 0, 0, 0);
+ }
+ }
+ else
+#endif
+ {
+ XWarpPointer(m_display, None, None, 0, 0, 0, 0, 0, 0);
+ }
}
/* Almost works without but important otherwise the mouse GHOST location can be incorrect on exit */
diff --git a/intern/ghost/intern/GHOST_WindowX11.h b/intern/ghost/intern/GHOST_WindowX11.h
index 5beb7b43032..9380aa9d631 100644
--- a/intern/ghost/intern/GHOST_WindowX11.h
+++ b/intern/ghost/intern/GHOST_WindowX11.h
@@ -73,6 +73,7 @@ public:
* \param parentWindow Parent (embedder) window
* \param type The type of drawing context installed in this window.
* \param stereoVisual Stereo visual for quad buffered stereo.
+ * \param alphaBackground Enable alpha blending of window with display background
* \param numOfAASamples Number of samples used for AA (zero if no AA)
*/
GHOST_WindowX11(
@@ -88,6 +89,7 @@ public:
GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone,
const bool stereoVisual = false,
const bool exclusive = false,
+ const bool alphaBackground = false,
const GHOST_TUns16 numOfAASamples = 0,
const bool is_debug = false
);
@@ -210,6 +212,10 @@ public:
bool createX11_XIC();
#endif
+#ifdef WITH_X11_XINPUT
+ void refreshXInputDevices();
+#endif
+
#ifdef WITH_XDND
GHOST_DropTargetX11 *getDropTarget()
{
@@ -313,14 +319,11 @@ private:
Cursor
getEmptyCursor(
);
-
-#ifdef WITH_X11_XINPUT
- void initXInputDevices();
-#endif
Window m_window;
Display *m_display;
XVisualInfo *m_visualInfo;
+ void *m_fbconfig;
GHOST_TWindowState m_normal_state;
diff --git a/intern/gpudirect/CMakeLists.txt b/intern/gpudirect/CMakeLists.txt
new file mode 100644
index 00000000000..88c09a663b8
--- /dev/null
+++ b/intern/gpudirect/CMakeLists.txt
@@ -0,0 +1,41 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2015, Blender Foundation
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): Blender Foundation.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+set(INC
+ .
+ # XXX, bad level include!
+ ../../source/blender/blenlib
+)
+
+set(INC_SYS
+ ${GLEW_INCLUDE_PATH}
+)
+
+set(SRC
+ dvpapi.cpp
+ dvpapi.h
+)
+
+blender_add_lib(bf_intern_gpudirect "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/intern/gpudirect/dvpapi.cpp b/intern/gpudirect/dvpapi.cpp
new file mode 100644
index 00000000000..56b58e0a348
--- /dev/null
+++ b/intern/gpudirect/dvpapi.cpp
@@ -0,0 +1,147 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2015, Blender Foundation
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Blender Foundation.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file gpudirect/dvpapi.c
+ * \ingroup gpudirect
+ */
+
+#ifdef WIN32
+
+#include <stdlib.h>
+#include "dvpapi.h"
+
+extern "C" {
+#include "BLI_dynlib.h"
+}
+
+#define KDVPAPI_Name "dvp.dll"
+
+typedef DVPStatus (DVPAPIENTRY * PFNDVPINITGLCONTEXT) (uint32_t flags);
+typedef DVPStatus (DVPAPIENTRY * PFNDVPCLOSEGLCONTEXT) (void);
+typedef DVPStatus (DVPAPIENTRY * PFNDVPGETLIBRARYVERSION)(uint32_t *major, uint32_t *minor);
+
+static uint32_t __dvpMajorVersion = 0;
+static uint32_t __dvpMinorVersion = 0;
+static PFNDVPGETLIBRARYVERSION __dvpGetLibrayVersion = NULL;
+static PFNDVPINITGLCONTEXT __dvpInitGLContext = NULL;
+static PFNDVPCLOSEGLCONTEXT __dvpCloseGLContext = NULL;
+PFNDVPBEGIN __dvpBegin = NULL;
+PFNDVPEND __dvpEnd = NULL;
+PFNDVPCREATEBUFFER __dvpCreateBuffer = NULL;
+PFNDVPDESTROYBUFFER __dvpDestroyBuffer = NULL;
+PFNDVPFREEBUFFER __dvpFreeBuffer = NULL;
+PFNDVPMEMCPYLINED __dvpMemcpyLined = NULL;
+PFNDVPMEMCPY __dvpMemcpy = NULL;
+PFNDVPIMPORTSYNCOBJECT __dvpImportSyncObject = NULL;
+PFNDVPFREESYNCOBJECT __dvpFreeSyncObject = NULL;
+PFNDVPMAPBUFFERENDAPI __dvpMapBufferEndAPI = NULL;
+PFNDVPMAPBUFFERWAITDVP __dvpMapBufferWaitDVP = NULL;
+PFNDVPMAPBUFFERENDDVP __dvpMapBufferEndDVP = NULL;
+PFNDVPMAPBUFFERWAITAPI __dvpMapBufferWaitAPI = NULL;
+PFNDVPBINDTOGLCTX __dvpBindToGLCtx = NULL;
+PFNDVPGETREQUIREDCONSTANTSGLCTX __dvpGetRequiredConstantsGLCtx = NULL;
+PFNDVPCREATEGPUTEXTUREGL __dvpCreateGPUTextureGL = NULL;
+PFNDVPUNBINDFROMGLCTX __dvpUnbindFromGLCtx = NULL;
+
+static DynamicLibrary *__dvpLibrary = NULL;
+
+DVPStatus dvpGetLibrayVersion(uint32_t *major, uint32_t *minor)
+{
+ if (!__dvpLibrary)
+ return DVP_STATUS_ERROR;
+ *major = __dvpMajorVersion;
+ *minor = __dvpMinorVersion;
+ return DVP_STATUS_OK;
+}
+
+DVPStatus dvpInitGLContext(uint32_t flags)
+{
+ DVPStatus status;
+ if (!__dvpLibrary) {
+ __dvpLibrary = BLI_dynlib_open(KDVPAPI_Name);
+ if (!__dvpLibrary) {
+ return DVP_STATUS_ERROR;
+ }
+// "?dvpInitGLContext@@YA?AW4DVPStatus@@I@Z";
+ __dvpInitGLContext = (PFNDVPINITGLCONTEXT)BLI_dynlib_find_symbol(__dvpLibrary, "?dvpInitGLContext@@YA?AW4DVPStatus@@I@Z");
+ __dvpCloseGLContext = (PFNDVPCLOSEGLCONTEXT)BLI_dynlib_find_symbol(__dvpLibrary, "?dvpCloseGLContext@@YA?AW4DVPStatus@@XZ");
+ __dvpGetLibrayVersion = (PFNDVPGETLIBRARYVERSION)BLI_dynlib_find_symbol(__dvpLibrary, "?dvpGetLibrayVersion@@YA?AW4DVPStatus@@PEAI0@Z");
+ __dvpBegin = (PFNDVPBEGIN)BLI_dynlib_find_symbol(__dvpLibrary, "?dvpBegin@@YA?AW4DVPStatus@@XZ");
+ __dvpEnd = (PFNDVPEND)BLI_dynlib_find_symbol(__dvpLibrary, "?dvpEnd@@YA?AW4DVPStatus@@XZ");
+ __dvpCreateBuffer = (PFNDVPCREATEBUFFER)BLI_dynlib_find_symbol(__dvpLibrary, "?dvpCreateBuffer@@YA?AW4DVPStatus@@PEAUDVPSysmemBufferDescRec@@PEA_K@Z");
+ __dvpDestroyBuffer = (PFNDVPDESTROYBUFFER)BLI_dynlib_find_symbol(__dvpLibrary, "?dvpDestroyBuffer@@YA?AW4DVPStatus@@_K@Z");
+ __dvpFreeBuffer = (PFNDVPFREEBUFFER)BLI_dynlib_find_symbol(__dvpLibrary, "?dvpFreeBuffer@@YA?AW4DVPStatus@@_K@Z");
+ __dvpMemcpyLined = (PFNDVPMEMCPYLINED)BLI_dynlib_find_symbol(__dvpLibrary, "?dvpMemcpyLined@@YA?AW4DVPStatus@@_K0I000III@Z");
+ __dvpMemcpy = (PFNDVPMEMCPY)BLI_dynlib_find_symbol(__dvpLibrary, "?dvpMemcpy2D@@YA?AW4DVPStatus@@_K0I000IIIII@Z");
+ __dvpImportSyncObject = (PFNDVPIMPORTSYNCOBJECT)BLI_dynlib_find_symbol(__dvpLibrary, "?dvpImportSyncObject@@YA?AW4DVPStatus@@PEAUDVPSyncObjectDescRec@@PEA_K@Z");
+ __dvpFreeSyncObject = (PFNDVPFREESYNCOBJECT)BLI_dynlib_find_symbol(__dvpLibrary, "?dvpFreeSyncObject@@YA?AW4DVPStatus@@_K@Z");
+ __dvpMapBufferEndAPI = (PFNDVPMAPBUFFERENDAPI)BLI_dynlib_find_symbol(__dvpLibrary, "?dvpMapBufferEndAPI@@YA?AW4DVPStatus@@_K@Z");
+ __dvpMapBufferWaitDVP = (PFNDVPMAPBUFFERWAITDVP)BLI_dynlib_find_symbol(__dvpLibrary, "?dvpMapBufferWaitDVP@@YA?AW4DVPStatus@@_K@Z");
+ __dvpMapBufferEndDVP = (PFNDVPMAPBUFFERENDDVP)BLI_dynlib_find_symbol(__dvpLibrary, "?dvpMapBufferEndDVP@@YA?AW4DVPStatus@@_K@Z");
+ __dvpMapBufferWaitAPI = (PFNDVPMAPBUFFERWAITAPI)BLI_dynlib_find_symbol(__dvpLibrary, "?dvpMapBufferWaitAPI@@YA?AW4DVPStatus@@_K@Z");
+ __dvpBindToGLCtx = (PFNDVPBINDTOGLCTX)BLI_dynlib_find_symbol(__dvpLibrary, "?dvpBindToGLCtx@@YA?AW4DVPStatus@@_K@Z");
+ __dvpGetRequiredConstantsGLCtx = (PFNDVPGETREQUIREDCONSTANTSGLCTX)BLI_dynlib_find_symbol(__dvpLibrary, "?dvpGetRequiredConstantsGLCtx@@YA?AW4DVPStatus@@PEAI00000@Z");
+ __dvpCreateGPUTextureGL = (PFNDVPCREATEGPUTEXTUREGL)BLI_dynlib_find_symbol(__dvpLibrary, "?dvpCreateGPUTextureGL@@YA?AW4DVPStatus@@IPEA_K@Z");
+ __dvpUnbindFromGLCtx = (PFNDVPUNBINDFROMGLCTX)BLI_dynlib_find_symbol(__dvpLibrary, "?dvpUnbindFromGLCtx@@YA?AW4DVPStatus@@_K@Z");
+ if (!__dvpInitGLContext ||
+ !__dvpCloseGLContext ||
+ !__dvpGetLibrayVersion ||
+ !__dvpBegin ||
+ !__dvpEnd ||
+ !__dvpCreateBuffer ||
+ !__dvpDestroyBuffer ||
+ !__dvpFreeBuffer ||
+ !__dvpMemcpyLined ||
+ !__dvpMemcpy ||
+ !__dvpImportSyncObject ||
+ !__dvpFreeSyncObject ||
+ !__dvpMapBufferEndAPI ||
+ !__dvpMapBufferWaitDVP ||
+ !__dvpMapBufferEndDVP ||
+ !__dvpMapBufferWaitAPI ||
+ !__dvpBindToGLCtx ||
+ !__dvpGetRequiredConstantsGLCtx ||
+ !__dvpCreateGPUTextureGL ||
+ !__dvpUnbindFromGLCtx)
+ {
+ return DVP_STATUS_ERROR;
+ }
+ // check that the library version is what we want
+ if ((status = __dvpGetLibrayVersion(&__dvpMajorVersion, &__dvpMinorVersion)) != DVP_STATUS_OK)
+ return status;
+ if (__dvpMajorVersion != DVP_MAJOR_VERSION || __dvpMinorVersion < DVP_MINOR_VERSION)
+ return DVP_STATUS_ERROR;
+ }
+ return (!__dvpInitGLContext) ? DVP_STATUS_ERROR : __dvpInitGLContext(flags);
+}
+
+DVPStatus dvpCloseGLContext(void)
+{
+ return (!__dvpCloseGLContext) ? DVP_STATUS_ERROR : __dvpCloseGLContext();
+}
+
+#endif // WIN32
diff --git a/intern/gpudirect/dvpapi.h b/intern/gpudirect/dvpapi.h
new file mode 100644
index 00000000000..cafc4e862ae
--- /dev/null
+++ b/intern/gpudirect/dvpapi.h
@@ -0,0 +1,667 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2015, Blender Foundation
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Blender Foundation.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file gpudirect/dvpapi.h
+ * \ingroup gpudirect
+ */
+
+#ifndef __DVPAPI_H__
+#define __DVPAPI_H__
+
+#ifdef WIN32
+
+#include <stdlib.h>
+#include <stdint.h>
+
+#include "GL/glew.h"
+
+#if defined(__GNUC__) && __GNUC__>=4
+# define DVPAPI extern __attribute__ ((visibility("default")))
+#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+# define DVPAPI extern __global
+#else
+# define DVPAPI extern
+#endif
+
+#define DVPAPIENTRY
+#define DVP_MAJOR_VERSION 1
+#define DVP_MINOR_VERSION 63
+
+typedef uint64_t DVPBufferHandle;
+typedef uint64_t DVPSyncObjectHandle;
+
+typedef enum {
+ DVP_STATUS_OK = 0,
+ DVP_STATUS_INVALID_PARAMETER = 1,
+ DVP_STATUS_UNSUPPORTED = 2,
+ DVP_STATUS_END_ENUMERATION = 3,
+ DVP_STATUS_INVALID_DEVICE = 4,
+ DVP_STATUS_OUT_OF_MEMORY = 5,
+ DVP_STATUS_INVALID_OPERATION = 6,
+ DVP_STATUS_TIMEOUT = 7,
+ DVP_STATUS_INVALID_CONTEXT = 8,
+ DVP_STATUS_INVALID_RESOURCE_TYPE = 9,
+ DVP_STATUS_INVALID_FORMAT_OR_TYPE = 10,
+ DVP_STATUS_DEVICE_UNINITIALIZED = 11,
+ DVP_STATUS_UNSIGNALED = 12,
+ DVP_STATUS_SYNC_ERROR = 13,
+ DVP_STATUS_SYNC_STILL_BOUND = 14,
+ DVP_STATUS_ERROR = -1,
+} DVPStatus;
+
+// Pixel component formats stored in the system memory buffer
+// analogous to those defined in the OpenGL API, except for
+// DVP_BUFFER and the DVP_CUDA_* types. DVP_BUFFER provides
+// an unspecified format type to allow for general interpretation
+// of the bytes at a later stage (in GPU shader). Note that not
+// all paths will achieve optimal speeds due to lack of HW support
+// for the transformation. The CUDA types are to be used when
+// copying to/from a system memory buffer from-to a CUDA array, as the
+// CUDA array implies a memory layout that matches the array.
+typedef enum {
+ DVP_BUFFER, // Buffer treated as a raw buffer
+ // and copied directly into GPU buffer
+ // without any interpretation of the
+ // stored bytes.
+ DVP_DEPTH_COMPONENT,
+ DVP_RGBA,
+ DVP_BGRA,
+ DVP_RED,
+ DVP_GREEN,
+ DVP_BLUE,
+ DVP_ALPHA,
+ DVP_RGB,
+ DVP_BGR,
+ DVP_LUMINANCE,
+ DVP_LUMINANCE_ALPHA,
+ DVP_CUDA_1_CHANNEL,
+ DVP_CUDA_2_CHANNELS,
+ DVP_CUDA_4_CHANNELS,
+ DVP_RGBA_INTEGER,
+ DVP_BGRA_INTEGER,
+ DVP_RED_INTEGER,
+ DVP_GREEN_INTEGER,
+ DVP_BLUE_INTEGER,
+ DVP_ALPHA_INTEGER,
+ DVP_RGB_INTEGER,
+ DVP_BGR_INTEGER,
+ DVP_LUMINANCE_INTEGER,
+ DVP_LUMINANCE_ALPHA_INTEGER,
+} DVPBufferFormats;
+
+// Possible pixel component storage types for system memory buffers
+typedef enum {
+ DVP_UNSIGNED_BYTE,
+ DVP_BYTE,
+ DVP_UNSIGNED_SHORT,
+ DVP_SHORT,
+ DVP_UNSIGNED_INT,
+ DVP_INT,
+ DVP_FLOAT,
+ DVP_HALF_FLOAT,
+ DVP_UNSIGNED_BYTE_3_3_2,
+ DVP_UNSIGNED_BYTE_2_3_3_REV,
+ DVP_UNSIGNED_SHORT_5_6_5,
+ DVP_UNSIGNED_SHORT_5_6_5_REV,
+ DVP_UNSIGNED_SHORT_4_4_4_4,
+ DVP_UNSIGNED_SHORT_4_4_4_4_REV,
+ DVP_UNSIGNED_SHORT_5_5_5_1,
+ DVP_UNSIGNED_SHORT_1_5_5_5_REV,
+ DVP_UNSIGNED_INT_8_8_8_8,
+ DVP_UNSIGNED_INT_8_8_8_8_REV,
+ DVP_UNSIGNED_INT_10_10_10_2,
+ DVP_UNSIGNED_INT_2_10_10_10_REV,
+} DVPBufferTypes;
+
+// System memory descriptor describing the size and storage formats
+// of the buffer
+typedef struct DVPSysmemBufferDescRec {
+ uint32_t width; // Buffer Width
+ uint32_t height; // Buffer Height
+ uint32_t stride; // Stride
+ uint32_t size; // Specifies the surface size if
+ // format == DVP_BUFFER
+ DVPBufferFormats format; // see enum above
+ DVPBufferTypes type; // see enum above
+ void *bufAddr; // Buffer memory address
+} DVPSysmemBufferDesc;
+
+// Flags specified at sync object creation:
+// ----------------------------------------
+// Tells the implementation to use events wherever
+// possible instead of software spin loops. Note if HW
+// wait operations are supported by the implementation
+// then events will not be used in the dvpMemcpy*
+// functions. In such a case, events may still be used
+// in dvpSyncObjClientWait* functions.
+#define DVP_SYNC_OBJECT_FLAGS_USE_EVENTS 0x00000001
+
+typedef struct DVPSyncObjectDescRec {
+ uint32_t *sem; // Location to write semaphore value
+ uint32_t flags; // See above DVP_SYNC_OBJECT_FLAGS_* bits
+ DVPStatus (*externalClientWaitFunc) (DVPSyncObjectHandle sync,
+ uint32_t value,
+ bool GEQ, // If true then the function should wait for the sync value to be
+ // greater than or equal to the value parameter. Otherwise just a
+ // straight forward equality comparison should be performed.
+ uint64_t timeout);
+ // If non-null, externalClientWaitFunc allows the DVP library
+ // to call the application to wait for a sync object to be
+ // released. This allows the application to create events,
+ // which can be triggered on device interrupts instead of
+ // using spin loops inside the DVP library. Upon succeeding
+ // the function must return DVP_STATUS_OK, non-zero for failure
+ // and DVP_STATUS_TIMEOUT on timeout. The externalClientWaitFunc should
+ // not alter the current GL or CUDA context state
+} DVPSyncObjectDesc;
+
+// Time used when event timeouts should be ignored
+#define DVP_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFFull
+
+typedef DVPStatus (DVPAPIENTRY * PFNDVPBEGIN) (void);
+typedef DVPStatus (DVPAPIENTRY * PFNDVPEND) (void);
+typedef DVPStatus (DVPAPIENTRY * PFNDVPCREATEBUFFER)(DVPSysmemBufferDesc *desc, DVPBufferHandle *hBuf);
+typedef DVPStatus (DVPAPIENTRY * PFNDVPDESTROYBUFFER)(DVPBufferHandle hBuf);
+typedef DVPStatus (DVPAPIENTRY * PFNDVPFREEBUFFER)(DVPBufferHandle gpuBufferHandle);
+typedef DVPStatus (DVPAPIENTRY * PFNDVPMEMCPYLINED)(DVPBufferHandle srcBuffer,
+ DVPSyncObjectHandle srcSync,
+ uint32_t srcAcquireValue,
+ uint64_t timeout,
+ DVPBufferHandle dstBuffer,
+ DVPSyncObjectHandle dstSync,
+ uint32_t dstReleaseValue,
+ uint32_t startingLine,
+ uint32_t numberOfLines);
+typedef DVPStatus (DVPAPIENTRY * PFNDVPMEMCPY)(DVPBufferHandle srcBuffer,
+ DVPSyncObjectHandle srcSync,
+ uint32_t srcAcquireValue,
+ uint64_t timeout,
+ DVPBufferHandle dstBuffer,
+ DVPSyncObjectHandle dstSync,
+ uint32_t dstReleaseValue,
+ uint32_t srcOffset,
+ uint32_t dstOffset,
+ uint32_t count);
+typedef DVPStatus (DVPAPIENTRY * PFNDVPIMPORTSYNCOBJECT)(DVPSyncObjectDesc *desc,
+ DVPSyncObjectHandle *syncObject);
+typedef DVPStatus (DVPAPIENTRY * PFNDVPFREESYNCOBJECT)(DVPSyncObjectHandle syncObject);
+typedef DVPStatus (DVPAPIENTRY * PFNDVPGETREQUIREDCONSTANTSGLCTX)(uint32_t *bufferAddrAlignment,
+ uint32_t *bufferGPUStrideAlignment,
+ uint32_t *semaphoreAddrAlignment,
+ uint32_t *semaphoreAllocSize,
+ uint32_t *semaphorePayloadOffset,
+ uint32_t *semaphorePayloadSize);
+typedef DVPStatus (DVPAPIENTRY * PFNDVPBINDTOGLCTX)(DVPBufferHandle hBuf);
+typedef DVPStatus (DVPAPIENTRY * PFNDVPUNBINDFROMGLCTX)(DVPBufferHandle hBuf);
+typedef DVPStatus (DVPAPIENTRY * PFNDVPMAPBUFFERENDAPI)(DVPBufferHandle gpuBufferHandle);
+typedef DVPStatus (DVPAPIENTRY * PFNDVPMAPBUFFERWAITDVP)(DVPBufferHandle gpuBufferHandle);
+typedef DVPStatus (DVPAPIENTRY * PFNDVPMAPBUFFERENDDVP)(DVPBufferHandle gpuBufferHandle);
+typedef DVPStatus (DVPAPIENTRY * PFNDVPMAPBUFFERWAITAPI)(DVPBufferHandle gpuBufferHandle);
+typedef DVPStatus (DVPAPIENTRY * PFNDVPCREATEGPUTEXTUREGL)(GLuint texID,
+ DVPBufferHandle *bufferHandle);
+
+// Flags supplied to the dvpInit* functions:
+//
+// DVP_DEVICE_FLAGS_SHARE_APP_CONTEXT is only supported for OpenGL
+// contexts and is the only supported flag for CUDA. It allows for
+// certain cases to be optimized by sharing the context
+// of the application for the DVP operations. This removes the
+// need to do certain synchronizations. See issue 5 for parallel
+// issues. When used, the app's GL context must be current for all calls
+// to the DVP library.
+// the DVP library.
+#define DVP_DEVICE_FLAGS_SHARE_APP_CONTEXT 0x000000001
+
+//------------------------------------------------------------------------
+// Function: dvpInitGLContext
+//
+// To be called before any DVP resources are allocated.
+// This call allows for specification of flags that may
+// change the way DVP operations are performed. See above
+// for the list of flags.
+//
+// The OpenGL context must be current at time of call.
+//
+// Parameters: flags[IN] - Buffer description structure
+//
+// Returns: DVP_STATUS_OK
+// DVP_STATUS_INVALID_PARAMETER
+// DVP_STATUS_ERROR
+//------------------------------------------------------------------------
+extern DVPStatus dvpInitGLContext(uint32_t flags);
+
+//------------------------------------------------------------------------
+// Function: dvpCloseGLContext
+//
+// Function to be called when app closes to allow freeing
+// of any DVP library allocated resources.
+//
+// The OpenGL context must be current at time of call.
+//
+// Parameters: none
+//
+// Returns: DVP_STATUS_OK
+// DVP_STATUS_INVALID_PARAMETER
+// DVP_STATUS_ERROR
+//------------------------------------------------------------------------
+extern DVPStatus dvpCloseGLContext();
+
+//------------------------------------------------------------------------
+// Function: dvpGetLibrayVersion
+//
+// Description: Returns the current version of the library
+//
+// Parameters: major[OUT] - returned major version
+// minor[OUT] - returned minor version
+//
+// Returns: DVP_STATUS_OK
+//------------------------------------------------------------------------
+extern DVPStatus dvpGetLibrayVersion(uint32_t *major, uint32_t *minor);
+
+//------------------------------------------------------------------------
+// Function: dvpBegin
+//
+// Description: dvpBegin must be called before any combination of DVP
+// function calls dvpMemCpy*, dvpMapBufferWaitDVP,
+// dvpSyncObjClientWait*, and dvpMapBufferEndDVP. After
+// the last of these functions has been called is dvpEnd
+// must be called. This allows for more efficient batched
+// DVP operations.
+//
+// Parameters: none
+//
+// Returns: DVP_STATUS_OK
+// DVP_STATUS_ERROR
+//------------------------------------------------------------------------
+#define dvpBegin DVPAPI_GET_FUN(__dvpBegin)
+
+//------------------------------------------------------------------------
+// Function: dvpEnd
+//
+// Description: dvpEnd signals the end of a batch of DVP function calls
+// that began with dvpBegin
+//
+// Parameters: none
+//
+// Returns: DVP_STATUS_OK
+// DVP_STATUS_ERROR
+//------------------------------------------------------------------------
+#define dvpEnd DVPAPI_GET_FUN(__dvpEnd)
+
+
+//------------------------------------------------------------------------
+// Function: dvpCreateBuffer
+//
+// Description: Create a DVP buffer using system memory, wrapping a user
+// passed pointer. The pointer must be aligned
+// to values returned by dvpGetRequiredAlignments*
+//
+// Parameters: desc[IN] - Buffer description structure
+// hBuf[OUT] - DVP Buffer handle
+//
+// Returns: DVP_STATUS_OK
+// DVP_STATUS_INVALID_PARAMETER
+// DVP_STATUS_ERROR
+//------------------------------------------------------------------------
+#define dvpCreateBuffer DVPAPI_GET_FUN(__dvpCreateBuffer)
+
+
+//------------------------------------------------------------------------
+// Function: dvpDestroyBuffer
+//
+// Description: Destroy a previously created DVP buffer.
+//
+// Parameters: hBuf[IN] - DVP Buffer handle
+//
+// Returns: DVP_STATUS_OK
+// DVP_STATUS_INVALID_PARAMETER
+// DVP_STATUS_ERROR
+//------------------------------------------------------------------------
+#define dvpDestroyBuffer DVPAPI_GET_FUN(__dvpDestroyBuffer)
+
+//------------------------------------------------------------------------
+// Function: dvpFreeBuffer
+//
+// Description: dvpFreeBuffer frees the DVP buffer reference
+//
+// Parameters: gpuBufferHandle[IN] - DVP Buffer handle
+//
+// Returns: DVP_STATUS_OK
+// DVP_STATUS_INVALID_PARAMETER
+// DVP_STATUS_ERROR
+//------------------------------------------------------------------------
+#define dvpFreeBuffer DVPAPI_GET_FUN(__dvpFreeBuffer)
+
+//------------------------------------------------------------------------
+// Function: dvpMemcpyLined
+//
+// Description: dvpMemcpyLined provides buffer copies between a
+// DVP sysmem buffer and a graphics API texture (as opposed to
+// a buffer type). Other buffer types (such
+// as graphics API buffers) return DVP_STATUS_INVALID_PARAMETER.
+//
+// In addition, see "dvpMemcpy* general comments" above.
+//
+// Parameters: srcBuffer[IN] - src buffer handle
+// srcSync[IN] - sync to acquire on before transfer
+// srcAcquireValue[IN] - value to acquire on before transfer
+// timeout[IN] - time out value in nanoseconds.
+// dstBuffer[IN] - src buffer handle
+// dstSync[IN] - sync to release on transfer completion
+// dstReleaseValue[IN] - value to release on completion
+// startingLine[IN] - starting line of buffer
+// numberOfLines[IN] - number of lines to copy
+//
+// Returns: DVP_STATUS_OK
+// DVP_STATUS_INVALID_PARAMETER
+// DVP_STATUS_ERROR
+//
+// GL state effected: The following GL state may be altered by this
+// function (not relevant if no GL source or destination
+// is used):
+// -GL_PACK_SKIP_ROWS, GL_PACK_SKIP_PIXELS,
+// GL_PACK_ROW_LENGTH
+// -The buffer bound to GL_PIXEL_PACK_BUFFER
+// -The current bound framebuffer (GL_FRAMEBUFFER_EXT)
+// -GL_UNPACK_SKIP_ROWS, GL_UNPACK_SKIP_PIXELS,
+// GL_UNPACK_ROW_LENGTH
+// -The buffer bound to GL_PIXEL_UNPACK_BUFFER
+// -The texture bound to GL_TEXTURE_2D
+//------------------------------------------------------------------------
+#define dvpMemcpyLined DVPAPI_GET_FUN(__dvpMemcpyLined)
+
+
+//------------------------------------------------------------------------
+// Function: dvpMemcpy
+//
+// Description: dvpMemcpy provides buffer copies between a
+// DVP sysmem buffer and a graphics API pure buffer (as
+// opposed to a texture type). Other buffer types (such
+// as graphics API textures) return
+// DVP_STATUS_INVALID_PARAMETER.
+//
+// The start address of the srcBuffer is given by srcOffset
+// and the dstBuffer start address is given by dstOffset.
+//
+// In addition, see "dvpMemcpy* general comments" above.
+//
+// Parameters: srcBuffer[IN] - src buffer handle
+// srcSync[IN] - sync to acquire on before transfer
+// srcAcquireValue[IN] - value to acquire on before transfer
+// timeout[IN] - time out value in nanoseconds.
+// dstBuffer[IN] - src buffer handle
+// dstSync[IN] - sync to release on completion
+// dstReleaseValue[IN] - value to release on completion
+// uint32_t srcOffset[IN] - byte offset of srcBuffer
+// uint32_t dstOffset[IN] - byte offset of dstBuffer
+// uint32_t count[IN] - number of bytes to copy
+//
+// Returns: DVP_STATUS_OK
+// DVP_STATUS_INVALID_PARAMETER
+// DVP_STATUS_ERROR
+//
+// GL state effected: The following GL state may be altered by this
+// function (not relevant if no GL source or destination
+// is used):
+// - The buffer bound to GL_COPY_WRITE_BUFFER
+// - The buffer bound to GL_COPY_READ_BUFFER
+//
+//------------------------------------------------------------------------
+#define dvpMemcpy DVPAPI_GET_FUN(__dvpMemcpy)
+
+//------------------------------------------------------------------------
+// Function: dvpImportSyncObject
+//
+// Description: dvpImportSyncObject creates a DVPSyncObject from the
+// DVPSyncObjectDesc. Note that a sync object is not
+// supported for copy operations targeting different APIs.
+// This means, for example, it is illegal to call dvpMemCpy*
+// for source or target GL texture with sync object A and
+// then later use that same sync object in dvpMemCpy*
+// operation for a source or target CUDA buffer. The same
+// semaphore memory can still be used for two different sync
+// objects.
+//
+// Parameters: desc[IN] - data describing the sync object
+// syncObject[OUT] - handle to sync object
+//
+// Returns: DVP_STATUS_OK
+// DVP_STATUS_INVALID_PARAMETER
+// DVP_STATUS_ERROR
+//------------------------------------------------------------------------
+#define dvpImportSyncObject DVPAPI_GET_FUN(__dvpImportSyncObject)
+
+//------------------------------------------------------------------------
+// Function: dvpFreeSyncObject
+//
+// Description: dvpFreeSyncObject waits for any outstanding releases on
+// this sync object before freeing the resources allocated for
+// the specified sync object. The application must make sure
+// any outstanding acquire operations have already been
+// completed.
+//
+// If OpenGL is being used and the app's GL context is being
+// shared (via the DVP_DEVICE_FLAGS_SHARE_APP_CONTEXT flag),
+// then dvpFreeSyncObject needs to be called while each context,
+// on which the sync object was used, is current. If
+// DVP_DEVICE_FLAGS_SHARE_APP_CONTEXT is used and there are out
+// standing contexts from which this sync object must be free'd
+// then dvpFreeSyncObject will return DVP_STATUS_SYNC_STILL_BOUND.
+//
+// Parameters: syncObject[IN] - handle to sync object to be free'd
+//
+// Returns: DVP_STATUS_OK
+// DVP_STATUS_INVALID_PARAMETER
+// DVP_STATUS_ERROR
+// DVP_STATUS_SYNC_STILL_BOUND
+//------------------------------------------------------------------------
+#define dvpFreeSyncObject DVPAPI_GET_FUN(__dvpFreeSyncObject)
+
+
+//------------------------------------------------------------------------
+// Function: dvpMapBufferEndAPI
+//
+// Description: Tells DVP to setup a signal for this buffer in the
+// callers API context or device. The signal follows all
+// previous API operations up to this point and, thus,
+// allows subsequent DVP calls to know when then this buffer
+// is ready for use within the DVP library. This function
+// would be followed by a call to dvpMapBufferWaitDVP to
+// synchronize rendering in the API stream and the DVP
+// stream.
+//
+// If OpenGL or CUDA is used, the OpenGL/CUDA context
+// must be current at time of call.
+//
+// The use of dvpMapBufferEndAPI is NOT recommended for
+// CUDA synchronisation, as it is more optimal to use a
+// applcation CUDA stream in conjunction with
+// dvpMapBufferEndCUDAStream. This allows the driver to
+// do optimisations, such as parllelise the copy operations
+// and compute.
+//
+// This must be called outside the dvpBegin/dvpEnd pair. In
+// addition, this call is not thread safe and must be called
+// from or fenced against the rendering thread associated with
+// the context or device.
+//
+// Parameters: gpuBufferHandle[IN] - buffer to track
+//
+// Returns: DVP_STATUS_OK
+// DVP_STATUS_INVALID_PARAMETER
+// DVP_STATUS_ERROR
+// DVP_STATUS_UNSIGNALED - returned if the API is
+// unable to place a signal in the API context queue
+//------------------------------------------------------------------------
+#define dvpMapBufferEndAPI DVPAPI_GET_FUN(__dvpMapBufferEndAPI)
+
+//------------------------------------------------------------------------
+// Function: dvpMapBufferEndAPI
+//
+// Description: Tells DVP to setup a signal for this buffer in the
+// callers API context or device. The signal follows all
+// previous API operations up to this point and, thus,
+// allows subsequent DVP calls to know when then this buffer
+// is ready for use within the DVP library. This function
+// would be followed by a call to dvpMapBufferWaitDVP to
+// synchronize rendering in the API stream and the DVP
+// stream.
+//
+// If OpenGL or CUDA is used, the OpenGL/CUDA context
+// must be current at time of call.
+//
+// The use of dvpMapBufferEndAPI is NOT recommended for
+// CUDA synchronisation, as it is more optimal to use a
+// applcation CUDA stream in conjunction with
+// dvpMapBufferEndCUDAStream. This allows the driver to
+// do optimisations, such as parllelise the copy operations
+// and compute.
+//
+// This must be called outside the dvpBegin/dvpEnd pair. In
+// addition, this call is not thread safe and must be called
+// from or fenced against the rendering thread associated with
+// the context or device.
+//
+// Parameters: gpuBufferHandle[IN] - buffer to track
+//
+// Returns: DVP_STATUS_OK
+// DVP_STATUS_INVALID_PARAMETER
+// DVP_STATUS_ERROR
+// DVP_STATUS_UNSIGNALED - returned if the API is
+// unable to place a signal in the API context queue
+//------------------------------------------------------------------------
+#define dvpMapBufferEndAPI DVPAPI_GET_FUN(__dvpMapBufferEndAPI)
+
+//------------------------------------------------------------------------
+// Function: dvpMapBufferWaitDVP
+//
+// Description: Tells DVP to make the DVP stream wait for a previous
+// signal triggered by a dvpMapBufferEndAPI call.
+//
+// This must be called inside the dvpBegin/dvpEnd pair.
+//
+// Parameters: gpuBufferHandle[IN] - buffer to track
+//
+// Returns: DVP_STATUS_OK
+// DVP_STATUS_INVALID_PARAMETER
+// DVP_STATUS_ERROR
+//------------------------------------------------------------------------
+#define dvpMapBufferWaitDVP DVPAPI_GET_FUN(__dvpMapBufferWaitDVP)
+
+//------------------------------------------------------------------------
+// Function: dvpMapBufferEndDVP
+//
+// Description: Tells DVP to setup a signal for this buffer after
+// DVP operations are complete. The signal allows
+// the API to know when then this buffer is
+// ready for use within a API stream. This function would
+// be followed by a call to dvpMapBufferWaitAPI to
+// synchronize copies in the DVP stream and the API
+// rendering stream.
+//
+// This must be called inside the dvpBegin/dvpEnd pair.
+//
+// Parameters: gpuBufferHandle[IN] - buffer to track
+//
+// Returns: DVP_STATUS_OK
+// DVP_STATUS_INVALID_PARAMETER
+// DVP_STATUS_ERROR
+//------------------------------------------------------------------------
+#define dvpMapBufferEndDVP DVPAPI_GET_FUN(__dvpMapBufferEndDVP)
+
+//------------------------------------------------------------------------
+// Function: dvpMapBufferWaitAPI
+//
+// Description: Tells DVP to make the current API context or device to
+// wait for a previous signal triggered by a
+// dvpMapBufferEndDVP call.
+//
+// The use of dvpMapBufferWaitCUDAStream is NOT recommended for
+// CUDA synchronisation, as it is more optimal to use a
+// applcation CUDA stream in conjunction with
+// dvpMapBufferEndCUDAStream. This allows the driver to
+// do optimisations, such as parllelise the copy operations
+// and compute.
+//
+// If OpenGL or CUDA is used, the OpenGL/CUDA context
+// must be current at time of call.
+//
+// This must be called outside the dvpBegin/dvpEnd pair. In
+// addition, this call is not thread safe and must be called
+// from or fenced against the rendering thread associated with
+// the context or device.
+//
+// Parameters: gpuBufferHandle[IN] - buffer to track
+//
+// Returns: DVP_STATUS_OK
+// DVP_STATUS_INVALID_PARAMETER
+// DVP_STATUS_ERROR
+//------------------------------------------------------------------------
+#define dvpMapBufferWaitAPI DVPAPI_GET_FUN(__dvpMapBufferWaitAPI)
+
+//------------------------------------------------------------------------
+// If the multiple GL contexts used in the application access the same
+// sysmem buffers, then application must create those GL contexts with
+// display list shared.
+//------------------------------------------------------------------------
+#define dvpBindToGLCtx DVPAPI_GET_FUN(__dvpBindToGLCtx)
+#define dvpGetRequiredConstantsGLCtx DVPAPI_GET_FUN(__dvpGetRequiredConstantsGLCtx)
+#define dvpCreateGPUTextureGL DVPAPI_GET_FUN(__dvpCreateGPUTextureGL)
+#define dvpUnbindFromGLCtx DVPAPI_GET_FUN(__dvpUnbindFromGLCtx)
+
+
+DVPAPI PFNDVPBEGIN __dvpBegin;
+DVPAPI PFNDVPEND __dvpEnd;
+DVPAPI PFNDVPCREATEBUFFER __dvpCreateBuffer;
+DVPAPI PFNDVPDESTROYBUFFER __dvpDestroyBuffer;
+DVPAPI PFNDVPFREEBUFFER __dvpFreeBuffer;
+DVPAPI PFNDVPMEMCPYLINED __dvpMemcpyLined;
+DVPAPI PFNDVPMEMCPY __dvpMemcpy;
+DVPAPI PFNDVPIMPORTSYNCOBJECT __dvpImportSyncObject;
+DVPAPI PFNDVPFREESYNCOBJECT __dvpFreeSyncObject;
+DVPAPI PFNDVPMAPBUFFERENDAPI __dvpMapBufferEndAPI;
+DVPAPI PFNDVPMAPBUFFERWAITDVP __dvpMapBufferWaitDVP;
+DVPAPI PFNDVPMAPBUFFERENDDVP __dvpMapBufferEndDVP;
+DVPAPI PFNDVPMAPBUFFERWAITAPI __dvpMapBufferWaitAPI;
+
+
+//------------------------------------------------------------------------
+// If the multiple GL contexts used in the application access the same
+// sysmem buffers, then application must create those GL contexts with
+// display list shared.
+//------------------------------------------------------------------------
+DVPAPI PFNDVPBINDTOGLCTX __dvpBindToGLCtx;
+DVPAPI PFNDVPGETREQUIREDCONSTANTSGLCTX __dvpGetRequiredConstantsGLCtx;
+DVPAPI PFNDVPCREATEGPUTEXTUREGL __dvpCreateGPUTextureGL;
+DVPAPI PFNDVPUNBINDFROMGLCTX __dvpUnbindFromGLCtx;
+
+#define DVPAPI_GET_FUN(x) x
+
+#endif // WIN32
+
+#endif // __DVPAPI_H__
+
diff --git a/intern/guardedalloc/test/simpletest/memtest.c b/intern/guardedalloc/test/simpletest/memtest.c
index 841b47bd4f1..79d55dd02cc 100644
--- a/intern/guardedalloc/test/simpletest/memtest.c
+++ b/intern/guardedalloc/test/simpletest/memtest.c
@@ -26,7 +26,6 @@
*/
/**
-
* Copyright (C) 2001 NaN Technologies B.V.
* Simple test of memory.
*/
diff --git a/intern/libmv/intern/autotrack.cc b/intern/libmv/intern/autotrack.cc
index f0cbc68f11e..3b7c9c5a010 100644
--- a/intern/libmv/intern/autotrack.cc
+++ b/intern/libmv/intern/autotrack.cc
@@ -67,12 +67,12 @@ int libmv_autoTrackMarker(libmv_AutoTrack* libmv_autotrack,
libmv_apiMarkerToMarker(*libmv_tracked_marker, &tracked_marker);
libmv_configureTrackRegionOptions(*libmv_options,
&options);
- (((AutoTrack*) libmv_autotrack)->TrackMarker(&tracked_marker,
- &result,
- &options));
+ bool ok = (((AutoTrack*) libmv_autotrack)->TrackMarker(&tracked_marker,
+ &result,
+ &options));
libmv_markerToApiMarker(tracked_marker, libmv_tracked_marker);
libmv_regionTrackergetResult(result, libmv_result);
- return result.is_usable();
+ return ok && result.is_usable();
}
void libmv_autoTrackAddMarker(libmv_AutoTrack* libmv_autotrack,
diff --git a/intern/libmv/libmv/multiview/projection.h b/intern/libmv/libmv/multiview/projection.h
index 3220bc2dbbc..8f304f31ec6 100644
--- a/intern/libmv/libmv/multiview/projection.h
+++ b/intern/libmv/libmv/multiview/projection.h
@@ -122,7 +122,7 @@ inline void Project(const Mat34 &P, const Vec3 &X, Vec3 *x) {
inline void Project(const Mat34 &P, const Vec3 &X, Vec2 *x) {
Vec3 hx;
- Project(P, X, x);
+ Project(P, X, &hx);
*x = hx.head<2>() / hx(2);
}
diff --git a/intern/libmv/libmv/numeric/numeric.cc b/intern/libmv/libmv/numeric/numeric.cc
index 9007663c8e2..3fc1e3b2bfd 100644
--- a/intern/libmv/libmv/numeric/numeric.cc
+++ b/intern/libmv/libmv/numeric/numeric.cc
@@ -109,7 +109,7 @@ void MeanAndVarianceAlongRows(const Mat &A,
}
void HorizontalStack(const Mat &left, const Mat &right, Mat *stacked) {
- assert(left.rows() == left.rows());
+ assert(left.rows() == right.rows());
int n = left.rows();
int m1 = left.cols();
int m2 = right.cols();
diff --git a/intern/libmv/libmv/numeric/numeric.h b/intern/libmv/libmv/numeric/numeric.h
index 20a4a29e5ba..a42dab8c7a2 100644
--- a/intern/libmv/libmv/numeric/numeric.h
+++ b/intern/libmv/libmv/numeric/numeric.h
@@ -148,7 +148,7 @@ using Eigen::Matrix;
// A = U * diag(s) * VT
//
template <typename TMat, typename TVec>
-inline void SVD(TMat *A, Vec *s, Mat *U, Mat *VT) {
+inline void SVD(TMat * /*A*/, Vec * /*s*/, Mat * /*U*/, Mat * /*VT*/) {
assert(0);
}
diff --git a/intern/moto/include/MT_Matrix4x4.h b/intern/moto/include/MT_Matrix4x4.h
index 045cc3b8361..2ecac81ea6f 100644
--- a/intern/moto/include/MT_Matrix4x4.h
+++ b/intern/moto/include/MT_Matrix4x4.h
@@ -144,6 +144,16 @@ public:
}
/**
+ * Scale the rows of this matrix with x, y, z, w respectively.
+ */
+ void tscale(MT_Scalar x, MT_Scalar y, MT_Scalar z, MT_Scalar w) {
+ m_el[0][0] *= x; m_el[1][0] *= y; m_el[2][0] *= z; m_el[3][0] *= w;
+ m_el[0][1] *= x; m_el[1][1] *= y; m_el[2][1] *= z; m_el[3][1] *= w;
+ m_el[0][2] *= x; m_el[1][2] *= y; m_el[2][2] *= z; m_el[3][2] *= w;
+ m_el[0][3] *= x; m_el[1][3] *= y; m_el[2][3] *= z; m_el[3][3] *= w;
+ }
+
+ /**
* Return a column-scaled version of this matrix.
*/
MT_Matrix4x4 scaled(MT_Scalar x, MT_Scalar y, MT_Scalar z, MT_Scalar w) const {
diff --git a/intern/opencolorio/gpu_shader_display_transform.glsl b/intern/opencolorio/gpu_shader_display_transform.glsl
index 5921d6d9c73..853bf575582 100644
--- a/intern/opencolorio/gpu_shader_display_transform.glsl
+++ b/intern/opencolorio/gpu_shader_display_transform.glsl
@@ -38,7 +38,7 @@ float read_curve_mapping(int table, int index)
* But is it actually correct to subtract 1 here?
*/
float texture_index = float(index) / float(curve_mapping_lut_size - 1);
- return texture1D(curve_mapping_texture, texture_index) [table];
+ return texture1D(curve_mapping_texture, texture_index)[table];
}
float curvemap_calc_extend(int table, float x, vec2 first, vec2 last)
diff --git a/intern/opensubdiv/CMakeLists.txt b/intern/opensubdiv/CMakeLists.txt
index 311b89b97cf..f8e80de7f8f 100644
--- a/intern/opensubdiv/CMakeLists.txt
+++ b/intern/opensubdiv/CMakeLists.txt
@@ -47,6 +47,7 @@ set(SRC
opensubdiv_device_context_cuda.h
opensubdiv_device_context_opencl.h
opensubdiv_intern.h
+ opensubdiv_topology_refiner.h
)
macro(OPENSUBDIV_DEFINE_COMPONENT component)
@@ -69,6 +70,7 @@ add_definitions(-DGLEW_STATIC)
if(WIN32)
add_definitions(-DNOMINMAX)
+ add_definitions(-D_USE_MATH_DEFINES)
endif()
# TODO(sergey): Put CUEW back when CUDA is officially supported by OSD.
diff --git a/intern/opensubdiv/gpu_shader_opensubd_display.glsl b/intern/opensubdiv/gpu_shader_opensubd_display.glsl
index 51e8ed46c34..5193d3a71dc 100644
--- a/intern/opensubdiv/gpu_shader_opensubd_display.glsl
+++ b/intern/opensubdiv/gpu_shader_opensubd_display.glsl
@@ -99,6 +99,7 @@ in block {
}
uniform samplerBuffer FVarDataBuffer;
+uniform isamplerBuffer FVarDataOffsetBuffer;
out block {
VertexData v;
@@ -111,7 +112,7 @@ void emit(int index, vec3 normal)
outpt.v.normal = normal;
/* TODO(sergey): Only uniform subdivisions atm. */
- vec2 quadst[4] = vec2[](vec2(0,0), vec2(1,0), vec2(1,1), vec2(0,1));
+ vec2 quadst[4] = vec2[](vec2(0, 0), vec2(1, 0), vec2(1, 1), vec2(0, 1));
vec2 st = quadst[index];
INTERP_FACE_VARYING_2(outpt.v.uv, osd_active_uv_offset, st);
@@ -135,7 +136,7 @@ void emit(int index)
outpt.v.normal = inpt[index].v.normal;
/* TODO(sergey): Only uniform subdivisions atm. */
- vec2 quadst[4] = vec2[](vec2(0,0), vec2(1,0), vec2(1,1), vec2(0,1));
+ vec2 quadst[4] = vec2[](vec2(0, 0), vec2(1, 0), vec2(1, 1), vec2(0, 1));
vec2 st = quadst[index];
INTERP_FACE_VARYING_2(outpt.v.uv, osd_active_uv_offset, st);
@@ -208,6 +209,7 @@ struct LightSource {
float spotCutoff;
float spotExponent;
float spotCosCutoff;
+ float pad, pad2;
#endif
};
@@ -240,6 +242,7 @@ void main()
vec3 L_diffuse = vec3(0.0);
vec3 L_specular = vec3(0.0);
+#ifdef USE_LIGHTING
#ifndef USE_COLOR_MATERIAL
/* Assume NUM_SOLID_LIGHTS directional lights. */
for (int i = 0; i < NUM_SOLID_LIGHTS; i++) {
@@ -261,7 +264,7 @@ void main()
#else /* USE_COLOR_MATERIAL */
vec3 varying_position = inpt.v.position.xyz;
vec3 V = (gl_ProjectionMatrix[3][3] == 0.0) ?
- normalize(varying_position): vec3(0.0, 0.0, -1.0);
+ normalize(varying_position) : vec3(0.0, 0.0, -1.0);
for (int i = 0; i < num_enabled_lights; i++) {
/* todo: this is a slow check for disabled lights */
if (lightSource[i].specular.a == 0.0)
@@ -299,7 +302,7 @@ void main()
/* diffuse light */
vec3 light_diffuse = lightSource[i].diffuse.rgb;
float diffuse_bsdf = max(dot(N, light_direction), 0.0);
- L_diffuse += light_diffuse*diffuse_bsdf*intensity;
+ L_diffuse += light_diffuse * diffuse_bsdf * intensity;
/* specular light */
vec3 light_specular = lightSource[i].specular.rgb;
@@ -307,9 +310,12 @@ void main()
float specular_bsdf = pow(max(dot(N, H), 0.0),
gl_FrontMaterial.shininess);
- L_specular += light_specular*specular_bsdf * intensity;
+ L_specular += light_specular * specular_bsdf * intensity;
}
#endif /* USE_COLOR_MATERIAL */
+#else /* USE_LIGHTING */
+ L_diffuse = vec3(1.0);
+#endif
/* Compute diffuse color. */
#ifdef USE_TEXTURE_2D
diff --git a/intern/opensubdiv/opensubdiv_capi.cc b/intern/opensubdiv/opensubdiv_capi.cc
index 9b9f4baa39e..ab904953c70 100644
--- a/intern/opensubdiv/opensubdiv_capi.cc
+++ b/intern/opensubdiv/opensubdiv_capi.cc
@@ -67,8 +67,10 @@
#include <opensubdiv/osd/glPatchTable.h>
#include <opensubdiv/far/stencilTable.h>
+#include <opensubdiv/far/primvarRefiner.h>
#include "opensubdiv_intern.h"
+#include "opensubdiv_topology_refiner.h"
#include "MEM_guardedalloc.h"
@@ -142,11 +144,73 @@ typedef Mesh<GLVertexBuffer,
GLPatchTable> OsdGLSLComputeMesh;
#endif
+namespace {
+
+struct FVarVertex {
+ float u, v;
+ void Clear() {
+ u = v = 0.0f;
+ }
+ void AddWithWeight(FVarVertex const & src, float weight) {
+ u += weight * src.u;
+ v += weight * src.v;
+ }
+};
+
+static void interpolate_fvar_data(OpenSubdiv::Far::TopologyRefiner& refiner,
+ const std::vector<float> uvs,
+ std::vector<float> &fvar_data) {
+ /* TODO(sergey): Make it somehow more generic way. */
+ const int fvar_width = 2;
+ const int max_level = refiner.GetMaxLevel();
+ size_t fvar_data_offset = 0, values_offset = 0;
+ for (int channel = 0; channel < refiner.GetNumFVarChannels(); ++channel) {
+ const int num_values = refiner.GetLevel(0).GetNumFVarValues(0) * 2,
+ num_values_max = refiner.GetLevel(max_level).GetNumFVarValues(channel),
+ num_values_total = refiner.GetNumFVarValuesTotal(channel);
+ if (num_values_total <= 0) {
+ continue;
+ }
+ OpenSubdiv::Far::PrimvarRefiner primvar_refiner(refiner);
+ if (refiner.IsUniform()) {
+ /* For uniform we only keep the highest level of refinement. */
+ fvar_data.resize(fvar_data.size() + num_values_max * fvar_width);
+ std::vector<FVarVertex> buffer(num_values_total - num_values_max);
+ FVarVertex *src = &buffer[0];
+ memcpy(src, &uvs[values_offset], num_values * sizeof(float));
+ /* Defer the last level to treat separately with its alternate
+ * destination.
+ */
+ for (int level = 1; level < max_level; ++level) {
+ FVarVertex *dst = src + refiner.GetLevel(level-1).GetNumFVarValues(channel);
+ primvar_refiner.InterpolateFaceVarying(level, src, dst, channel);
+ src = dst;
+ }
+ FVarVertex *dst = reinterpret_cast<FVarVertex *>(&fvar_data[fvar_data_offset]);
+ primvar_refiner.InterpolateFaceVarying(max_level, src, dst, channel);
+ fvar_data_offset += num_values_max * fvar_width;
+ } else {
+ /* For adaptive we keep all levels. */
+ fvar_data.resize(fvar_data.size() + num_values_total * fvar_width);
+ FVarVertex *src = reinterpret_cast<FVarVertex *>(&fvar_data[fvar_data_offset]);
+ memcpy(src, &uvs[values_offset], num_values * sizeof(float));
+ for (int level = 1; level <= max_level; ++level) {
+ FVarVertex *dst = src + refiner.GetLevel(level-1).GetNumFVarValues(channel);
+ primvar_refiner.InterpolateFaceVarying(level, src, dst, channel);
+ src = dst;
+ }
+ fvar_data_offset += num_values_total * fvar_width;
+ }
+ values_offset += num_values;
+ }
+}
+
+} // namespace
+
struct OpenSubdiv_GLMesh *openSubdiv_createOsdGLMeshFromTopologyRefiner(
OpenSubdiv_TopologyRefinerDescr *topology_refiner,
int evaluator_type,
- int level,
- int /*subdivide_uvs*/)
+ int level)
{
using OpenSubdiv::Far::TopologyRefiner;
@@ -164,7 +228,7 @@ struct OpenSubdiv_GLMesh *openSubdiv_createOsdGLMeshFromTopologyRefiner(
const int num_varying_elements = 3;
GLMeshInterface *mesh = NULL;
- TopologyRefiner *refiner = (TopologyRefiner*)topology_refiner;
+ TopologyRefiner *refiner = topology_refiner->osd_refiner;
switch(evaluator_type) {
#define CHECK_EVALUATOR_TYPE(type, class) \
@@ -210,13 +274,23 @@ struct OpenSubdiv_GLMesh *openSubdiv_createOsdGLMeshFromTopologyRefiner(
(OpenSubdiv_GLMesh *) OBJECT_GUARDED_NEW(OpenSubdiv_GLMesh);
gl_mesh->evaluator_type = evaluator_type;
gl_mesh->descriptor = (OpenSubdiv_GLMeshDescr *) mesh;
- gl_mesh->topology_refiner = (OpenSubdiv_TopologyRefinerDescr*)refiner;
+ gl_mesh->topology_refiner = topology_refiner;
+
+ if (refiner->GetNumFVarChannels() > 0) {
+ std::vector<float> fvar_data;
+ interpolate_fvar_data(*refiner, topology_refiner->uvs, fvar_data);
+ openSubdiv_osdGLAllocFVar(topology_refiner, gl_mesh, &fvar_data[0]);
+ }
+ else {
+ gl_mesh->fvar_data = NULL;
+ }
return gl_mesh;
}
void openSubdiv_deleteOsdGLMesh(struct OpenSubdiv_GLMesh *gl_mesh)
{
+ openSubdiv_osdGLDestroyFVar(gl_mesh);
switch (gl_mesh->evaluator_type) {
#define CHECK_EVALUATOR_TYPE(type, class) \
case OPENSUBDIV_EVALUATOR_ ## type: \
@@ -249,6 +323,8 @@ void openSubdiv_deleteOsdGLMesh(struct OpenSubdiv_GLMesh *gl_mesh)
#undef CHECK_EVALUATOR_TYPE
}
+ /* NOTE: OSD refiner was owned by gl_mesh, no need to free it here. */
+ OBJECT_GUARDED_DELETE(gl_mesh->topology_refiner, OpenSubdiv_TopologyRefinerDescr);
OBJECT_GUARDED_DELETE(gl_mesh, OpenSubdiv_GLMesh);
}
@@ -299,6 +375,9 @@ int openSubdiv_supportGPUDisplay(void)
return openSubdiv_gpu_legacy_support() &&
(GLEW_VERSION_3_2 ||
(GLEW_VERSION_3_1 && GLEW_EXT_geometry_shader4) ||
- (GLEW_VERSION_3_0 && GLEW_EXT_geometry_shader4 && GLEW_ARB_uniform_buffer_object && (GLEW_ARB_texture_buffer_object || GLEW_EXT_texture_buffer_object)));
+ (GLEW_VERSION_3_0 &&
+ GLEW_EXT_geometry_shader4 &&
+ GLEW_ARB_uniform_buffer_object &&
+ (GLEW_ARB_texture_buffer_object || GLEW_EXT_texture_buffer_object)));
/* also ARB_explicit_attrib_location? */
}
diff --git a/intern/opensubdiv/opensubdiv_capi.h b/intern/opensubdiv/opensubdiv_capi.h
index b40505b197d..c3a194813e6 100644
--- a/intern/opensubdiv/opensubdiv_capi.h
+++ b/intern/opensubdiv/opensubdiv_capi.h
@@ -32,16 +32,19 @@ extern "C" {
// Types declaration.
struct OpenSubdiv_GLMesh;
+struct OpenSubdiv_GLMeshFVarData;
struct OpenSubdiv_TopologyRefinerDescr;
typedef struct OpenSubdiv_GLMesh OpenSubdiv_GLMesh;
#ifdef __cplusplus
struct OpenSubdiv_GLMeshDescr;
+
typedef struct OpenSubdiv_GLMesh {
int evaluator_type;
OpenSubdiv_GLMeshDescr *descriptor;
OpenSubdiv_TopologyRefinerDescr *topology_refiner;
+ OpenSubdiv_GLMeshFVarData *fvar_data;
} OpenSubdiv_GLMesh;
#endif
@@ -66,8 +69,7 @@ enum {
OpenSubdiv_GLMesh *openSubdiv_createOsdGLMeshFromTopologyRefiner(
struct OpenSubdiv_TopologyRefinerDescr *topology_refiner,
int evaluator_type,
- int level,
- int subdivide_uvs);
+ int level);
void openSubdiv_deleteOsdGLMesh(OpenSubdiv_GLMesh *gl_mesh);
unsigned int openSubdiv_getOsdGLMeshPatchIndexBuffer(
@@ -138,6 +140,11 @@ void openSubdiv_osdGLMeshDisplay(OpenSubdiv_GLMesh *gl_mesh,
int start_patch,
int num_patches);
+void openSubdiv_osdGLAllocFVar(struct OpenSubdiv_TopologyRefinerDescr *topology_refiner,
+ OpenSubdiv_GLMesh *gl_mesh,
+ const float *fvar_data);
+void openSubdiv_osdGLDestroyFVar(OpenSubdiv_GLMesh *gl_mesh);
+
/* ** Utility functions ** */
int openSubdiv_supportGPUDisplay(void);
int openSubdiv_getAvailableEvaluators(void);
diff --git a/intern/opensubdiv/opensubdiv_converter.cc b/intern/opensubdiv/opensubdiv_converter.cc
index 3fadde68d32..ea41a56768f 100644
--- a/intern/opensubdiv/opensubdiv_converter.cc
+++ b/intern/opensubdiv/opensubdiv_converter.cc
@@ -32,8 +32,12 @@
#include <opensubdiv/far/topologyRefinerFactory.h>
+#include "MEM_guardedalloc.h"
+
#include "opensubdiv_converter_capi.h"
#include "opensubdiv_intern.h"
+#include "opensubdiv_topology_refiner.h"
+
#include <stack>
@@ -49,6 +53,11 @@ inline void reverse_face_verts(int *face_verts, int num_verts)
face_verts[0] = last_vert;
}
+struct TopologyRefinerData {
+ const OpenSubdiv_Converter& conv;
+ std::vector<float> *uvs;
+};
+
} /* namespace */
#endif /* OPENSUBDIV_ORIENT_TOPOLOGY */
@@ -137,10 +146,11 @@ inline void check_oriented_vert_connectivity(const int num_vert_edges,
} /* namespace */
template <>
-inline bool TopologyRefinerFactory<OpenSubdiv_Converter>::resizeComponentTopology(
+inline bool TopologyRefinerFactory<TopologyRefinerData>::resizeComponentTopology(
TopologyRefiner& refiner,
- const OpenSubdiv_Converter& conv)
+ const TopologyRefinerData& cb_data)
{
+ const OpenSubdiv_Converter& conv = cb_data.conv;
/* Faces and face-verts */
const int num_faces = conv.get_num_faces(&conv);
setNumBaseFaces(refiner, num_faces);
@@ -168,10 +178,11 @@ inline bool TopologyRefinerFactory<OpenSubdiv_Converter>::resizeComponentTopolog
}
template <>
-inline bool TopologyRefinerFactory<OpenSubdiv_Converter>::assignComponentTopology(
+inline bool TopologyRefinerFactory<TopologyRefinerData>::assignComponentTopology(
TopologyRefiner& refiner,
- const OpenSubdiv_Converter& conv)
+ const TopologyRefinerData &cb_data)
{
+ const OpenSubdiv_Converter& conv = cb_data.conv;
using Far::IndexArray;
/* Face relations. */
const int num_faces = conv.get_num_faces(&conv);
@@ -332,7 +343,6 @@ inline bool TopologyRefinerFactory<OpenSubdiv_Converter>::assignComponentTopolog
else {
/* Special handle of non-manifold vertex. */
for (int i = 0; i < num_vert_edges; ++i) {
- bool start_found = false;
edge_start = vert_edges[i];
IndexArray edge_faces = getBaseEdgeFaces(refiner, edge_start);
if (edge_faces.size() == 1) {
@@ -343,14 +353,10 @@ inline bool TopologyRefinerFactory<OpenSubdiv_Converter>::assignComponentTopolog
face_edges = getBaseFaceEdges(refiner, face_start);
face_vert_start = findInArray(face_verts, vert);
if (edge_start == face_edges[face_vert_start]) {
- start_found = true;
break;
}
}
}
- if (start_found) {
- break;
- }
/* Reset indices for sanity check below. */
face_start = edge_start = face_vert_start = -1;
}
@@ -431,10 +437,11 @@ inline bool TopologyRefinerFactory<OpenSubdiv_Converter>::assignComponentTopolog
};
template <>
-inline bool TopologyRefinerFactory<OpenSubdiv_Converter>::assignComponentTags(
+inline bool TopologyRefinerFactory<TopologyRefinerData>::assignComponentTags(
TopologyRefiner& refiner,
- const OpenSubdiv_Converter& conv)
+ const TopologyRefinerData& cb_data)
{
+ const OpenSubdiv_Converter& conv = cb_data.conv;
typedef OpenSubdiv::Sdc::Crease Crease;
int num_edges = conv.get_num_edges(&conv);
@@ -481,14 +488,52 @@ inline bool TopologyRefinerFactory<OpenSubdiv_Converter>::assignComponentTags(
}
template <>
-inline void TopologyRefinerFactory<OpenSubdiv_Converter>::reportInvalidTopology(
+inline void TopologyRefinerFactory<TopologyRefinerData>::reportInvalidTopology(
TopologyError /*errCode*/,
const char *msg,
- const OpenSubdiv_Converter& /*mesh*/)
+ const TopologyRefinerData& /*mesh*/)
{
printf("OpenSubdiv Error: %s\n", msg);
}
+template <>
+inline bool TopologyRefinerFactory<TopologyRefinerData>::assignFaceVaryingTopology(
+ TopologyRefiner& refiner,
+ const TopologyRefinerData& cb_data)
+{
+ const OpenSubdiv_Converter& conv = cb_data.conv;
+ const int num_layers = conv.get_num_uv_layers(&conv);
+ if (num_layers <= 0) {
+ /* No UV maps, we can skip any face-varying data. */
+ return true;
+ }
+ const int num_faces = getNumBaseFaces(refiner);
+ size_t uvs_offset = 0;
+ for (int layer = 0; layer < num_layers; ++layer) {
+ conv.precalc_uv_layer(&conv, layer);
+ const int num_uvs = conv.get_num_uvs(&conv);
+ /* Fill in UV coordinates. */
+ cb_data.uvs->resize(cb_data.uvs->size() + num_uvs * 2);
+ conv.get_uvs(&conv, &cb_data.uvs->at(uvs_offset));
+ uvs_offset += num_uvs * 2;
+ /* Fill in per-corner index of the UV. */
+ const int channel = createBaseFVarChannel(refiner, num_uvs);
+ for (int face = 0; face < num_faces; ++face) {
+ Far::IndexArray dst_face_uvs = getBaseFaceFVarValues(refiner,
+ face,
+ channel);
+ for (int corner = 0; corner < dst_face_uvs.size(); ++corner) {
+ const int uv_index = conv.get_face_corner_uv_index(&conv,
+ face,
+ corner);
+ dst_face_uvs[corner] = uv_index;
+ }
+ }
+ conv.finish_uv_layer(&conv);
+ }
+ return true;
+}
+
} /* namespace Far */
} /* namespace OPENSUBDIV_VERSION */
} /* namespace OpenSubdiv */
@@ -522,33 +567,43 @@ struct OpenSubdiv_TopologyRefinerDescr *openSubdiv_createTopologyRefinerDescr(
Options options;
options.SetVtxBoundaryInterpolation(Options::VTX_BOUNDARY_EDGE_ONLY);
options.SetCreasingMethod(Options::CREASE_UNIFORM);
- options.SetFVarLinearInterpolation(Options::FVAR_LINEAR_ALL);
+ if (converter->get_subdiv_uvs(converter)) {
+ options.SetFVarLinearInterpolation(Options::FVAR_LINEAR_CORNERS_ONLY);
+ }
+ else {
+ options.SetFVarLinearInterpolation(Options::FVAR_LINEAR_ALL);
+ }
- TopologyRefinerFactory<OpenSubdiv_Converter>::Options
+ TopologyRefinerFactory<TopologyRefinerData>::Options
topology_options(scheme_type, options);
#ifdef OPENSUBDIV_VALIDATE_TOPOLOGY
topology_options.validateFullTopology = true;
#endif
+ OpenSubdiv_TopologyRefinerDescr *result = OBJECT_GUARDED_NEW(OpenSubdiv_TopologyRefinerDescr);
+ TopologyRefinerData cb_data = {*converter, &result->uvs};
/* We don't use guarded allocation here so we can re-use the refiner
* for GL mesh creation directly.
*/
- return (struct OpenSubdiv_TopologyRefinerDescr*)
- TopologyRefinerFactory<OpenSubdiv_Converter>::Create(
- *converter,
+ result->osd_refiner =
+ TopologyRefinerFactory<TopologyRefinerData>::Create(
+ cb_data,
topology_options);
+
+ return result;
}
void openSubdiv_deleteTopologyRefinerDescr(
OpenSubdiv_TopologyRefinerDescr *topology_refiner)
{
- delete (OpenSubdiv::Far::TopologyRefiner *)topology_refiner;
+ delete topology_refiner->osd_refiner;
+ OBJECT_GUARDED_DELETE(topology_refiner, OpenSubdiv_TopologyRefinerDescr);
}
int openSubdiv_topologyRefinerGetSubdivLevel(
const OpenSubdiv_TopologyRefinerDescr *topology_refiner)
{
using OpenSubdiv::Far::TopologyRefiner;
- const TopologyRefiner *refiner = (const TopologyRefiner *)topology_refiner;
+ const TopologyRefiner *refiner = topology_refiner->osd_refiner;
return refiner->GetMaxLevel();
}
@@ -557,7 +612,7 @@ int openSubdiv_topologyRefinerGetNumVerts(
{
using OpenSubdiv::Far::TopologyLevel;
using OpenSubdiv::Far::TopologyRefiner;
- const TopologyRefiner *refiner = (const TopologyRefiner *)topology_refiner;
+ const TopologyRefiner *refiner = topology_refiner->osd_refiner;
const TopologyLevel &base_level = refiner->GetLevel(0);
return base_level.GetNumVertices();
}
@@ -567,7 +622,7 @@ int openSubdiv_topologyRefinerGetNumEdges(
{
using OpenSubdiv::Far::TopologyLevel;
using OpenSubdiv::Far::TopologyRefiner;
- const TopologyRefiner *refiner = (const TopologyRefiner *)topology_refiner;
+ const TopologyRefiner *refiner = topology_refiner->osd_refiner;
const TopologyLevel &base_level = refiner->GetLevel(0);
return base_level.GetNumEdges();
}
@@ -577,7 +632,7 @@ int openSubdiv_topologyRefinerGetNumFaces(
{
using OpenSubdiv::Far::TopologyLevel;
using OpenSubdiv::Far::TopologyRefiner;
- const TopologyRefiner *refiner = (const TopologyRefiner *)topology_refiner;
+ const TopologyRefiner *refiner = topology_refiner->osd_refiner;
const TopologyLevel &base_level = refiner->GetLevel(0);
return base_level.GetNumFaces();
}
@@ -588,7 +643,7 @@ int openSubdiv_topologyRefinerGetNumFaceVerts(
{
using OpenSubdiv::Far::TopologyLevel;
using OpenSubdiv::Far::TopologyRefiner;
- const TopologyRefiner *refiner = (const TopologyRefiner *)topology_refiner;
+ const TopologyRefiner *refiner = topology_refiner->osd_refiner;
const TopologyLevel &base_level = refiner->GetLevel(0);
return base_level.GetFaceVertices(face).size();
}
@@ -597,10 +652,11 @@ int openSubdiv_topologyRefnerCompareConverter(
const OpenSubdiv_TopologyRefinerDescr *topology_refiner,
OpenSubdiv_Converter *converter)
{
+ typedef OpenSubdiv::Sdc::Options Options;
using OpenSubdiv::Far::ConstIndexArray;
using OpenSubdiv::Far::TopologyRefiner;
using OpenSubdiv::Far::TopologyLevel;
- const TopologyRefiner *refiner = (const TopologyRefiner *)topology_refiner;
+ const TopologyRefiner *refiner = topology_refiner->osd_refiner;
const TopologyLevel &base_level = refiner->GetLevel(0);
const int num_verts = base_level.GetNumVertices();
const int num_edges = base_level.GetNumEdges();
@@ -611,6 +667,12 @@ int openSubdiv_topologyRefnerCompareConverter(
if (scheme_type != refiner->GetSchemeType()) {
return false;
}
+ const Options options = refiner->GetSchemeOptions();
+ Options::FVarLinearInterpolation interp = options.GetFVarLinearInterpolation();
+ const bool subdiv_uvs = (interp != Options::FVAR_LINEAR_ALL);
+ if (converter->get_subdiv_uvs(converter) != subdiv_uvs) {
+ return false;
+ }
if (converter->get_num_verts(converter) != num_verts ||
converter->get_num_edges(converter) != num_edges ||
converter->get_num_faces(converter) != num_faces)
diff --git a/intern/opensubdiv/opensubdiv_converter_capi.h b/intern/opensubdiv/opensubdiv_converter_capi.h
index 1f09fa074d8..6eda6ae5d8a 100644
--- a/intern/opensubdiv/opensubdiv_converter_capi.h
+++ b/intern/opensubdiv/opensubdiv_converter_capi.h
@@ -47,6 +47,8 @@ typedef struct OpenSubdiv_Converter {
OpenSubdiv_SchemeType (*get_type)(const OpenSubdiv_Converter *converter);
+ bool (*get_subdiv_uvs)(const OpenSubdiv_Converter *converter);
+
int (*get_num_faces)(const OpenSubdiv_Converter *converter);
int (*get_num_edges)(const OpenSubdiv_Converter *converter);
int (*get_num_verts)(const OpenSubdiv_Converter *converter);
@@ -83,6 +85,20 @@ typedef struct OpenSubdiv_Converter {
int vert,
int *vert_faces);
+ /* Face-varying data. */
+
+ int (*get_num_uv_layers)(const OpenSubdiv_Converter *converter);
+
+ void (*precalc_uv_layer)(const OpenSubdiv_Converter *converter, int layer);
+ void (*finish_uv_layer)(const OpenSubdiv_Converter *converter);
+
+ int (*get_num_uvs)(const OpenSubdiv_Converter *converter);
+ void (*get_uvs)(const OpenSubdiv_Converter *converter, float *uvs);
+
+ int (*get_face_corner_uv_index)(const OpenSubdiv_Converter *converter,
+ int face,
+ int corner);
+
void (*free_user_data)(const OpenSubdiv_Converter *converter);
void *user_data;
} OpenSubdiv_Converter;
diff --git a/intern/opensubdiv/opensubdiv_gpu_capi.cc b/intern/opensubdiv/opensubdiv_gpu_capi.cc
index 698fdfee00f..0cf6fcfef43 100644
--- a/intern/opensubdiv/opensubdiv_gpu_capi.cc
+++ b/intern/opensubdiv/opensubdiv_gpu_capi.cc
@@ -42,11 +42,29 @@
#include <opensubdiv/osd/cpuGLVertexBuffer.h>
#include <opensubdiv/osd/cpuEvaluator.h>
+#include "MEM_guardedalloc.h"
+
+#include "opensubdiv_capi.h"
+#include "opensubdiv_topology_refiner.h"
+
using OpenSubdiv::Osd::GLMeshInterface;
extern "C" char datatoc_gpu_shader_opensubd_display_glsl[];
+/* TODO(sergey): This is bit of bad level calls :S */
+extern "C" {
+void copy_m3_m3(float m1[3][3], float m2[3][3]);
+void copy_m3_m4(float m1[3][3], float m2[4][4]);
+void adjoint_m3_m3(float m1[3][3], float m[3][3]);
+float determinant_m3_array(float m[3][3]);
+bool invert_m3_m3(float m1[3][3], float m2[3][3]);
+bool invert_m3(float m[3][3]);
+void transpose_m3(float mat[3][3]);
+}
+
#define MAX_LIGHTS 8
+#define SUPPORT_COLOR_MATERIAL
+
typedef struct Light {
float position[4];
float ambient[4];
@@ -60,6 +78,7 @@ typedef struct Light {
float spot_cutoff;
float spot_exponent;
float spot_cos_cutoff;
+ float pad, pad2;
#endif
} Light;
@@ -75,114 +94,116 @@ typedef struct Transform {
} Transform;
static bool g_use_osd_glsl = false;
-static int g_active_uv_index = -1;
+static int g_active_uv_index = 0;
static GLuint g_flat_fill_solid_program = 0;
static GLuint g_flat_fill_texture2d_program = 0;
static GLuint g_smooth_fill_solid_program = 0;
static GLuint g_smooth_fill_texture2d_program = 0;
+
+static GLuint g_flat_fill_solid_shadeless_program = 0;
+static GLuint g_flat_fill_texture2d_shadeless_program = 0;
+static GLuint g_smooth_fill_solid_shadeless_program = 0;
+static GLuint g_smooth_fill_texture2d_shadeless_program = 0;
+
static GLuint g_wireframe_program = 0;
static GLuint g_lighting_ub = 0;
static Lighting g_lighting_data;
static Transform g_transform;
-/* TODO(sergey): This is actually duplicated code from BLI. */
-namespace {
-void copy_m3_m3(float m1[3][3], float m2[3][3])
-{
- /* destination comes first: */
- memcpy(&m1[0], &m2[0], 9 * sizeof(float));
-}
-
-void copy_m3_m4(float m1[3][3], float m2[4][4])
-{
- m1[0][0] = m2[0][0];
- m1[0][1] = m2[0][1];
- m1[0][2] = m2[0][2];
-
- m1[1][0] = m2[1][0];
- m1[1][1] = m2[1][1];
- m1[1][2] = m2[1][2];
-
- m1[2][0] = m2[2][0];
- m1[2][1] = m2[2][1];
- m1[2][2] = m2[2][2];
-}
-
-void adjoint_m3_m3(float m1[3][3], float m[3][3])
-{
- m1[0][0] = m[1][1] * m[2][2] - m[1][2] * m[2][1];
- m1[0][1] = -m[0][1] * m[2][2] + m[0][2] * m[2][1];
- m1[0][2] = m[0][1] * m[1][2] - m[0][2] * m[1][1];
-
- m1[1][0] = -m[1][0] * m[2][2] + m[1][2] * m[2][0];
- m1[1][1] = m[0][0] * m[2][2] - m[0][2] * m[2][0];
- m1[1][2] = -m[0][0] * m[1][2] + m[0][2] * m[1][0];
-
- m1[2][0] = m[1][0] * m[2][1] - m[1][1] * m[2][0];
- m1[2][1] = -m[0][0] * m[2][1] + m[0][1] * m[2][0];
- m1[2][2] = m[0][0] * m[1][1] - m[0][1] * m[1][0];
-}
-
-float determinant_m3_array(float m[3][3])
+struct OpenSubdiv_GLMeshFVarData
{
- return (m[0][0] * (m[1][1] * m[2][2] - m[1][2] * m[2][1]) -
- m[1][0] * (m[0][1] * m[2][2] - m[0][2] * m[2][1]) +
- m[2][0] * (m[0][1] * m[1][2] - m[0][2] * m[1][1]));
-}
-
-bool invert_m3_m3(float m1[3][3], float m2[3][3])
-{
- float det;
- int a, b;
- bool success;
-
- /* calc adjoint */
- adjoint_m3_m3(m1, m2);
+ OpenSubdiv_GLMeshFVarData() :
+ texture_buffer(0) {
+ }
- /* then determinant old matrix! */
- det = determinant_m3_array(m2);
+ ~OpenSubdiv_GLMeshFVarData()
+ {
+ Release();
+ }
- success = (det != 0.0f);
+ void Release()
+ {
+ if (texture_buffer) {
+ glDeleteTextures(1, &texture_buffer);
+ }
+ if (offset_buffer) {
+ glDeleteTextures(1, &offset_buffer);
+ }
+ texture_buffer = 0;
+ offset_buffer = 0;
+ fvar_width = 0;
+ channel_offsets.clear();
+ }
- if (det != 0.0f) {
- det = 1.0f / det;
- for (a = 0; a < 3; a++) {
- for (b = 0; b < 3; b++) {
- m1[a][b] *= det;
+ void Create(const OpenSubdiv::Far::TopologyRefiner *refiner,
+ const OpenSubdiv::Far::PatchTable *patch_table,
+ int fvar_width,
+ const float *fvar_src_data)
+ {
+ Release();
+
+ this->fvar_width = fvar_width;
+
+ /* Expand fvar data to per-patch array */
+ const int max_level = refiner->GetMaxLevel();
+ const int num_channels = patch_table->GetNumFVarChannels();
+ std::vector<float> data;
+ int fvar_data_offset = 0;
+ channel_offsets.resize(num_channels);
+ for (int channel = 0; channel < num_channels; ++channel) {
+ OpenSubdiv::Far::ConstIndexArray indices =
+ patch_table->GetFVarValues(channel);
+
+ channel_offsets[channel] = data.size();
+ data.reserve(data.size() + indices.size() * fvar_width);
+
+ for (int fvert = 0; fvert < (int)indices.size(); ++fvert) {
+ int index = indices[fvert] * fvar_width;
+ for (int i = 0; i < fvar_width; ++i) {
+ data.push_back(fvar_src_data[fvar_data_offset + index++]);
+ }
+ }
+ if (refiner->IsUniform()) {
+ const int num_values_max = refiner->GetLevel(max_level).GetNumFVarValues(channel);
+ fvar_data_offset += num_values_max * fvar_width;
+ } else {
+ const int num_values_total = refiner->GetNumFVarValuesTotal(channel);
+ fvar_data_offset += num_values_total * fvar_width;
}
}
- }
- return success;
-}
+ GLuint buffer;
+ glGenBuffers(1, &buffer);
+ glBindBuffer(GL_ARRAY_BUFFER, buffer);
+ glBufferData(GL_ARRAY_BUFFER, data.size()*sizeof(float),
+ &data[0], GL_STATIC_DRAW);
-bool invert_m3(float m[3][3])
-{
- float tmp[3][3];
- bool success;
+ glGenTextures(1, &texture_buffer);
+ glBindTexture(GL_TEXTURE_BUFFER, texture_buffer);
+ glTexBuffer(GL_TEXTURE_BUFFER, GL_R32F, buffer);
- success = invert_m3_m3(tmp, m);
- copy_m3_m3(m, tmp);
+ glDeleteBuffers(1, &buffer);
- return success;
-}
+ glGenBuffers(1, &buffer);
+ glBindBuffer(GL_ARRAY_BUFFER, buffer);
+ glBufferData(GL_ARRAY_BUFFER, channel_offsets.size()*sizeof(int),
+ &channel_offsets[0], GL_STATIC_DRAW);
-void transpose_m3(float mat[3][3])
-{
- float t;
-
- t = mat[0][1];
- mat[0][1] = mat[1][0];
- mat[1][0] = t;
- t = mat[0][2];
- mat[0][2] = mat[2][0];
- mat[2][0] = t;
- t = mat[1][2];
- mat[1][2] = mat[2][1];
- mat[2][1] = t;
-}
+ glGenTextures(1, &offset_buffer);
+ glBindTexture(GL_TEXTURE_BUFFER, offset_buffer);
+ glTexBuffer(GL_TEXTURE_BUFFER, GL_R32I, buffer);
+ glBindTexture(GL_TEXTURE_BUFFER, 0);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ }
+ GLuint texture_buffer;
+ GLuint offset_buffer;
+ std::vector<int> channel_offsets;
+ int fvar_width;
+};
+
+namespace {
GLuint compileShader(GLenum shaderType,
const char *section,
@@ -196,11 +217,14 @@ GLuint compileShader(GLenum shaderType,
version,
define,
sdefine,
+#ifdef SUPPORT_COLOR_MATERIAL
+ "#define SUPPORT_COLOR_MATERIAL\n",
+#endif
datatoc_gpu_shader_opensubd_display_glsl
};
GLuint shader = glCreateShader(shaderType);
- glShaderSource(shader, 4, sources, NULL);
+ glShaderSource(shader, 5, sources, NULL);
glCompileShader(shader);
GLint status;
@@ -295,14 +319,17 @@ GLuint linkProgram(const char *version, const char *define)
0); /* GL_TEXTURE0 */
glProgramUniform1i(program,
+ glGetUniformLocation(program, "FVarDataOffsetBuffer"),
+ 30); /* GL_TEXTURE30 */
+
+ glProgramUniform1i(program,
glGetUniformLocation(program, "FVarDataBuffer"),
31); /* GL_TEXTURE31 */
return program;
}
-void bindProgram(GLMeshInterface * /*mesh*/,
- int program)
+void bindProgram(OpenSubdiv_GLMesh *gl_mesh, int program)
{
glUseProgram(program);
@@ -346,23 +373,34 @@ void bindProgram(GLMeshInterface * /*mesh*/,
glUniform4fv(glGetUniformLocation(program, "diffuse"), 1, color);
}
- /* TODO(sergey): Bring face varying back. */
-#if 0
/* Face-vertex data */
- if (mesh->GetDrawContext()->GetFvarDataTextureBuffer()) {
- glActiveTexture(GL_TEXTURE31);
- glBindTexture(GL_TEXTURE_BUFFER,
- mesh->GetDrawContext()->GetFvarDataTextureBuffer());
- glActiveTexture(GL_TEXTURE0);
- }
-#endif
+ if (gl_mesh->fvar_data != NULL) {
+ if (gl_mesh->fvar_data->texture_buffer) {
+ glActiveTexture(GL_TEXTURE31);
+ glBindTexture(GL_TEXTURE_BUFFER, gl_mesh->fvar_data->texture_buffer);
+ glActiveTexture(GL_TEXTURE0);
+ }
- /* TODO(sergey): Bring face varying back. */
- glUniform1i(glGetUniformLocation(program, "osd_fvar_count"),
- 0/* * mesh->GetFVarCount()*/);
+ if (gl_mesh->fvar_data->offset_buffer) {
+ glActiveTexture(GL_TEXTURE30);
+ glBindTexture(GL_TEXTURE_BUFFER, gl_mesh->fvar_data->offset_buffer);
+ glActiveTexture(GL_TEXTURE0);
+ }
- glUniform1i(glGetUniformLocation(program, "osd_active_uv_offset"),
- g_active_uv_index * 2);
+ glUniform1i(glGetUniformLocation(program, "osd_fvar_count"),
+ gl_mesh->fvar_data->fvar_width);
+ if (gl_mesh->fvar_data->channel_offsets.size() > 0 &&
+ g_active_uv_index >= 0)
+ {
+ glUniform1i(glGetUniformLocation(program, "osd_active_uv_offset"),
+ gl_mesh->fvar_data->channel_offsets[g_active_uv_index]);
+ } else {
+ glUniform1i(glGetUniformLocation(program, "osd_active_uv_offset"), 0);
+ }
+ } else {
+ glUniform1i(glGetUniformLocation(program, "osd_fvar_count"), 0);
+ glUniform1i(glGetUniformLocation(program, "osd_active_uv_offset"), 0);
+ }
}
} /* namespace */
@@ -390,11 +428,51 @@ bool openSubdiv_osdGLDisplayInit(void)
/* minimum supported for OpenSubdiv */
}
- g_flat_fill_solid_program = linkProgram(version, "#define FLAT_SHADING\n");
- g_flat_fill_texture2d_program = linkProgram(version, "#define USE_TEXTURE_2D\n#define FLAT_SHADING\n");
- g_smooth_fill_solid_program = linkProgram(version, "#define SMOOTH_SHADING\n");
- g_smooth_fill_texture2d_program = linkProgram(version, "#define USE_TEXTURE_2D\n#define SMOOTH_SHADING\n");
- g_wireframe_program = linkProgram(version, "#define WIREFRAME\n");
+ g_flat_fill_solid_program = linkProgram(
+ version,
+ "#define USE_COLOR_MATERIAL\n"
+ "#define USE_LIGHTING\n"
+ "#define FLAT_SHADING\n");
+ g_flat_fill_texture2d_program = linkProgram(
+ version,
+ "#define USE_COLOR_MATERIAL\n"
+ "#define USE_LIGHTING\n"
+ "#define USE_TEXTURE_2D\n"
+ "#define FLAT_SHADING\n");
+ g_smooth_fill_solid_program = linkProgram(
+ version,
+ "#define USE_COLOR_MATERIAL\n"
+ "#define USE_LIGHTING\n"
+ "#define SMOOTH_SHADING\n");
+ g_smooth_fill_texture2d_program = linkProgram(
+ version,
+ "#define USE_COLOR_MATERIAL\n"
+ "#define USE_LIGHTING\n"
+ "#define USE_TEXTURE_2D\n"
+ "#define SMOOTH_SHADING\n");
+
+ g_flat_fill_solid_shadeless_program = linkProgram(
+ version,
+ "#define USE_COLOR_MATERIAL\n"
+ "#define FLAT_SHADING\n");
+ g_flat_fill_texture2d_shadeless_program = linkProgram(
+ version,
+ "#define USE_COLOR_MATERIAL\n"
+ "#define USE_TEXTURE_2D\n"
+ "#define FLAT_SHADING\n");
+ g_smooth_fill_solid_shadeless_program = linkProgram(
+ version,
+ "#define USE_COLOR_MATERIAL\n"
+ "#define SMOOTH_SHADING\n");
+ g_smooth_fill_texture2d_shadeless_program = linkProgram(
+ version,
+ "#define USE_COLOR_MATERIAL\n"
+ "#define USE_TEXTURE_2D\n"
+ "#define SMOOTH_SHADING\n");
+
+ g_wireframe_program = linkProgram(
+ version,
+ "#define WIREFRAME\n");
glGenBuffers(1, &g_lighting_ub);
glBindBuffer(GL_UNIFORM_BUFFER, g_lighting_ub);
@@ -416,28 +494,31 @@ void openSubdiv_osdGLDisplayDeinit(void)
if (g_lighting_ub != 0) {
glDeleteBuffers(1, &g_lighting_ub);
}
- if (g_flat_fill_solid_program) {
- glDeleteProgram(g_flat_fill_solid_program);
- }
- if (g_flat_fill_texture2d_program) {
- glDeleteProgram(g_flat_fill_texture2d_program);
- }
- if (g_smooth_fill_solid_program) {
- glDeleteProgram(g_flat_fill_solid_program);
- }
- if (g_smooth_fill_texture2d_program) {
- glDeleteProgram(g_smooth_fill_texture2d_program);
- }
- if (g_wireframe_program) {
- glDeleteProgram(g_wireframe_program);
- }
+#define SAFE_DELETE_PROGRAM(program) \
+ do { \
+ if (program) { \
+ glDeleteProgram(program); \
+ } \
+ } while (false)
+
+ SAFE_DELETE_PROGRAM(g_flat_fill_solid_program);
+ SAFE_DELETE_PROGRAM(g_flat_fill_texture2d_program);
+ SAFE_DELETE_PROGRAM(g_smooth_fill_solid_program);
+ SAFE_DELETE_PROGRAM(g_smooth_fill_texture2d_program);
+ SAFE_DELETE_PROGRAM(g_flat_fill_solid_shadeless_program);
+ SAFE_DELETE_PROGRAM(g_flat_fill_texture2d_shadeless_program);
+ SAFE_DELETE_PROGRAM(g_smooth_fill_solid_shadeless_program);
+ SAFE_DELETE_PROGRAM(g_smooth_fill_texture2d_shadeless_program);
+ SAFE_DELETE_PROGRAM(g_wireframe_program);
+
+#undef SAFE_DELETE_PROGRAM
}
void openSubdiv_osdGLMeshDisplayPrepare(int use_osd_glsl,
int active_uv_index)
{
- g_use_osd_glsl = use_osd_glsl != 0;
g_active_uv_index = active_uv_index;
+ g_use_osd_glsl = (use_osd_glsl != 0);
/* Update transformation matrices. */
glGetFloatv(GL_PROJECTION_MATRIX, g_transform.projection_matrix);
@@ -494,7 +575,7 @@ void openSubdiv_osdGLMeshDisplayPrepare(int use_osd_glsl,
}
}
-static GLuint prepare_patchDraw(GLMeshInterface *mesh,
+static GLuint prepare_patchDraw(OpenSubdiv_GLMesh *gl_mesh,
bool fill_quads)
{
GLint program = 0;
@@ -509,51 +590,74 @@ static GLuint prepare_patchDraw(GLMeshInterface *mesh,
glUniform1i(location, model == GL_FLAT);
}
- /* TODO(sergey): Bring this back. */
-#if 0
/* Face-vertex data */
- if (mesh->GetDrawContext()->GetFvarDataTextureBuffer()) {
- glActiveTexture(GL_TEXTURE31);
- glBindTexture(GL_TEXTURE_BUFFER,
- mesh->GetDrawContext()->GetFvarDataTextureBuffer());
- glActiveTexture(GL_TEXTURE0);
+ if (gl_mesh->fvar_data != NULL) {
+ if (gl_mesh->fvar_data->texture_buffer) {
+ glActiveTexture(GL_TEXTURE31);
+ glBindTexture(GL_TEXTURE_BUFFER,
+ gl_mesh->fvar_data->texture_buffer);
+ glActiveTexture(GL_TEXTURE0);
+ }
+
+ if (gl_mesh->fvar_data->offset_buffer) {
+ glActiveTexture(GL_TEXTURE30);
+ glBindTexture(GL_TEXTURE_BUFFER,
+ gl_mesh->fvar_data->offset_buffer);
+ glActiveTexture(GL_TEXTURE0);
+ }
GLint location = glGetUniformLocation(program, "osd_fvar_count");
if (location != -1) {
- glUniform1i(location, mesh->GetFVarCount());
+ glUniform1i(location, gl_mesh->fvar_data->fvar_width);
}
location = glGetUniformLocation(program, "osd_active_uv_offset");
if (location != -1) {
- glUniform1i(location,
- g_active_uv_index * 2);
+ if (gl_mesh->fvar_data->channel_offsets.size() > 0 &&
+ g_active_uv_index >= 0)
+ {
+ glUniform1i(location,
+ gl_mesh->fvar_data->channel_offsets[g_active_uv_index]);
+ } else {
+ glUniform1i(location, 0);
+ }
}
+ } else {
+ glUniform1i(glGetUniformLocation(program, "osd_fvar_count"), 0);
+ glUniform1i(glGetUniformLocation(program, "osd_active_uv_offset"), 0);
}
-#endif
-
}
return program;
}
if (fill_quads) {
int model;
- GLboolean use_texture_2d;
+ GLboolean use_texture_2d, use_lighting;
glGetIntegerv(GL_SHADE_MODEL, &model);
glGetBooleanv(GL_TEXTURE_2D, &use_texture_2d);
+ glGetBooleanv(GL_LIGHTING, &use_lighting);
if (model == GL_FLAT) {
if (use_texture_2d) {
- program = g_flat_fill_texture2d_program;
+ program = use_lighting
+ ? g_flat_fill_texture2d_program
+ : g_flat_fill_texture2d_shadeless_program;
}
else {
- program = g_flat_fill_solid_program;
+ program = use_lighting
+ ? g_flat_fill_solid_program
+ : g_flat_fill_solid_shadeless_program;
}
}
else {
if (use_texture_2d) {
- program = g_smooth_fill_texture2d_program;
+ program = use_lighting
+ ? g_smooth_fill_texture2d_program
+ : g_smooth_fill_texture2d_shadeless_program;
}
else {
- program = g_smooth_fill_solid_program;
+ program = use_lighting
+ ? g_smooth_fill_solid_program
+ : g_smooth_fill_solid_shadeless_program;
}
}
}
@@ -562,7 +666,7 @@ static GLuint prepare_patchDraw(GLMeshInterface *mesh,
program = g_wireframe_program;
}
- bindProgram(mesh, program);
+ bindProgram(gl_mesh, program);
return program;
}
@@ -623,7 +727,7 @@ static void draw_partition_patches_range(GLMeshInterface *mesh,
const int num_draw_patches = std::min(num_remained_patches,
num_block_patches - start_draw_patch);
perform_drawElements(program,
- i,
+ i + start_draw_patch,
num_draw_patches * num_control_verts,
patch.GetIndexBase() + start_draw_patch * num_control_verts);
num_remained_patches -= num_draw_patches;
@@ -669,7 +773,7 @@ void openSubdiv_osdGLMeshDisplay(OpenSubdiv_GLMesh *gl_mesh,
}
/* Setup GLSL/OpenGL to draw patches in current context. */
- GLuint program = prepare_patchDraw(mesh, fill_quads != 0);
+ GLuint program = prepare_patchDraw(gl_mesh, fill_quads != 0);
if (start_patch != -1) {
draw_partition_patches_range(mesh,
@@ -684,3 +788,23 @@ void openSubdiv_osdGLMeshDisplay(OpenSubdiv_GLMesh *gl_mesh,
/* Finish patch drawing by restoring all changes to the OpenGL context. */
finish_patchDraw(fill_quads != 0);
}
+
+void openSubdiv_osdGLAllocFVar(OpenSubdiv_TopologyRefinerDescr *topology_refiner,
+ OpenSubdiv_GLMesh *gl_mesh,
+ const float *fvar_data)
+{
+ GLMeshInterface *mesh =
+ (GLMeshInterface *)(gl_mesh->descriptor);
+ gl_mesh->fvar_data = OBJECT_GUARDED_NEW(OpenSubdiv_GLMeshFVarData);
+ gl_mesh->fvar_data->Create(topology_refiner->osd_refiner,
+ mesh->GetFarPatchTable(),
+ 2,
+ fvar_data);
+}
+
+void openSubdiv_osdGLDestroyFVar(OpenSubdiv_GLMesh *gl_mesh)
+{
+ if (gl_mesh->fvar_data != NULL) {
+ OBJECT_GUARDED_DELETE(gl_mesh->fvar_data, OpenSubdiv_GLMeshFVarData);
+ }
+}
diff --git a/intern/opensubdiv/opensubdiv_topology_refiner.h b/intern/opensubdiv/opensubdiv_topology_refiner.h
new file mode 100644
index 00000000000..b00f6a54201
--- /dev/null
+++ b/intern/opensubdiv/opensubdiv_topology_refiner.h
@@ -0,0 +1,41 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2016 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Sergey Sharybin.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __OPENSUBDIV_TOPOLOGY_REFINER_H__
+#define __OPENSUBDIV_TOPOLOGY_REFINER_H__
+
+#include <opensubdiv/far/topologyRefiner.h>
+
+typedef struct OpenSubdiv_TopologyRefinerDescr {
+ OpenSubdiv::Far::TopologyRefiner *osd_refiner;
+
+ /* TODO(sergey): For now only, need to find better place
+ * after revisiting whole OSD drawing pipeline and Blender
+ * integration.
+ */
+ std::vector<float> uvs;
+} OpenSubdiv_TopologyRefinerDescr;
+
+#endif /* __OPENSUBDIV_TOPOLOGY_REFINER_H__ */