diff options
Diffstat (limited to 'intern')
121 files changed, 1770 insertions, 1547 deletions
diff --git a/intern/cycles/blender/python.cpp b/intern/cycles/blender/python.cpp index 8b2b331f73e..1e33b0b7207 100644 --- a/intern/cycles/blender/python.cpp +++ b/intern/cycles/blender/python.cpp @@ -59,8 +59,6 @@ static void debug_flags_sync_from_scene(BL::Scene b_scene) { DebugFlagsRef flags = DebugFlags(); PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles"); - /* Synchronize shared flags. */ - flags.viewport_static_bvh = get_enum(cscene, "debug_bvh_type"); /* Synchronize CPU flags. */ flags.cpu.avx2 = get_boolean(cscene, "debug_use_cpu_avx2"); flags.cpu.avx = get_boolean(cscene, "debug_use_cpu_avx"); @@ -140,8 +138,6 @@ static PyObject *init_func(PyObject * /*self*/, PyObject *args) BlenderSession::headless = headless; - DebugFlags().running_inside_blender = true; - Py_RETURN_NONE; } diff --git a/intern/cycles/blender/session.cpp b/intern/cycles/blender/session.cpp index 6d27b8e7d87..e1da85b84ff 100644 --- a/intern/cycles/blender/session.cpp +++ b/intern/cycles/blender/session.cpp @@ -110,7 +110,8 @@ void BlenderSession::create_session() { const SessionParams session_params = BlenderSync::get_session_params( b_engine, b_userpref, b_scene, background); - const SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background); + const SceneParams scene_params = BlenderSync::get_scene_params( + b_scene, background, use_developer_ui); const bool session_pause = BlenderSync::get_session_pause(b_scene, background); /* reset status/progress */ @@ -196,7 +197,8 @@ void BlenderSession::reset_session(BL::BlendData &b_data, BL::Depsgraph &b_depsg const SessionParams session_params = BlenderSync::get_session_params( b_engine, b_userpref, b_scene, background); - const SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background); + const SceneParams scene_params = BlenderSync::get_scene_params( + b_scene, background, use_developer_ui); if (scene->params.modified(scene_params) || session->params.modified(session_params) || !this->b_render.use_persistent_data()) { @@ -724,7 +726,8 @@ void BlenderSession::synchronize(BL::Depsgraph &b_depsgraph_) /* on session/scene parameter changes, we recreate session entirely */ const SessionParams session_params = BlenderSync::get_session_params( b_engine, b_userpref, b_scene, background); - const SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background); + const SceneParams scene_params = BlenderSync::get_scene_params( + b_scene, background, use_developer_ui); const bool session_pause = BlenderSync::get_session_pause(b_scene, background); if (session->params.modified(session_params) || scene->params.modified(scene_params)) { diff --git a/intern/cycles/blender/sync.cpp b/intern/cycles/blender/sync.cpp index 429a8e665af..0d4c1d70180 100644 --- a/intern/cycles/blender/sync.cpp +++ b/intern/cycles/blender/sync.cpp @@ -801,7 +801,9 @@ void BlenderSync::free_data_after_sync(BL::Depsgraph &b_depsgraph) /* Scene Parameters */ -SceneParams BlenderSync::get_scene_params(BL::Scene &b_scene, bool background) +SceneParams BlenderSync::get_scene_params(BL::Scene &b_scene, + const bool background, + const bool use_developer_ui) { SceneParams params; PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles"); @@ -812,7 +814,7 @@ SceneParams BlenderSync::get_scene_params(BL::Scene &b_scene, bool background) else if (shadingsystem == 1) params.shadingsystem = SHADINGSYSTEM_OSL; - if (background || DebugFlags().viewport_static_bvh) + if (background || (use_developer_ui && get_enum(cscene, "debug_bvh_type"))) params.bvh_type = BVH_TYPE_STATIC; else params.bvh_type = BVH_TYPE_DYNAMIC; diff --git a/intern/cycles/blender/sync.h b/intern/cycles/blender/sync.h index 0ad4ca6fe83..ae6c2420e55 100644 --- a/intern/cycles/blender/sync.h +++ b/intern/cycles/blender/sync.h @@ -84,7 +84,9 @@ class BlenderSync { } /* get parameters */ - static SceneParams get_scene_params(BL::Scene &b_scene, bool background); + static SceneParams get_scene_params(BL::Scene &b_scene, + const bool background, + const bool use_developer_ui); static SessionParams get_session_params(BL::RenderEngine &b_engine, BL::Preferences &b_userpref, BL::Scene &b_scene, diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index b00515eb037..fbc30234dac 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -343,6 +343,7 @@ set(SRC_UTIL_HEADERS ../util/types_int3_impl.h ../util/types_int4.h ../util/types_int4_impl.h + ../util/types_spectrum.h ../util/types_uchar2.h ../util/types_uchar2_impl.h ../util/types_uchar3.h @@ -356,8 +357,6 @@ set(SRC_UTIL_HEADERS ../util/types_uint4.h ../util/types_uint4_impl.h ../util/types_ushort4.h - ../util/types_vector3.h - ../util/types_vector3_impl.h ) set(LIB diff --git a/intern/cycles/kernel/bake/bake.h b/intern/cycles/kernel/bake/bake.h index ec87990b699..9d53d71b431 100644 --- a/intern/cycles/kernel/bake/bake.h +++ b/intern/cycles/kernel/bake/bake.h @@ -8,6 +8,8 @@ #include "kernel/geom/geom.h" +#include "kernel/util/color.h" + CCL_NAMESPACE_BEGIN ccl_device void kernel_displace_evaluate(KernelGlobals kg, @@ -65,7 +67,7 @@ ccl_device void kernel_background_evaluate(KernelGlobals kg, shader_eval_surface<KERNEL_FEATURE_NODE_MASK_SURFACE_LIGHT & ~(KERNEL_FEATURE_NODE_RAYTRACE | KERNEL_FEATURE_NODE_LIGHT_PATH)>( kg, INTEGRATOR_STATE_NULL, &sd, NULL, path_flag); - float3 color = shader_background_eval(&sd); + Spectrum color = shader_background_eval(&sd); #ifdef __KERNEL_DEBUG_NAN__ if (!isfinite_safe(color)) { @@ -76,10 +78,12 @@ ccl_device void kernel_background_evaluate(KernelGlobals kg, /* Ensure finite color, avoiding possible numerical instabilities in the path tracing kernels. */ color = ensure_finite(color); + float3 color_rgb = spectrum_to_rgb(color); + /* Write output. */ - output[offset * 3 + 0] += color.x; - output[offset * 3 + 1] += color.y; - output[offset * 3 + 2] += color.z; + output[offset * 3 + 0] += color_rgb.x; + output[offset * 3 + 1] += color_rgb.y; + output[offset * 3 + 2] += color_rgb.z; } ccl_device void kernel_curve_shadow_transparency_evaluate( diff --git a/intern/cycles/kernel/closure/alloc.h b/intern/cycles/kernel/closure/alloc.h index 933c07a5102..9847898ee89 100644 --- a/intern/cycles/kernel/closure/alloc.h +++ b/intern/cycles/kernel/closure/alloc.h @@ -8,7 +8,7 @@ CCL_NAMESPACE_BEGIN ccl_device ccl_private ShaderClosure *closure_alloc(ccl_private ShaderData *sd, int size, ClosureType type, - float3 weight) + Spectrum weight) { kernel_assert(size <= sizeof(ShaderClosure)); @@ -49,7 +49,7 @@ ccl_device ccl_private void *closure_alloc_extra(ccl_private ShaderData *sd, int ccl_device_inline ccl_private ShaderClosure *bsdf_alloc(ccl_private ShaderData *sd, int size, - float3 weight) + Spectrum weight) { kernel_assert(isfinite_safe(weight)); @@ -74,7 +74,7 @@ ccl_device_inline ccl_private ShaderClosure *bsdf_alloc(ccl_private ShaderData * #ifdef __OSL__ ccl_device_inline ShaderClosure *bsdf_alloc_osl(ShaderData *sd, int size, - float3 weight, + Spectrum weight, void *data) { kernel_assert(isfinite_safe(weight)); diff --git a/intern/cycles/kernel/closure/bsdf.h b/intern/cycles/kernel/closure/bsdf.h index 4feb21c43e3..7b28018afad 100644 --- a/intern/cycles/kernel/closure/bsdf.h +++ b/intern/cycles/kernel/closure/bsdf.h @@ -103,7 +103,7 @@ ccl_device_inline int bsdf_sample(KernelGlobals kg, ccl_private const ShaderClosure *sc, float randu, float randv, - ccl_private float3 *eval, + ccl_private Spectrum *eval, ccl_private float3 *omega_in, ccl_private differential3 *domega_in, ccl_private float *pdf) @@ -458,7 +458,7 @@ ccl_device #else ccl_device_inline #endif - float3 + Spectrum bsdf_eval(KernelGlobals kg, ccl_private ShaderData *sd, ccl_private const ShaderClosure *sc, @@ -466,7 +466,7 @@ ccl_device_inline const bool is_transmission, ccl_private float *pdf) { - float3 eval = zero_float3(); + Spectrum eval = zero_spectrum(); if (!is_transmission) { switch (sc->type) { diff --git a/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h b/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h index 47066542122..2f6ac2dceb0 100644 --- a/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h +++ b/intern/cycles/kernel/closure/bsdf_ashikhmin_shirley.h @@ -39,7 +39,7 @@ ccl_device_inline float bsdf_ashikhmin_shirley_roughness_to_exponent(float rough return 2.0f / (roughness * roughness) - 2.0f; } -ccl_device_forceinline float3 +ccl_device_forceinline Spectrum bsdf_ashikhmin_shirley_eval_reflect(ccl_private const ShaderClosure *sc, const float3 I, const float3 omega_in, @@ -55,7 +55,7 @@ bsdf_ashikhmin_shirley_eval_reflect(ccl_private const ShaderClosure *sc, if (fmaxf(bsdf->alpha_x, bsdf->alpha_y) <= 1e-4f) { *pdf = 0.0f; - return make_float3(0.0f, 0.0f, 0.0f); + return zero_spectrum(); } if (NdotI > 0.0f && NdotO > 0.0f) { NdotI = fmaxf(NdotI, 1e-6f); @@ -105,16 +105,16 @@ bsdf_ashikhmin_shirley_eval_reflect(ccl_private const ShaderClosure *sc, } } - return make_float3(out, out, out); + return make_spectrum(out); } -ccl_device float3 bsdf_ashikhmin_shirley_eval_transmit(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) +ccl_device Spectrum bsdf_ashikhmin_shirley_eval_transmit(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) { *pdf = 0.0f; - return make_float3(0.0f, 0.0f, 0.0f); + return zero_spectrum(); } ccl_device_inline void bsdf_ashikhmin_shirley_sample_first_quadrant(float n_x, @@ -137,7 +137,7 @@ ccl_device int bsdf_ashikhmin_shirley_sample(ccl_private const ShaderClosure *sc float3 dIdy, float randu, float randv, - ccl_private float3 *eval, + ccl_private Spectrum *eval, ccl_private float3 *omega_in, ccl_private float3 *domega_in_dx, ccl_private float3 *domega_in_dy, @@ -214,7 +214,7 @@ ccl_device int bsdf_ashikhmin_shirley_sample(ccl_private const ShaderClosure *sc if (fmaxf(bsdf->alpha_x, bsdf->alpha_y) <= 1e-4f) { /* Some high number for MIS. */ *pdf = 1e6f; - *eval = make_float3(1e6f, 1e6f, 1e6f); + *eval = make_spectrum(1e6f); label = LABEL_REFLECT | LABEL_SINGULAR; } else { diff --git a/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h b/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h index 3d7906eef7d..ee58bd50aa1 100644 --- a/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h +++ b/intern/cycles/kernel/closure/bsdf_ashikhmin_velvet.h @@ -31,10 +31,10 @@ ccl_device int bsdf_ashikhmin_velvet_setup(ccl_private VelvetBsdf *bsdf) return SD_BSDF | SD_BSDF_HAS_EVAL; } -ccl_device float3 bsdf_ashikhmin_velvet_eval_reflect(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) +ccl_device Spectrum bsdf_ashikhmin_velvet_eval_reflect(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) { ccl_private const VelvetBsdf *bsdf = (ccl_private const VelvetBsdf *)sc; float m_invsigma2 = bsdf->invsigma2; @@ -50,7 +50,7 @@ ccl_device float3 bsdf_ashikhmin_velvet_eval_reflect(ccl_private const ShaderClo if (!(fabsf(cosNH) < 1.0f - 1e-5f && cosHO > 1e-5f)) { *pdf = 0.0f; - return make_float3(0.0f, 0.0f, 0.0f); + return zero_spectrum(); } float cosNHdivHO = cosNH / cosHO; cosNHdivHO = fmaxf(cosNHdivHO, 1e-5f); @@ -68,20 +68,20 @@ ccl_device float3 bsdf_ashikhmin_velvet_eval_reflect(ccl_private const ShaderClo float out = 0.25f * (D * G) / cosNO; *pdf = 0.5f * M_1_PI_F; - return make_float3(out, out, out); + return make_spectrum(out); } *pdf = 0.0f; - return make_float3(0.0f, 0.0f, 0.0f); + return zero_spectrum(); } -ccl_device float3 bsdf_ashikhmin_velvet_eval_transmit(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) +ccl_device Spectrum bsdf_ashikhmin_velvet_eval_transmit(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) { *pdf = 0.0f; - return make_float3(0.0f, 0.0f, 0.0f); + return zero_spectrum(); } ccl_device int bsdf_ashikhmin_velvet_sample(ccl_private const ShaderClosure *sc, @@ -91,7 +91,7 @@ ccl_device int bsdf_ashikhmin_velvet_sample(ccl_private const ShaderClosure *sc, float3 dIdy, float randu, float randv, - ccl_private float3 *eval, + ccl_private Spectrum *eval, ccl_private float3 *omega_in, ccl_private float3 *domega_in_dx, ccl_private float3 *domega_in_dy, @@ -129,7 +129,7 @@ ccl_device int bsdf_ashikhmin_velvet_sample(ccl_private const ShaderClosure *sc, float power = 0.25f * (D * G) / cosNO; - *eval = make_float3(power, power, power); + *eval = make_spectrum(power); #ifdef __RAY_DIFFERENTIALS__ // TODO: find a better approximation for the retroreflective bounce @@ -139,12 +139,12 @@ ccl_device int bsdf_ashikhmin_velvet_sample(ccl_private const ShaderClosure *sc, } else { *pdf = 0.0f; - *eval = make_float3(0.0f, 0.0f, 0.0f); + *eval = zero_spectrum(); } } else { *pdf = 0.0f; - *eval = make_float3(0.0f, 0.0f, 0.0f); + *eval = zero_spectrum(); } return LABEL_REFLECT | LABEL_DIFFUSE; } diff --git a/intern/cycles/kernel/closure/bsdf_diffuse.h b/intern/cycles/kernel/closure/bsdf_diffuse.h index 759ad03f8e8..2a082796043 100644 --- a/intern/cycles/kernel/closure/bsdf_diffuse.h +++ b/intern/cycles/kernel/closure/bsdf_diffuse.h @@ -26,26 +26,26 @@ ccl_device int bsdf_diffuse_setup(ccl_private DiffuseBsdf *bsdf) return SD_BSDF | SD_BSDF_HAS_EVAL; } -ccl_device float3 bsdf_diffuse_eval_reflect(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) +ccl_device Spectrum bsdf_diffuse_eval_reflect(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) { ccl_private const DiffuseBsdf *bsdf = (ccl_private const DiffuseBsdf *)sc; float3 N = bsdf->N; float cos_pi = fmaxf(dot(N, omega_in), 0.0f) * M_1_PI_F; *pdf = cos_pi; - return make_float3(cos_pi, cos_pi, cos_pi); + return make_spectrum(cos_pi); } -ccl_device float3 bsdf_diffuse_eval_transmit(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) +ccl_device Spectrum bsdf_diffuse_eval_transmit(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) { *pdf = 0.0f; - return make_float3(0.0f, 0.0f, 0.0f); + return zero_spectrum(); } ccl_device int bsdf_diffuse_sample(ccl_private const ShaderClosure *sc, @@ -55,7 +55,7 @@ ccl_device int bsdf_diffuse_sample(ccl_private const ShaderClosure *sc, float3 dIdy, float randu, float randv, - ccl_private float3 *eval, + ccl_private Spectrum *eval, ccl_private float3 *omega_in, ccl_private float3 *domega_in_dx, ccl_private float3 *domega_in_dy, @@ -68,7 +68,7 @@ ccl_device int bsdf_diffuse_sample(ccl_private const ShaderClosure *sc, sample_cos_hemisphere(N, randu, randv, omega_in, pdf); if (dot(Ng, *omega_in) > 0.0f) { - *eval = make_float3(*pdf, *pdf, *pdf); + *eval = make_spectrum(*pdf); #ifdef __RAY_DIFFERENTIALS__ // TODO: find a better approximation for the diffuse bounce *domega_in_dx = (2 * dot(N, dIdx)) * N - dIdx; @@ -77,7 +77,7 @@ ccl_device int bsdf_diffuse_sample(ccl_private const ShaderClosure *sc, } else { *pdf = 0.0f; - *eval = make_float3(0.0f, 0.0f, 0.0f); + *eval = zero_spectrum(); } return LABEL_REFLECT | LABEL_DIFFUSE; } @@ -90,26 +90,26 @@ ccl_device int bsdf_translucent_setup(ccl_private DiffuseBsdf *bsdf) return SD_BSDF | SD_BSDF_HAS_EVAL; } -ccl_device float3 bsdf_translucent_eval_reflect(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) +ccl_device Spectrum bsdf_translucent_eval_reflect(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) { *pdf = 0.0f; - return make_float3(0.0f, 0.0f, 0.0f); + return zero_spectrum(); } -ccl_device float3 bsdf_translucent_eval_transmit(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) +ccl_device Spectrum bsdf_translucent_eval_transmit(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) { ccl_private const DiffuseBsdf *bsdf = (ccl_private const DiffuseBsdf *)sc; float3 N = bsdf->N; float cos_pi = fmaxf(-dot(N, omega_in), 0.0f) * M_1_PI_F; *pdf = cos_pi; - return make_float3(cos_pi, cos_pi, cos_pi); + return make_spectrum(cos_pi); } ccl_device int bsdf_translucent_sample(ccl_private const ShaderClosure *sc, @@ -119,7 +119,7 @@ ccl_device int bsdf_translucent_sample(ccl_private const ShaderClosure *sc, float3 dIdy, float randu, float randv, - ccl_private float3 *eval, + ccl_private Spectrum *eval, ccl_private float3 *omega_in, ccl_private float3 *domega_in_dx, ccl_private float3 *domega_in_dy, @@ -132,7 +132,7 @@ ccl_device int bsdf_translucent_sample(ccl_private const ShaderClosure *sc, // distribution over the hemisphere sample_cos_hemisphere(-N, randu, randv, omega_in, pdf); if (dot(Ng, *omega_in) < 0) { - *eval = make_float3(*pdf, *pdf, *pdf); + *eval = make_spectrum(*pdf); #ifdef __RAY_DIFFERENTIALS__ // TODO: find a better approximation for the diffuse bounce *domega_in_dx = -((2 * dot(N, dIdx)) * N - dIdx); @@ -141,7 +141,7 @@ ccl_device int bsdf_translucent_sample(ccl_private const ShaderClosure *sc, } else { *pdf = 0; - *eval = make_float3(0.0f, 0.0f, 0.0f); + *eval = zero_spectrum(); } return LABEL_TRANSMIT | LABEL_DIFFUSE; } diff --git a/intern/cycles/kernel/closure/bsdf_diffuse_ramp.h b/intern/cycles/kernel/closure/bsdf_diffuse_ramp.h index aa4c091f587..8b88edb37f7 100644 --- a/intern/cycles/kernel/closure/bsdf_diffuse_ramp.h +++ b/intern/cycles/kernel/closure/bsdf_diffuse_ramp.h @@ -9,6 +9,7 @@ #pragma once #include "kernel/sample/mapping.h" +#include "kernel/util/color.h" CCL_NAMESPACE_BEGIN @@ -46,25 +47,25 @@ ccl_device void bsdf_diffuse_ramp_blur(ccl_private ShaderClosure *sc, float roug { } -ccl_device float3 bsdf_diffuse_ramp_eval_reflect(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) +ccl_device Spectrum bsdf_diffuse_ramp_eval_reflect(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) { const DiffuseRampBsdf *bsdf = (const DiffuseRampBsdf *)sc; float3 N = bsdf->N; float cos_pi = fmaxf(dot(N, omega_in), 0.0f); *pdf = cos_pi * M_1_PI_F; - return bsdf_diffuse_ramp_get_color(bsdf->colors, cos_pi) * M_1_PI_F; + return rgb_to_spectrum(bsdf_diffuse_ramp_get_color(bsdf->colors, cos_pi) * M_1_PI_F); } -ccl_device float3 bsdf_diffuse_ramp_eval_transmit(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) +ccl_device Spectrum bsdf_diffuse_ramp_eval_transmit(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) { - return make_float3(0.0f, 0.0f, 0.0f); + return zero_spectrum(); } ccl_device int bsdf_diffuse_ramp_sample(ccl_private const ShaderClosure *sc, @@ -74,7 +75,7 @@ ccl_device int bsdf_diffuse_ramp_sample(ccl_private const ShaderClosure *sc, float3 dIdy, float randu, float randv, - ccl_private float3 *eval, + ccl_private Spectrum *eval, ccl_private float3 *omega_in, ccl_private float3 *domega_in_dx, ccl_private float3 *domega_in_dy, @@ -87,7 +88,7 @@ ccl_device int bsdf_diffuse_ramp_sample(ccl_private const ShaderClosure *sc, sample_cos_hemisphere(N, randu, randv, omega_in, pdf); if (dot(Ng, *omega_in) > 0.0f) { - *eval = bsdf_diffuse_ramp_get_color(bsdf->colors, *pdf * M_PI_F) * M_1_PI_F; + *eval = rgb_to_spectrum(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,7 +96,7 @@ ccl_device int bsdf_diffuse_ramp_sample(ccl_private const ShaderClosure *sc, } else { *pdf = 0.0f; - *eval = make_float3(0.0f, 0.0f, 0.0f); + *eval = zero_spectrum(); } return LABEL_REFLECT | LABEL_DIFFUSE; } diff --git a/intern/cycles/kernel/closure/bsdf_hair.h b/intern/cycles/kernel/closure/bsdf_hair.h index a136ed05800..4179f73e22c 100644 --- a/intern/cycles/kernel/closure/bsdf_hair.h +++ b/intern/cycles/kernel/closure/bsdf_hair.h @@ -37,10 +37,10 @@ ccl_device int bsdf_hair_transmission_setup(ccl_private HairBsdf *bsdf) return SD_BSDF | SD_BSDF_HAS_EVAL; } -ccl_device float3 bsdf_hair_reflection_eval_reflect(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) +ccl_device Spectrum bsdf_hair_reflection_eval_reflect(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) { ccl_private const HairBsdf *bsdf = (ccl_private const HairBsdf *)sc; float offset = bsdf->offset; @@ -61,7 +61,7 @@ ccl_device float3 bsdf_hair_reflection_eval_reflect(ccl_private const ShaderClos if (M_PI_2_F - fabsf(theta_i) < 0.001f || cosphi_i < 0.0f) { *pdf = 0.0f; - return make_float3(*pdf, *pdf, *pdf); + return zero_spectrum(); } float roughness1_inv = 1.0f / roughness1; @@ -81,31 +81,31 @@ ccl_device float3 bsdf_hair_reflection_eval_reflect(ccl_private const ShaderClos (2 * (t * t + roughness1 * roughness1) * (a_R - b_R) * costheta_i); *pdf = phi_pdf * theta_pdf; - return make_float3(*pdf, *pdf, *pdf); + return make_spectrum(*pdf); } -ccl_device float3 bsdf_hair_transmission_eval_reflect(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) +ccl_device Spectrum bsdf_hair_transmission_eval_reflect(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) { *pdf = 0.0f; - return make_float3(0.0f, 0.0f, 0.0f); + return zero_spectrum(); } -ccl_device float3 bsdf_hair_reflection_eval_transmit(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) +ccl_device Spectrum bsdf_hair_reflection_eval_transmit(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) { *pdf = 0.0f; - return make_float3(0.0f, 0.0f, 0.0f); + return zero_spectrum(); } -ccl_device float3 bsdf_hair_transmission_eval_transmit(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) +ccl_device Spectrum bsdf_hair_transmission_eval_transmit(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) { ccl_private const HairBsdf *bsdf = (ccl_private const HairBsdf *)sc; float offset = bsdf->offset; @@ -125,7 +125,7 @@ ccl_device float3 bsdf_hair_transmission_eval_transmit(ccl_private const ShaderC if (M_PI_2_F - fabsf(theta_i) < 0.001f) { *pdf = 0.0f; - return make_float3(*pdf, *pdf, *pdf); + return zero_spectrum(); } float costheta_i = fast_cosf(theta_i); @@ -145,7 +145,7 @@ ccl_device float3 bsdf_hair_transmission_eval_transmit(ccl_private const ShaderC float phi_pdf = roughness2 / (c_TT * (p * p + roughness2 * roughness2)); *pdf = phi_pdf * theta_pdf; - return make_float3(*pdf, *pdf, *pdf); + return make_spectrum(*pdf); } ccl_device int bsdf_hair_reflection_sample(ccl_private const ShaderClosure *sc, @@ -155,7 +155,7 @@ ccl_device int bsdf_hair_reflection_sample(ccl_private const ShaderClosure *sc, float3 dIdy, float randu, float randv, - ccl_private float3 *eval, + ccl_private Spectrum *eval, ccl_private float3 *omega_in, ccl_private float3 *domega_in_dx, ccl_private float3 *domega_in_dy, @@ -204,7 +204,7 @@ ccl_device int bsdf_hair_reflection_sample(ccl_private const ShaderClosure *sc, if (M_PI_2_F - fabsf(theta_i) < 0.001f) *pdf = 0.0f; - *eval = make_float3(*pdf, *pdf, *pdf); + *eval = make_spectrum(*pdf); return LABEL_REFLECT | LABEL_GLOSSY; } @@ -216,7 +216,7 @@ ccl_device int bsdf_hair_transmission_sample(ccl_private const ShaderClosure *sc float3 dIdy, float randu, float randv, - ccl_private float3 *eval, + ccl_private Spectrum *eval, ccl_private float3 *omega_in, ccl_private float3 *domega_in_dx, ccl_private float3 *domega_in_dy, @@ -266,7 +266,7 @@ ccl_device int bsdf_hair_transmission_sample(ccl_private const ShaderClosure *sc *pdf = 0.0f; } - *eval = make_float3(*pdf, *pdf, *pdf); + *eval = make_spectrum(*pdf); /* TODO(sergey): Should always be negative, but seems some precision issue * is involved here. diff --git a/intern/cycles/kernel/closure/bsdf_hair_principled.h b/intern/cycles/kernel/closure/bsdf_hair_principled.h index e7f24b89458..f78a05ea212 100644 --- a/intern/cycles/kernel/closure/bsdf_hair_principled.h +++ b/intern/cycles/kernel/closure/bsdf_hair_principled.h @@ -20,7 +20,7 @@ typedef struct PrincipledHairBSDF { SHADER_CLOSURE_BASE; /* Absorption coefficient. */ - float3 sigma; + Spectrum sigma; /* Variance of the underlying logistic distribution. */ float v; /* Scale factor of the underlying logistic distribution. */ @@ -166,12 +166,6 @@ ccl_device_inline float longitudinal_scattering( } } -/* Combine the three values using their luminances. */ -ccl_device_inline float4 combine_with_energy(KernelGlobals kg, float3 c) -{ - return make_float4(c.x, c.y, c.z, linear_rgb_to_gray(kg, c)); -} - #ifdef __HAIR__ /* Set up the hair closure. */ ccl_device int bsdf_principled_hair_setup(ccl_private ShaderData *sd, @@ -214,34 +208,36 @@ ccl_device int bsdf_principled_hair_setup(ccl_private ShaderData *sd, #endif /* __HAIR__ */ /* Given the Fresnel term and transmittance, generate the attenuation terms for each bounce. */ -ccl_device_inline void hair_attenuation(KernelGlobals kg, - float f, - float3 T, - ccl_private float4 *Ap) +ccl_device_inline void hair_attenuation( + KernelGlobals kg, float f, Spectrum T, ccl_private Spectrum *Ap, ccl_private float *Ap_energy) { /* Primary specular (R). */ - Ap[0] = make_float4(f, f, f, f); + Ap[0] = make_spectrum(f); + Ap_energy[0] = f; /* Transmission (TT). */ - float3 col = sqr(1.0f - f) * T; - Ap[1] = combine_with_energy(kg, col); + Spectrum col = sqr(1.0f - f) * T; + Ap[1] = col; + Ap_energy[1] = spectrum_to_gray(kg, col); /* Secondary specular (TRT). */ col *= T * f; - Ap[2] = combine_with_energy(kg, col); + Ap[2] = col; + Ap_energy[2] = spectrum_to_gray(kg, col); /* Residual component (TRRT+). */ - col *= safe_divide_color(T * f, make_float3(1.0f, 1.0f, 1.0f) - T * f); - Ap[3] = combine_with_energy(kg, col); + col *= safe_divide(T * f, one_spectrum() - T * f); + Ap[3] = col; + Ap_energy[3] = spectrum_to_gray(kg, col); /* Normalize sampling weights. */ - float totweight = Ap[0].w + Ap[1].w + Ap[2].w + Ap[3].w; + float totweight = Ap_energy[0] + Ap_energy[1] + Ap_energy[2] + Ap_energy[3]; float fac = safe_divide(1.0f, totweight); - Ap[0].w *= fac; - Ap[1].w *= fac; - Ap[2].w *= fac; - Ap[3].w *= fac; + Ap_energy[0] *= fac; + Ap_energy[1] *= fac; + Ap_energy[2] *= fac; + Ap_energy[3] *= fac; } /* Given the tilt angle, generate the rotated theta_i for the different bounces. */ @@ -266,11 +262,11 @@ ccl_device_inline void hair_alpha_angles(float sin_theta_i, } /* Evaluation function for our shader. */ -ccl_device float3 bsdf_principled_hair_eval(KernelGlobals kg, - ccl_private const ShaderData *sd, - ccl_private const ShaderClosure *sc, - const float3 omega_in, - ccl_private float *pdf) +ccl_device Spectrum bsdf_principled_hair_eval(KernelGlobals kg, + ccl_private const ShaderData *sd, + ccl_private const ShaderClosure *sc, + const float3 omega_in, + ccl_private float *pdf) { kernel_assert(isfinite_safe(sd->P) && isfinite_safe(sd->ray_length)); @@ -299,9 +295,11 @@ ccl_device float3 bsdf_principled_hair_eval(KernelGlobals kg, float cos_gamma_t = cos_from_sin(sin_gamma_t); float gamma_t = safe_asinf(sin_gamma_t); - float3 T = exp(-bsdf->sigma * (2.0f * cos_gamma_t / cos_theta_t)); - float4 Ap[4]; - hair_attenuation(kg, fresnel_dielectric_cos(cos_theta_o * cos_gamma_o, bsdf->eta), T, Ap); + Spectrum T = exp(-bsdf->sigma * (2.0f * cos_gamma_t / cos_theta_t)); + Spectrum Ap[4]; + float Ap_energy[4]; + hair_attenuation( + kg, fresnel_dielectric_cos(cos_theta_o * cos_gamma_o, bsdf->eta), T, Ap, Ap_energy); float sin_theta_i = wi.x; float cos_theta_i = cos_from_sin(sin_theta_i); @@ -312,35 +310,40 @@ ccl_device float3 bsdf_principled_hair_eval(KernelGlobals kg, float angles[6]; hair_alpha_angles(sin_theta_i, cos_theta_i, bsdf->alpha, angles); - float4 F; + Spectrum F; + float F_energy; float Mp, Np; /* Primary specular (R). */ Mp = longitudinal_scattering(angles[0], angles[1], sin_theta_o, cos_theta_o, bsdf->m0_roughness); Np = azimuthal_scattering(phi, 0, bsdf->s, gamma_o, gamma_t); F = Ap[0] * Mp * Np; - kernel_assert(isfinite_safe(float4_to_float3(F))); + F_energy = Ap_energy[0] * Mp * Np; + kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy)); /* Transmission (TT). */ Mp = longitudinal_scattering(angles[2], angles[3], sin_theta_o, cos_theta_o, 0.25f * bsdf->v); Np = azimuthal_scattering(phi, 1, bsdf->s, gamma_o, gamma_t); F += Ap[1] * Mp * Np; - kernel_assert(isfinite_safe(float4_to_float3(F))); + F_energy += Ap_energy[1] * Mp * Np; + kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy)); /* Secondary specular (TRT). */ Mp = longitudinal_scattering(angles[4], angles[5], sin_theta_o, cos_theta_o, 4.0f * bsdf->v); Np = azimuthal_scattering(phi, 2, bsdf->s, gamma_o, gamma_t); F += Ap[2] * Mp * Np; - kernel_assert(isfinite_safe(float4_to_float3(F))); + F_energy += Ap_energy[2] * Mp * Np; + kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy)); /* Residual component (TRRT+). */ Mp = longitudinal_scattering(sin_theta_i, cos_theta_i, sin_theta_o, cos_theta_o, 4.0f * bsdf->v); Np = M_1_2PI_F; F += Ap[3] * Mp * Np; - kernel_assert(isfinite_safe(float4_to_float3(F))); + F_energy += Ap_energy[3] * Mp * Np; + kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy)); - *pdf = F.w; - return float4_to_float3(F); + *pdf = F_energy; + return F; } /* Sampling function for the hair shader. */ @@ -349,7 +352,7 @@ ccl_device int bsdf_principled_hair_sample(KernelGlobals kg, ccl_private ShaderData *sd, float randu, float randv, - ccl_private float3 *eval, + ccl_private Spectrum *eval, ccl_private float3 *omega_in, ccl_private float3 *domega_in_dx, ccl_private float3 *domega_in_dy, @@ -385,16 +388,18 @@ ccl_device int bsdf_principled_hair_sample(KernelGlobals kg, float cos_gamma_t = cos_from_sin(sin_gamma_t); float gamma_t = safe_asinf(sin_gamma_t); - float3 T = exp(-bsdf->sigma * (2.0f * cos_gamma_t / cos_theta_t)); - float4 Ap[4]; - hair_attenuation(kg, fresnel_dielectric_cos(cos_theta_o * cos_gamma_o, bsdf->eta), T, Ap); + Spectrum T = exp(-bsdf->sigma * (2.0f * cos_gamma_t / cos_theta_t)); + Spectrum Ap[4]; + float Ap_energy[4]; + hair_attenuation( + kg, fresnel_dielectric_cos(cos_theta_o * cos_gamma_o, bsdf->eta), T, Ap, Ap_energy); int p = 0; for (; p < 3; p++) { - if (u[0].x < Ap[p].w) { + if (u[0].x < Ap_energy[p]) { break; } - u[0].x -= Ap[p].w; + u[0].x -= Ap_energy[p]; } float v = bsdf->v; @@ -429,35 +434,40 @@ ccl_device int bsdf_principled_hair_sample(KernelGlobals kg, hair_alpha_angles(sin_theta_i, cos_theta_i, bsdf->alpha, angles); - float4 F; + Spectrum F; + float F_energy; float Mp, Np; /* Primary specular (R). */ Mp = longitudinal_scattering(angles[0], angles[1], sin_theta_o, cos_theta_o, bsdf->m0_roughness); Np = azimuthal_scattering(phi, 0, bsdf->s, gamma_o, gamma_t); F = Ap[0] * Mp * Np; - kernel_assert(isfinite_safe(float4_to_float3(F))); + F_energy = Ap_energy[0] * Mp * Np; + kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy)); /* Transmission (TT). */ Mp = longitudinal_scattering(angles[2], angles[3], sin_theta_o, cos_theta_o, 0.25f * bsdf->v); Np = azimuthal_scattering(phi, 1, bsdf->s, gamma_o, gamma_t); F += Ap[1] * Mp * Np; - kernel_assert(isfinite_safe(float4_to_float3(F))); + F_energy += Ap_energy[1] * Mp * Np; + kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy)); /* Secondary specular (TRT). */ Mp = longitudinal_scattering(angles[4], angles[5], sin_theta_o, cos_theta_o, 4.0f * bsdf->v); Np = azimuthal_scattering(phi, 2, bsdf->s, gamma_o, gamma_t); F += Ap[2] * Mp * Np; - kernel_assert(isfinite_safe(float4_to_float3(F))); + F_energy += Ap_energy[2] * Mp * Np; + kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy)); /* Residual component (TRRT+). */ Mp = longitudinal_scattering(sin_theta_i, cos_theta_i, sin_theta_o, cos_theta_o, 4.0f * bsdf->v); Np = M_1_2PI_F; F += Ap[3] * Mp * Np; - kernel_assert(isfinite_safe(float4_to_float3(F))); + F_energy += Ap_energy[3] * Mp * Np; + kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy)); - *eval = float4_to_float3(F); - *pdf = F.w; + *eval = F; + *pdf = F_energy; *omega_in = X * sin_theta_i + Y * cos_theta_i * cosf(phi_i) + Z * cos_theta_i * sinf(phi_i); @@ -489,25 +499,28 @@ ccl_device_inline float bsdf_principled_hair_albedo_roughness_scale( return (((((0.245f * x) + 5.574f) * x - 10.73f) * x + 2.532f) * x - 0.215f) * x + 5.969f; } -ccl_device float3 bsdf_principled_hair_albedo(ccl_private const ShaderClosure *sc) +ccl_device Spectrum bsdf_principled_hair_albedo(ccl_private const ShaderClosure *sc) { ccl_private PrincipledHairBSDF *bsdf = (ccl_private PrincipledHairBSDF *)sc; return exp(-sqrt(bsdf->sigma) * bsdf_principled_hair_albedo_roughness_scale(bsdf->v)); } -ccl_device_inline float3 -bsdf_principled_hair_sigma_from_reflectance(const float3 color, const float azimuthal_roughness) +ccl_device_inline Spectrum +bsdf_principled_hair_sigma_from_reflectance(const Spectrum color, const float azimuthal_roughness) { - const float3 sigma = log(color) / - bsdf_principled_hair_albedo_roughness_scale(azimuthal_roughness); + const Spectrum sigma = log(color) / + bsdf_principled_hair_albedo_roughness_scale(azimuthal_roughness); return sigma * sigma; } -ccl_device_inline float3 bsdf_principled_hair_sigma_from_concentration(const float eumelanin, - const float pheomelanin) +ccl_device_inline Spectrum bsdf_principled_hair_sigma_from_concentration(const float eumelanin, + const float pheomelanin) { - return eumelanin * make_float3(0.506f, 0.841f, 1.653f) + - pheomelanin * make_float3(0.343f, 0.733f, 1.924f); + const float3 eumelanin_color = make_float3(0.506f, 0.841f, 1.653f); + const float3 pheomelanin_color = make_float3(0.343f, 0.733f, 1.924f); + + return eumelanin * rgb_to_spectrum(eumelanin_color) + + pheomelanin * rgb_to_spectrum(pheomelanin_color); } CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/closure/bsdf_microfacet.h b/intern/cycles/kernel/closure/bsdf_microfacet.h index c6cbd1ffae7..091fbde5585 100644 --- a/intern/cycles/kernel/closure/bsdf_microfacet.h +++ b/intern/cycles/kernel/closure/bsdf_microfacet.h @@ -17,8 +17,8 @@ CCL_NAMESPACE_BEGIN typedef struct MicrofacetExtra { - float3 color, cspec0; - float3 fresnel_color; + Spectrum color, cspec0; + Spectrum fresnel_color; float clearcoat; } MicrofacetExtra; @@ -233,11 +233,11 @@ ccl_device_forceinline float3 microfacet_sample_stretched(KernelGlobals kg, * * Else it is simply white */ -ccl_device_forceinline float3 reflection_color(ccl_private const MicrofacetBsdf *bsdf, - float3 L, - float3 H) +ccl_device_forceinline Spectrum reflection_color(ccl_private const MicrofacetBsdf *bsdf, + float3 L, + float3 H) { - float3 F = make_float3(1.0f, 1.0f, 1.0f); + Spectrum F = one_spectrum(); bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID || bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID); if (use_fresnel) { @@ -357,10 +357,10 @@ ccl_device void bsdf_microfacet_ggx_blur(ccl_private ShaderClosure *sc, float ro bsdf->alpha_y = fmaxf(roughness, bsdf->alpha_y); } -ccl_device float3 bsdf_microfacet_ggx_eval_reflect(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) +ccl_device Spectrum bsdf_microfacet_ggx_eval_reflect(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) { ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc; float alpha_x = bsdf->alpha_x; @@ -370,7 +370,7 @@ ccl_device float3 bsdf_microfacet_ggx_eval_reflect(ccl_private const ShaderClosu if (m_refractive || alpha_x * alpha_y <= 1e-7f) { *pdf = 0.0f; - return make_float3(0.0f, 0.0f, 0.0f); + return zero_spectrum(); } float cosNO = dot(N, I); @@ -451,12 +451,12 @@ ccl_device float3 bsdf_microfacet_ggx_eval_reflect(ccl_private const ShaderClosu /* eq. 20 */ float common = D * 0.25f / cosNO; - float3 F = reflection_color(bsdf, omega_in, m); + Spectrum F = reflection_color(bsdf, omega_in, m); if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) { F *= 0.25f * bsdf->extra->clearcoat; } - float3 out = F * G * common; + Spectrum out = F * G * common; /* eq. 2 in distribution of visible normals sampling * `pm = Dw = G1o * dot(m, I) * D / dot(N, I);` */ @@ -469,13 +469,13 @@ ccl_device float3 bsdf_microfacet_ggx_eval_reflect(ccl_private const ShaderClosu return out; } - return make_float3(0.0f, 0.0f, 0.0f); + return zero_spectrum(); } -ccl_device float3 bsdf_microfacet_ggx_eval_transmit(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) +ccl_device Spectrum bsdf_microfacet_ggx_eval_transmit(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) { ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc; float alpha_x = bsdf->alpha_x; @@ -486,7 +486,7 @@ ccl_device float3 bsdf_microfacet_ggx_eval_transmit(ccl_private const ShaderClos if (!m_refractive || alpha_x * alpha_y <= 1e-7f) { *pdf = 0.0f; - return make_float3(0.0f, 0.0f, 0.0f); + return zero_spectrum(); } float cosNO = dot(N, I); @@ -494,7 +494,7 @@ ccl_device float3 bsdf_microfacet_ggx_eval_transmit(ccl_private const ShaderClos if (cosNO <= 0 || cosNI >= 0) { *pdf = 0.0f; - return make_float3(0.0f, 0.0f, 0.0f); /* vectors on same side -- not possible */ + return zero_spectrum(); /* vectors on same side -- not possible */ } /* compute half-vector of the refraction (eq. 16) */ float3 ht = -(m_eta * omega_in + I); @@ -530,7 +530,7 @@ ccl_device float3 bsdf_microfacet_ggx_eval_transmit(ccl_private const ShaderClos float out = G * fabsf(cosHI * cosHO) * common; *pdf = G1o * fabsf(cosHO * cosHI) * common; - return make_float3(out, out, out); + return make_spectrum(out); } ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals kg, @@ -541,7 +541,7 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals kg, float3 dIdy, float randu, float randv, - ccl_private float3 *eval, + ccl_private Spectrum *eval, ccl_private float3 *omega_in, ccl_private float3 *domega_in_dx, ccl_private float3 *domega_in_dy, @@ -588,7 +588,7 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals kg, if (alpha_x * alpha_y <= 1e-7f) { /* some high number for MIS */ *pdf = 1e6f; - *eval = make_float3(1e6f, 1e6f, 1e6f); + *eval = make_spectrum(1e6f); bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID || bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID); @@ -664,7 +664,7 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals kg, float common = (G1o * D) * 0.25f / cosNO; *pdf = common; - float3 F = reflection_color(bsdf, *omega_in, m); + Spectrum F = reflection_color(bsdf, *omega_in, m); *eval = G1i * common * F; } @@ -679,7 +679,7 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals kg, #endif } else { - *eval = make_float3(0.0f, 0.0f, 0.0f); + *eval = zero_spectrum(); *pdf = 0.0f; } } @@ -722,7 +722,7 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals kg, 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); + *eval = make_spectrum(1e6f); label = LABEL_TRANSMIT | LABEL_SINGULAR; } else { @@ -750,11 +750,11 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals kg, float out = G1i * fabsf(cosHI * cosHO) * common; *pdf = cosHO * fabsf(cosHI) * common; - *eval = make_float3(out, out, out); + *eval = make_spectrum(out); } } else { - *eval = make_float3(0.0f, 0.0f, 0.0f); + *eval = zero_spectrum(); *pdf = 0.0f; } } @@ -835,10 +835,10 @@ ccl_device_inline float bsdf_beckmann_aniso_G1( return ((2.181f * a + 3.535f) * a) / ((2.577f * a + 2.276f) * a + 1.0f); } -ccl_device float3 bsdf_microfacet_beckmann_eval_reflect(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) +ccl_device Spectrum bsdf_microfacet_beckmann_eval_reflect(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) { ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc; float alpha_x = bsdf->alpha_x; @@ -848,7 +848,7 @@ ccl_device float3 bsdf_microfacet_beckmann_eval_reflect(ccl_private const Shader if (m_refractive || alpha_x * alpha_y <= 1e-7f) { *pdf = 0.0f; - return make_float3(0.0f, 0.0f, 0.0f); + return zero_spectrum(); } float cosNO = dot(N, I); @@ -910,16 +910,16 @@ ccl_device float3 bsdf_microfacet_beckmann_eval_reflect(ccl_private const Shader * pdf = pm * 0.25 / dot(m, I); */ *pdf = G1o * common; - return make_float3(out, out, out); + return make_spectrum(out); } - return make_float3(0.0f, 0.0f, 0.0f); + return zero_spectrum(); } -ccl_device float3 bsdf_microfacet_beckmann_eval_transmit(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) +ccl_device Spectrum bsdf_microfacet_beckmann_eval_transmit(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) { ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc; float alpha_x = bsdf->alpha_x; @@ -930,7 +930,7 @@ ccl_device float3 bsdf_microfacet_beckmann_eval_transmit(ccl_private const Shade if (!m_refractive || alpha_x * alpha_y <= 1e-7f) { *pdf = 0.0f; - return make_float3(0.0f, 0.0f, 0.0f); + return zero_spectrum(); } float cosNO = dot(N, I); @@ -938,7 +938,7 @@ ccl_device float3 bsdf_microfacet_beckmann_eval_transmit(ccl_private const Shade if (cosNO <= 0 || cosNI >= 0) { *pdf = 0.0f; - return make_float3(0.0f, 0.0f, 0.0f); + return zero_spectrum(); } /* compute half-vector of the refraction (eq. 16) */ float3 ht = -(m_eta * omega_in + I); @@ -971,7 +971,7 @@ ccl_device float3 bsdf_microfacet_beckmann_eval_transmit(ccl_private const Shade float out = G * fabsf(cosHI * cosHO) * common; *pdf = G1o * fabsf(cosHO * cosHI) * common; - return make_float3(out, out, out); + return make_spectrum(out); } ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals kg, @@ -982,7 +982,7 @@ ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals kg, float3 dIdy, float randu, float randv, - ccl_private float3 *eval, + ccl_private Spectrum *eval, ccl_private float3 *omega_in, ccl_private float3 *domega_in_dx, ccl_private float3 *domega_in_dy, @@ -1028,7 +1028,7 @@ ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals kg, if (alpha_x * alpha_y <= 1e-7f) { /* some high number for MIS */ *pdf = 1e6f; - *eval = make_float3(1e6f, 1e6f, 1e6f); + *eval = make_spectrum(1e6f); label = LABEL_REFLECT | LABEL_SINGULAR; } else { @@ -1074,7 +1074,7 @@ ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals kg, float out = G * common; *pdf = G1o * common; - *eval = make_float3(out, out, out); + *eval = make_spectrum(out); } #ifdef __RAY_DIFFERENTIALS__ @@ -1083,7 +1083,7 @@ ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals kg, #endif } else { - *eval = make_float3(0.0f, 0.0f, 0.0f); + *eval = zero_spectrum(); *pdf = 0.0f; } } @@ -1126,7 +1126,7 @@ ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals kg, 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); + *eval = make_spectrum(1e6f); label = LABEL_TRANSMIT | LABEL_SINGULAR; } else { @@ -1155,11 +1155,11 @@ ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals kg, float out = G * fabsf(cosHI * cosHO) * common; *pdf = G1o * cosHO * fabsf(cosHI) * common; - *eval = make_float3(out, out, out); + *eval = make_spectrum(out); } } else { - *eval = make_float3(0.0f, 0.0f, 0.0f); + *eval = zero_spectrum(); *pdf = 0.0f; } } diff --git a/intern/cycles/kernel/closure/bsdf_microfacet_multi.h b/intern/cycles/kernel/closure/bsdf_microfacet_multi.h index b2e068daf17..e6ab116519b 100644 --- a/intern/cycles/kernel/closure/bsdf_microfacet_multi.h +++ b/intern/cycles/kernel/closure/bsdf_microfacet_multi.h @@ -95,29 +95,29 @@ ccl_device_forceinline float3 mf_sample_vndf(const float3 wi, /* Phase function for reflective materials. */ ccl_device_forceinline float3 mf_sample_phase_glossy(const float3 wi, - ccl_private float3 *weight, + ccl_private Spectrum *weight, const float3 wm) { return -wi + 2.0f * wm * dot(wi, wm); } -ccl_device_forceinline float3 mf_eval_phase_glossy(const float3 w, - const float lambda, - const float3 wo, - const float2 alpha) +ccl_device_forceinline Spectrum mf_eval_phase_glossy(const float3 w, + const float lambda, + const float3 wo, + const float2 alpha) { if (w.z > 0.9999f) - return make_float3(0.0f, 0.0f, 0.0f); + return zero_spectrum(); const float3 wh = normalize(wo - w); if (wh.z < 0.0f) - return make_float3(0.0f, 0.0f, 0.0f); + return zero_spectrum(); 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); + return zero_spectrum(); float phase = max(0.0f, dotW_WH) * 0.25f / max(pArea * dotW_WH, 1e-7f); if (alpha.x == alpha.y) @@ -125,7 +125,7 @@ ccl_device_forceinline float3 mf_eval_phase_glossy(const float3 w, else phase *= D_ggx_aniso(wh, alpha); - return make_float3(phase, phase, phase); + return make_spectrum(phase); } /* Phase function for dielectric transmissive materials, including both reflection and refraction @@ -148,22 +148,22 @@ ccl_device_forceinline float3 mf_sample_phase_glass(const float3 wi, return normalize(wm * (cosI * inv_eta + cosT) - wi * inv_eta); } -ccl_device_forceinline float3 mf_eval_phase_glass(const float3 w, - const float lambda, - const float3 wo, - const bool wo_outside, - const float2 alpha, - const float eta) +ccl_device_forceinline Spectrum 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); + return zero_spectrum(); 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); + return zero_spectrum(); 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 / @@ -175,14 +175,14 @@ ccl_device_forceinline float3 mf_eval_phase_glass(const float3 w, 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); + return zero_spectrum(); 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); + return make_spectrum(v); } /* === Utility functions for the random walks === */ @@ -415,27 +415,27 @@ ccl_device int bsdf_microfacet_multi_ggx_refraction_setup(ccl_private Microfacet return bsdf_microfacet_multi_ggx_common_setup(bsdf); } -ccl_device float3 bsdf_microfacet_multi_ggx_eval_transmit(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf, - ccl_private uint *lcg_state) +ccl_device Spectrum bsdf_microfacet_multi_ggx_eval_transmit(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf, + ccl_private uint *lcg_state) { *pdf = 0.0f; - return make_float3(0.0f, 0.0f, 0.0f); + return zero_spectrum(); } -ccl_device float3 bsdf_microfacet_multi_ggx_eval_reflect(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf, - ccl_private uint *lcg_state) +ccl_device Spectrum bsdf_microfacet_multi_ggx_eval_reflect(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf, + ccl_private uint *lcg_state) { ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc; if (bsdf->alpha_x * bsdf->alpha_y < 1e-7f) { *pdf = 0.0f; - return make_float3(0.0f, 0.0f, 0.0f); + return zero_spectrum(); } float3 X, Y, Z; @@ -444,7 +444,7 @@ ccl_device float3 bsdf_microfacet_multi_ggx_eval_reflect(ccl_private const Shade /* Ensure that the both directions are on the outside w.r.t. the shading normal. */ if (dot(Z, I) <= 0.0f || dot(Z, omega_in) <= 0.0f) { *pdf = 0.0f; - return make_float3(0.0f, 0.0f, 0.0f); + return zero_spectrum(); } bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID); @@ -482,7 +482,7 @@ ccl_device int bsdf_microfacet_multi_ggx_sample(KernelGlobals kg, float3 dIdy, float randu, float randv, - ccl_private float3 *eval, + ccl_private Spectrum *eval, ccl_private float3 *omega_in, ccl_private float3 *domega_in_dx, ccl_private float3 *domega_in_dy, @@ -509,7 +509,7 @@ ccl_device int bsdf_microfacet_multi_ggx_sample(KernelGlobals kg, return LABEL_NONE; } *pdf = 1e6f; - *eval = make_float3(1e6f, 1e6f, 1e6f); + *eval = make_spectrum(1e6f); #ifdef __RAY_DIFFERENTIALS__ *domega_in_dx = (2 * dot(Z, dIdx)) * Z - dIdx; *domega_in_dy = (2 * dot(Z, dIdy)) * Z - dIdy; @@ -588,7 +588,7 @@ ccl_device int bsdf_microfacet_multi_ggx_glass_fresnel_setup(ccl_private Microfa return SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_NEEDS_LCG; } -ccl_device float3 +ccl_device Spectrum bsdf_microfacet_multi_ggx_glass_eval_transmit(ccl_private const ShaderClosure *sc, const float3 I, const float3 omega_in, @@ -599,7 +599,7 @@ bsdf_microfacet_multi_ggx_glass_eval_transmit(ccl_private const ShaderClosure *s if (bsdf->alpha_x * bsdf->alpha_y < 1e-7f) { *pdf = 0.0f; - return make_float3(0.0f, 0.0f, 0.0f); + return zero_spectrum(); } float3 X, Y, Z; @@ -622,17 +622,18 @@ bsdf_microfacet_multi_ggx_glass_eval_transmit(ccl_private const ShaderClosure *s bsdf->extra->color); } -ccl_device float3 bsdf_microfacet_multi_ggx_glass_eval_reflect(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf, - ccl_private uint *lcg_state) +ccl_device Spectrum +bsdf_microfacet_multi_ggx_glass_eval_reflect(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf, + ccl_private uint *lcg_state) { ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc; if (bsdf->alpha_x * bsdf->alpha_y < 1e-7f) { *pdf = 0.0f; - return make_float3(0.0f, 0.0f, 0.0f); + return zero_spectrum(); } bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID); @@ -665,7 +666,7 @@ ccl_device int bsdf_microfacet_multi_ggx_glass_sample(KernelGlobals kg, float3 dIdy, float randu, float randv, - ccl_private float3 *eval, + ccl_private Spectrum *eval, ccl_private float3 *omega_in, ccl_private float3 *domega_in_dx, ccl_private float3 *domega_in_dy, @@ -699,7 +700,7 @@ ccl_device int bsdf_microfacet_multi_ggx_glass_sample(KernelGlobals kg, &inside); *pdf = 1e6f; - *eval = make_float3(1e6f, 1e6f, 1e6f); + *eval = make_spectrum(1e6f); if (randu < fresnel) { *omega_in = R; #ifdef __RAY_DIFFERENTIALS__ diff --git a/intern/cycles/kernel/closure/bsdf_microfacet_multi_impl.h b/intern/cycles/kernel/closure/bsdf_microfacet_multi_impl.h index e4fcf0e6ba3..91fb9158050 100644 --- a/intern/cycles/kernel/closure/bsdf_microfacet_multi_impl.h +++ b/intern/cycles/kernel/closure/bsdf_microfacet_multi_impl.h @@ -12,16 +12,16 @@ * 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_forceinline float3 MF_FUNCTION_FULL_NAME(mf_eval)(float3 wi, - float3 wo, - const bool wo_outside, - const float3 color, - const float alpha_x, - const float alpha_y, - ccl_private uint *lcg_state, - const float eta, - bool use_fresnel, - const float3 cspec0) +ccl_device_forceinline Spectrum MF_FUNCTION_FULL_NAME(mf_eval)(float3 wi, + float3 wo, + const bool wo_outside, + const Spectrum color, + const float alpha_x, + const float alpha_y, + ccl_private uint *lcg_state, + const float eta, + bool use_fresnel, + const Spectrum cspec0) { /* Evaluating for a shallower incoming direction produces less noise, and the properties of the * BSDF guarantee reciprocity. */ @@ -46,7 +46,7 @@ ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_eval)(float3 wi, } 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); + return zero_spectrum(); const float2 alpha = make_float2(alpha_x, alpha_y); @@ -54,8 +54,8 @@ ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_eval)(float3 wi, float shadowing_lambda = mf_lambda(wo_outside ? wo : -wo, alpha); /* Analytically compute single scattering for lower noise. */ - float3 eval; - float3 throughput = make_float3(1.0f, 1.0f, 1.0f); + Spectrum eval; + Spectrum throughput = one_spectrum(); const float3 wh = normalize(wi + wo); #ifdef MF_MULTI_GLASS eval = mf_eval_phase_glass(-wi, lambda_r, wo, wo_outside, alpha, eta); @@ -70,7 +70,7 @@ ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_eval)(float3 wi, val *= D_ggx(wh, alpha.x); else val *= D_ggx_aniso(wh, alpha); - eval = make_float3(val, val, val); + eval = make_spectrum(val); #endif float F0 = fresnel_dielectric_cos(1.0f, eta); @@ -99,7 +99,7 @@ ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_eval)(float3 wi, #ifdef MF_MULTI_GLASS if (order == 0 && use_fresnel) { /* Evaluate amount of scattering towards wo on this microfacet. */ - float3 phase; + Spectrum phase; if (outside) phase = mf_eval_phase_glass(wr, lambda_r, wo, wo_outside, alpha, eta); else @@ -113,7 +113,7 @@ ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_eval)(float3 wi, #endif if (order > 0) { /* Evaluate amount of scattering towards wo on this microfacet. */ - float3 phase; + Spectrum phase; #ifdef MF_MULTI_GLASS if (outside) phase = mf_eval_phase_glass(wr, lambda_r, wo, wo_outside, alpha, eta); @@ -172,19 +172,19 @@ ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_eval)(float3 wi, * walk escaped the surface in wo. The function returns the throughput between wi and wo. Without * reflection losses due to coloring or fresnel absorption in conductors, the sampling is optimal. */ -ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_sample)(float3 wi, - ccl_private float3 *wo, - const float3 color, - const float alpha_x, - const float alpha_y, - ccl_private uint *lcg_state, - const float eta, - bool use_fresnel, - const float3 cspec0) +ccl_device_forceinline Spectrum MF_FUNCTION_FULL_NAME(mf_sample)(float3 wi, + ccl_private float3 *wo, + const Spectrum color, + const float alpha_x, + const float alpha_y, + ccl_private uint *lcg_state, + const float eta, + bool use_fresnel, + const Spectrum cspec0) { const float2 alpha = make_float2(alpha_x, alpha_y); - float3 throughput = make_float3(1.0f, 1.0f, 1.0f); + Spectrum throughput = one_spectrum(); float3 wr = -wi; float lambda_r = mf_lambda(wr, alpha); float hr = 1.0f; @@ -229,7 +229,7 @@ ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_sample)(float3 wi, throughput *= color; } else { - float3 t_color = interpolate_fresnel_color(wi_prev, wm, eta, F0, cspec0); + Spectrum t_color = interpolate_fresnel_color(wi_prev, wm, eta, F0, cspec0); if (order == 0) throughput = t_color; @@ -239,7 +239,7 @@ ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_sample)(float3 wi, } #else /* MF_MULTI_GLOSSY */ if (use_fresnel) { - float3 t_color = interpolate_fresnel_color(-wr, wm, eta, F0, cspec0); + Spectrum t_color = interpolate_fresnel_color(-wr, wm, eta, F0, cspec0); if (order == 0) throughput = t_color; @@ -254,7 +254,7 @@ ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_sample)(float3 wi, 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); + return zero_spectrum(); } #undef MF_MULTI_GLASS diff --git a/intern/cycles/kernel/closure/bsdf_oren_nayar.h b/intern/cycles/kernel/closure/bsdf_oren_nayar.h index 56c7ec869c7..fcfeb9257f1 100644 --- a/intern/cycles/kernel/closure/bsdf_oren_nayar.h +++ b/intern/cycles/kernel/closure/bsdf_oren_nayar.h @@ -15,10 +15,10 @@ typedef struct OrenNayarBsdf { static_assert(sizeof(ShaderClosure) >= sizeof(OrenNayarBsdf), "OrenNayarBsdf is too large!"); -ccl_device float3 bsdf_oren_nayar_get_intensity(ccl_private const ShaderClosure *sc, - float3 n, - float3 v, - float3 l) +ccl_device Spectrum bsdf_oren_nayar_get_intensity(ccl_private const ShaderClosure *sc, + float3 n, + float3 v, + float3 l) { ccl_private const OrenNayarBsdf *bsdf = (ccl_private const OrenNayarBsdf *)sc; float nl = max(dot(n, l), 0.0f); @@ -28,7 +28,7 @@ ccl_device float3 bsdf_oren_nayar_get_intensity(ccl_private const ShaderClosure if (t > 0.0f) t /= max(nl, nv) + FLT_MIN; float is = nl * (bsdf->a + bsdf->b * t); - return make_float3(is, is, is); + return make_spectrum(is); } ccl_device int bsdf_oren_nayar_setup(ccl_private OrenNayarBsdf *bsdf) @@ -47,10 +47,10 @@ ccl_device int bsdf_oren_nayar_setup(ccl_private OrenNayarBsdf *bsdf) return SD_BSDF | SD_BSDF_HAS_EVAL; } -ccl_device float3 bsdf_oren_nayar_eval_reflect(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) +ccl_device Spectrum bsdf_oren_nayar_eval_reflect(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) { ccl_private const OrenNayarBsdf *bsdf = (ccl_private const OrenNayarBsdf *)sc; if (dot(bsdf->N, omega_in) > 0.0f) { @@ -59,17 +59,17 @@ ccl_device float3 bsdf_oren_nayar_eval_reflect(ccl_private const ShaderClosure * } else { *pdf = 0.0f; - return make_float3(0.0f, 0.0f, 0.0f); + return zero_spectrum(); } } -ccl_device float3 bsdf_oren_nayar_eval_transmit(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) +ccl_device Spectrum bsdf_oren_nayar_eval_transmit(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) { *pdf = 0.0f; - return make_float3(0.0f, 0.0f, 0.0f); + return zero_spectrum(); } ccl_device int bsdf_oren_nayar_sample(ccl_private const ShaderClosure *sc, @@ -79,7 +79,7 @@ ccl_device int bsdf_oren_nayar_sample(ccl_private const ShaderClosure *sc, float3 dIdy, float randu, float randv, - ccl_private float3 *eval, + ccl_private Spectrum *eval, ccl_private float3 *omega_in, ccl_private float3 *domega_in_dx, ccl_private float3 *domega_in_dy, @@ -99,7 +99,7 @@ ccl_device int bsdf_oren_nayar_sample(ccl_private const ShaderClosure *sc, } else { *pdf = 0.0f; - *eval = make_float3(0.0f, 0.0f, 0.0f); + *eval = zero_spectrum(); } return LABEL_REFLECT | LABEL_DIFFUSE; diff --git a/intern/cycles/kernel/closure/bsdf_phong_ramp.h b/intern/cycles/kernel/closure/bsdf_phong_ramp.h index 74a1f7ae090..d010e74cb65 100644 --- a/intern/cycles/kernel/closure/bsdf_phong_ramp.h +++ b/intern/cycles/kernel/closure/bsdf_phong_ramp.h @@ -8,6 +8,8 @@ #pragma once +#include "kernel/util/color.h" + CCL_NAMESPACE_BEGIN #ifdef __OSL__ @@ -42,10 +44,10 @@ ccl_device int bsdf_phong_ramp_setup(ccl_private PhongRampBsdf *bsdf) return SD_BSDF | SD_BSDF_HAS_EVAL; } -ccl_device float3 bsdf_phong_ramp_eval_reflect(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) +ccl_device Spectrum bsdf_phong_ramp_eval_reflect(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) { ccl_private const PhongRampBsdf *bsdf = (ccl_private const PhongRampBsdf *)sc; float m_exponent = bsdf->exponent; @@ -61,11 +63,11 @@ ccl_device float3 bsdf_phong_ramp_eval_reflect(ccl_private const ShaderClosure * float common = 0.5f * M_1_PI_F * cosp; float out = cosNI * (m_exponent + 2) * common; *pdf = (m_exponent + 1) * common; - return bsdf_phong_ramp_get_color(bsdf->colors, cosp) * out; + return rgb_to_spectrum(bsdf_phong_ramp_get_color(bsdf->colors, cosp) * out); } } *pdf = 0.0f; - return make_float3(0.0f, 0.0f, 0.0f); + return zero_spectrum(); } ccl_device float3 bsdf_phong_ramp_eval_transmit(ccl_private const ShaderClosure *sc, @@ -84,7 +86,7 @@ ccl_device int bsdf_phong_ramp_sample(ccl_private const ShaderClosure *sc, float3 dIdy, float randu, float randv, - ccl_private float3 *eval, + ccl_private Spectrum *eval, ccl_private float3 *omega_in, ccl_private float3 *domega_in_dx, ccl_private float3 *domega_in_dy, @@ -119,12 +121,12 @@ ccl_device int bsdf_phong_ramp_sample(ccl_private const ShaderClosure *sc, float common = 0.5f * M_1_PI_F * cosp; *pdf = (m_exponent + 1) * common; float out = cosNI * (m_exponent + 2) * common; - *eval = bsdf_phong_ramp_get_color(bsdf->colors, cosp) * out; + *eval = rgb_to_spectrum(bsdf_phong_ramp_get_color(bsdf->colors, cosp) * out); } } } else { - *eval = make_float3(0.0f, 0.0f, 0.0f); + *eval = zero_spectrum(); *pdf = 0.0f; } return LABEL_REFLECT | LABEL_GLOSSY; diff --git a/intern/cycles/kernel/closure/bsdf_principled_diffuse.h b/intern/cycles/kernel/closure/bsdf_principled_diffuse.h index 5a7020e82d2..90ef252b3b9 100644 --- a/intern/cycles/kernel/closure/bsdf_principled_diffuse.h +++ b/intern/cycles/kernel/closure/bsdf_principled_diffuse.h @@ -42,7 +42,7 @@ ccl_device int bsdf_principled_diffuse_setup(ccl_private PrincipledDiffuseBsdf * return SD_BSDF | SD_BSDF_HAS_EVAL; } -ccl_device float3 +ccl_device Spectrum bsdf_principled_diffuse_compute_brdf(ccl_private const PrincipledDiffuseBsdf *bsdf, float3 N, float3 V, @@ -52,7 +52,7 @@ bsdf_principled_diffuse_compute_brdf(ccl_private const PrincipledDiffuseBsdf *bs const float NdotL = dot(N, L); if (NdotL <= 0) { - return make_float3(0.0f, 0.0f, 0.0f); + return zero_spectrum(); } const float NdotV = dot(N, V); @@ -82,7 +82,7 @@ bsdf_principled_diffuse_compute_brdf(ccl_private const PrincipledDiffuseBsdf *bs float value = M_1_PI_F * NdotL * f; - return make_float3(value, value, value); + return make_spectrum(value); } /* Compute Fresnel at entry point, to be combined with #PRINCIPLED_DIFFUSE_LAMBERT_EXIT @@ -109,10 +109,10 @@ ccl_device int bsdf_principled_diffuse_setup(ccl_private PrincipledDiffuseBsdf * return SD_BSDF | SD_BSDF_HAS_EVAL; } -ccl_device float3 bsdf_principled_diffuse_eval_reflect(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) +ccl_device Spectrum bsdf_principled_diffuse_eval_reflect(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) { ccl_private const PrincipledDiffuseBsdf *bsdf = (ccl_private const PrincipledDiffuseBsdf *)sc; @@ -126,17 +126,17 @@ ccl_device float3 bsdf_principled_diffuse_eval_reflect(ccl_private const ShaderC } else { *pdf = 0.0f; - return make_float3(0.0f, 0.0f, 0.0f); + return zero_spectrum(); } } -ccl_device float3 bsdf_principled_diffuse_eval_transmit(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) +ccl_device Spectrum bsdf_principled_diffuse_eval_transmit(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) { *pdf = 0.0f; - return make_float3(0.0f, 0.0f, 0.0f); + return zero_spectrum(); } ccl_device int bsdf_principled_diffuse_sample(ccl_private const ShaderClosure *sc, @@ -146,7 +146,7 @@ ccl_device int bsdf_principled_diffuse_sample(ccl_private const ShaderClosure *s float3 dIdy, float randu, float randv, - ccl_private float3 *eval, + ccl_private Spectrum *eval, ccl_private float3 *omega_in, ccl_private float3 *domega_in_dx, ccl_private float3 *domega_in_dy, @@ -169,7 +169,7 @@ ccl_device int bsdf_principled_diffuse_sample(ccl_private const ShaderClosure *s } else { *pdf = 0.0f; - *eval = make_float3(0.0f, 0.0f, 0.0f); + *eval = zero_spectrum(); } return LABEL_REFLECT | LABEL_DIFFUSE; } diff --git a/intern/cycles/kernel/closure/bsdf_principled_sheen.h b/intern/cycles/kernel/closure/bsdf_principled_sheen.h index 3a96a93db73..42a776299eb 100644 --- a/intern/cycles/kernel/closure/bsdf_principled_sheen.h +++ b/intern/cycles/kernel/closure/bsdf_principled_sheen.h @@ -32,7 +32,7 @@ ccl_device_inline float calculate_avg_principled_sheen_brdf(float3 N, float3 I) return schlick_fresnel(NdotI) * NdotI; } -ccl_device float3 +ccl_device Spectrum calculate_principled_sheen_brdf(float3 N, float3 V, float3 L, float3 H, ccl_private float *pdf) { float NdotL = dot(N, L); @@ -40,14 +40,14 @@ calculate_principled_sheen_brdf(float3 N, float3 V, float3 L, float3 H, ccl_priv if (NdotL < 0 || NdotV < 0) { *pdf = 0.0f; - return make_float3(0.0f, 0.0f, 0.0f); + return zero_spectrum(); } float LdotH = dot(L, H); float value = schlick_fresnel(LdotH) * NdotL; - return make_float3(value, value, value); + return make_spectrum(value); } ccl_device int bsdf_principled_sheen_setup(ccl_private const ShaderData *sd, @@ -59,10 +59,10 @@ ccl_device int bsdf_principled_sheen_setup(ccl_private const ShaderData *sd, return SD_BSDF | SD_BSDF_HAS_EVAL; } -ccl_device float3 bsdf_principled_sheen_eval_reflect(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) +ccl_device Spectrum bsdf_principled_sheen_eval_reflect(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) { ccl_private const PrincipledSheenBsdf *bsdf = (ccl_private const PrincipledSheenBsdf *)sc; @@ -77,17 +77,17 @@ ccl_device float3 bsdf_principled_sheen_eval_reflect(ccl_private const ShaderClo } else { *pdf = 0.0f; - return make_float3(0.0f, 0.0f, 0.0f); + return zero_spectrum(); } } -ccl_device float3 bsdf_principled_sheen_eval_transmit(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) +ccl_device Spectrum bsdf_principled_sheen_eval_transmit(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) { *pdf = 0.0f; - return make_float3(0.0f, 0.0f, 0.0f); + return zero_spectrum(); } ccl_device int bsdf_principled_sheen_sample(ccl_private const ShaderClosure *sc, @@ -97,7 +97,7 @@ ccl_device int bsdf_principled_sheen_sample(ccl_private const ShaderClosure *sc, float3 dIdy, float randu, float randv, - ccl_private float3 *eval, + ccl_private Spectrum *eval, ccl_private float3 *omega_in, ccl_private float3 *domega_in_dx, ccl_private float3 *domega_in_dy, @@ -121,7 +121,7 @@ ccl_device int bsdf_principled_sheen_sample(ccl_private const ShaderClosure *sc, #endif } else { - *eval = make_float3(0.0f, 0.0f, 0.0f); + *eval = zero_spectrum(); *pdf = 0.0f; } return LABEL_REFLECT | LABEL_DIFFUSE; diff --git a/intern/cycles/kernel/closure/bsdf_reflection.h b/intern/cycles/kernel/closure/bsdf_reflection.h index c8db2b7cf13..40d02b13b46 100644 --- a/intern/cycles/kernel/closure/bsdf_reflection.h +++ b/intern/cycles/kernel/closure/bsdf_reflection.h @@ -18,22 +18,22 @@ ccl_device int bsdf_reflection_setup(ccl_private MicrofacetBsdf *bsdf) return SD_BSDF; } -ccl_device float3 bsdf_reflection_eval_reflect(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) +ccl_device Spectrum bsdf_reflection_eval_reflect(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) { *pdf = 0.0f; - return make_float3(0.0f, 0.0f, 0.0f); + return zero_spectrum(); } -ccl_device float3 bsdf_reflection_eval_transmit(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) +ccl_device Spectrum bsdf_reflection_eval_transmit(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) { *pdf = 0.0f; - return make_float3(0.0f, 0.0f, 0.0f); + return zero_spectrum(); } ccl_device int bsdf_reflection_sample(ccl_private const ShaderClosure *sc, @@ -43,7 +43,7 @@ ccl_device int bsdf_reflection_sample(ccl_private const ShaderClosure *sc, float3 dIdy, float randu, float randv, - ccl_private float3 *eval, + ccl_private Spectrum *eval, ccl_private float3 *omega_in, ccl_private float3 *domega_in_dx, ccl_private float3 *domega_in_dy, @@ -63,12 +63,12 @@ ccl_device int bsdf_reflection_sample(ccl_private const ShaderClosure *sc, #endif /* Some high number for MIS. */ *pdf = 1e6f; - *eval = make_float3(1e6f, 1e6f, 1e6f); + *eval = make_spectrum(1e6f); } } else { *pdf = 0.0f; - *eval = make_float3(0.0f, 0.0f, 0.0f); + *eval = zero_spectrum(); } return LABEL_REFLECT | LABEL_SINGULAR; } diff --git a/intern/cycles/kernel/closure/bsdf_refraction.h b/intern/cycles/kernel/closure/bsdf_refraction.h index 862e774da87..3faa51025d6 100644 --- a/intern/cycles/kernel/closure/bsdf_refraction.h +++ b/intern/cycles/kernel/closure/bsdf_refraction.h @@ -18,22 +18,22 @@ ccl_device int bsdf_refraction_setup(ccl_private MicrofacetBsdf *bsdf) return SD_BSDF; } -ccl_device float3 bsdf_refraction_eval_reflect(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) +ccl_device Spectrum bsdf_refraction_eval_reflect(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) { *pdf = 0.0f; - return make_float3(0.0f, 0.0f, 0.0f); + return zero_spectrum(); } -ccl_device float3 bsdf_refraction_eval_transmit(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) +ccl_device Spectrum bsdf_refraction_eval_transmit(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) { *pdf = 0.0f; - return make_float3(0.0f, 0.0f, 0.0f); + return zero_spectrum(); } ccl_device int bsdf_refraction_sample(ccl_private const ShaderClosure *sc, @@ -43,7 +43,7 @@ ccl_device int bsdf_refraction_sample(ccl_private const ShaderClosure *sc, float3 dIdy, float randu, float randv, - ccl_private float3 *eval, + ccl_private Spectrum *eval, ccl_private float3 *omega_in, ccl_private float3 *domega_in_dx, ccl_private float3 *domega_in_dy, @@ -77,7 +77,7 @@ ccl_device int bsdf_refraction_sample(ccl_private const ShaderClosure *sc, if (!inside && fresnel != 1.0f) { /* Some high number for MIS. */ *pdf = 1e6f; - *eval = make_float3(1e6f, 1e6f, 1e6f); + *eval = make_spectrum(1e6f); *omega_in = T; #ifdef __RAY_DIFFERENTIALS__ *domega_in_dx = dTdx; @@ -86,7 +86,7 @@ ccl_device int bsdf_refraction_sample(ccl_private const ShaderClosure *sc, } else { *pdf = 0.0f; - *eval = make_float3(0.0f, 0.0f, 0.0f); + *eval = zero_spectrum(); } return LABEL_TRANSMIT | LABEL_SINGULAR; } diff --git a/intern/cycles/kernel/closure/bsdf_toon.h b/intern/cycles/kernel/closure/bsdf_toon.h index 0400fc61860..f2f48417319 100644 --- a/intern/cycles/kernel/closure/bsdf_toon.h +++ b/intern/cycles/kernel/closure/bsdf_toon.h @@ -30,7 +30,7 @@ ccl_device int bsdf_diffuse_toon_setup(ccl_private ToonBsdf *bsdf) return SD_BSDF | SD_BSDF_HAS_EVAL; } -ccl_device float3 bsdf_toon_get_intensity(float max_angle, float smooth, float angle) +ccl_device float bsdf_toon_get_intensity(float max_angle, float smooth, float angle) { float is; @@ -41,7 +41,7 @@ ccl_device float3 bsdf_toon_get_intensity(float max_angle, float smooth, float a else is = 0.0f; - return make_float3(is, is, is); + return is; } ccl_device float bsdf_toon_get_sample_angle(float max_angle, float smooth) @@ -49,35 +49,35 @@ ccl_device float bsdf_toon_get_sample_angle(float max_angle, float smooth) return fminf(max_angle + smooth, M_PI_2_F); } -ccl_device float3 bsdf_diffuse_toon_eval_reflect(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) +ccl_device Spectrum bsdf_diffuse_toon_eval_reflect(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) { ccl_private const ToonBsdf *bsdf = (ccl_private 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); + float eval = bsdf_toon_get_intensity(max_angle, smooth, angle); - if (eval.x > 0.0f) { + if (eval > 0.0f) { float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth); *pdf = 0.5f * M_1_PI_F / (1.0f - cosf(sample_angle)); - return *pdf * eval; + return make_spectrum(*pdf * eval); } *pdf = 0.0f; - return make_float3(0.0f, 0.0f, 0.0f); + return zero_spectrum(); } -ccl_device float3 bsdf_diffuse_toon_eval_transmit(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) +ccl_device Spectrum bsdf_diffuse_toon_eval_transmit(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) { *pdf = 0.0f; - return make_float3(0.0f, 0.0f, 0.0f); + return zero_spectrum(); } ccl_device int bsdf_diffuse_toon_sample(ccl_private const ShaderClosure *sc, @@ -87,7 +87,7 @@ ccl_device int bsdf_diffuse_toon_sample(ccl_private const ShaderClosure *sc, float3 dIdy, float randu, float randv, - ccl_private float3 *eval, + ccl_private Spectrum *eval, ccl_private float3 *omega_in, ccl_private float3 *domega_in_dx, ccl_private float3 *domega_in_dy, @@ -103,7 +103,7 @@ ccl_device int bsdf_diffuse_toon_sample(ccl_private const ShaderClosure *sc, 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); + *eval = make_spectrum(*pdf * bsdf_toon_get_intensity(max_angle, smooth, angle)); #ifdef __RAY_DIFFERENTIALS__ // TODO: find a better approximation for the bounce @@ -112,12 +112,12 @@ ccl_device int bsdf_diffuse_toon_sample(ccl_private const ShaderClosure *sc, #endif } else { - *eval = make_float3(0.f, 0.f, 0.f); + *eval = zero_spectrum(); *pdf = 0.0f; } } else { - *eval = make_float3(0.f, 0.f, 0.f); + *eval = zero_spectrum(); *pdf = 0.0f; } @@ -135,10 +135,10 @@ ccl_device int bsdf_glossy_toon_setup(ccl_private ToonBsdf *bsdf) return SD_BSDF | SD_BSDF_HAS_EVAL; } -ccl_device float3 bsdf_glossy_toon_eval_reflect(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) +ccl_device Spectrum bsdf_glossy_toon_eval_reflect(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) { ccl_private const ToonBsdf *bsdf = (ccl_private const ToonBsdf *)sc; float max_angle = bsdf->size * M_PI_2_F; @@ -153,23 +153,23 @@ ccl_device float3 bsdf_glossy_toon_eval_reflect(ccl_private const ShaderClosure float angle = safe_acosf(fmaxf(cosRI, 0.0f)); - float3 eval = bsdf_toon_get_intensity(max_angle, smooth, angle); + float eval = bsdf_toon_get_intensity(max_angle, smooth, angle); float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth); *pdf = 0.5f * M_1_PI_F / (1.0f - cosf(sample_angle)); - return *pdf * eval; + return make_spectrum(*pdf * eval); } *pdf = 0.0f; - return make_float3(0.0f, 0.0f, 0.0f); + return zero_spectrum(); } -ccl_device float3 bsdf_glossy_toon_eval_transmit(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) +ccl_device Spectrum bsdf_glossy_toon_eval_transmit(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) { *pdf = 0.0f; - return make_float3(0.0f, 0.0f, 0.0f); + return zero_spectrum(); } ccl_device int bsdf_glossy_toon_sample(ccl_private const ShaderClosure *sc, @@ -179,7 +179,7 @@ ccl_device int bsdf_glossy_toon_sample(ccl_private const ShaderClosure *sc, float3 dIdy, float randu, float randv, - ccl_private float3 *eval, + ccl_private Spectrum *eval, ccl_private float3 *omega_in, ccl_private float3 *domega_in_dx, ccl_private float3 *domega_in_dy, @@ -204,7 +204,7 @@ ccl_device int bsdf_glossy_toon_sample(ccl_private const ShaderClosure *sc, /* 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); + *eval = make_spectrum(*pdf * bsdf_toon_get_intensity(max_angle, smooth, angle)); #ifdef __RAY_DIFFERENTIALS__ *domega_in_dx = (2 * dot(bsdf->N, dIdx)) * bsdf->N - dIdx; @@ -213,12 +213,12 @@ ccl_device int bsdf_glossy_toon_sample(ccl_private const ShaderClosure *sc, } else { *pdf = 0.0f; - *eval = make_float3(0.0f, 0.0f, 0.0f); + *eval = zero_spectrum(); } } else { *pdf = 0.0f; - *eval = make_float3(0.0f, 0.0f, 0.0f); + *eval = zero_spectrum(); } } diff --git a/intern/cycles/kernel/closure/bsdf_transparent.h b/intern/cycles/kernel/closure/bsdf_transparent.h index 636d9d664f2..89b36c709e4 100644 --- a/intern/cycles/kernel/closure/bsdf_transparent.h +++ b/intern/cycles/kernel/closure/bsdf_transparent.h @@ -11,7 +11,7 @@ CCL_NAMESPACE_BEGIN ccl_device void bsdf_transparent_setup(ccl_private ShaderData *sd, - const float3 weight, + const Spectrum weight, uint32_t path_flag) { /* Check cutoff weight. */ @@ -59,22 +59,22 @@ ccl_device void bsdf_transparent_setup(ccl_private ShaderData *sd, } } -ccl_device float3 bsdf_transparent_eval_reflect(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) +ccl_device Spectrum bsdf_transparent_eval_reflect(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) { *pdf = 0.0f; - return make_float3(0.0f, 0.0f, 0.0f); + return zero_spectrum(); } -ccl_device float3 bsdf_transparent_eval_transmit(ccl_private const ShaderClosure *sc, - const float3 I, - const float3 omega_in, - ccl_private float *pdf) +ccl_device Spectrum bsdf_transparent_eval_transmit(ccl_private const ShaderClosure *sc, + const float3 I, + const float3 omega_in, + ccl_private float *pdf) { *pdf = 0.0f; - return make_float3(0.0f, 0.0f, 0.0f); + return zero_spectrum(); } ccl_device int bsdf_transparent_sample(ccl_private const ShaderClosure *sc, @@ -84,7 +84,7 @@ ccl_device int bsdf_transparent_sample(ccl_private const ShaderClosure *sc, float3 dIdy, float randu, float randv, - ccl_private float3 *eval, + ccl_private Spectrum *eval, ccl_private float3 *omega_in, ccl_private float3 *domega_in_dx, ccl_private float3 *domega_in_dy, @@ -97,7 +97,7 @@ ccl_device int bsdf_transparent_sample(ccl_private const ShaderClosure *sc, *domega_in_dy = -dIdy; #endif *pdf = 1; - *eval = make_float3(1, 1, 1); + *eval = one_spectrum(); return LABEL_TRANSMIT | LABEL_TRANSPARENT; } diff --git a/intern/cycles/kernel/closure/bsdf_util.h b/intern/cycles/kernel/closure/bsdf_util.h index e3b24d487f1..10f2643721e 100644 --- a/intern/cycles/kernel/closure/bsdf_util.h +++ b/intern/cycles/kernel/closure/bsdf_util.h @@ -110,8 +110,8 @@ ccl_device float schlick_fresnel(float u) } /* Calculate the fresnel color which is a blend between white and the F0 color (cspec0) */ -ccl_device_forceinline float3 -interpolate_fresnel_color(float3 L, float3 H, float ior, float F0, float3 cspec0) +ccl_device_forceinline Spectrum +interpolate_fresnel_color(float3 L, float3 H, float ior, float F0, Spectrum cspec0) { /* Calculate the fresnel interpolation factor * The value from fresnel_dielectric_cos(...) has to be normalized because @@ -121,7 +121,7 @@ interpolate_fresnel_color(float3 L, float3 H, float ior, float F0, float3 cspec0 float FH = (fresnel_dielectric_cos(dot(L, H), ior) - F0) * F0_norm; /* Blend between white and a specular color with respect to the fresnel */ - return cspec0 * (1.0f - FH) + make_float3(1.0f, 1.0f, 1.0f) * FH; + return cspec0 * (1.0f - FH) + make_spectrum(FH); } ccl_device float3 ensure_valid_reflection(float3 Ng, float3 I, float3 N) diff --git a/intern/cycles/kernel/closure/bssrdf.h b/intern/cycles/kernel/closure/bssrdf.h index b87790f5f8a..cdd4d128c1f 100644 --- a/intern/cycles/kernel/closure/bssrdf.h +++ b/intern/cycles/kernel/closure/bssrdf.h @@ -8,8 +8,8 @@ CCL_NAMESPACE_BEGIN typedef struct Bssrdf { SHADER_CLOSURE_BASE; - float3 radius; - float3 albedo; + Spectrum radius; + Spectrum albedo; float roughness; float anisotropy; } Bssrdf; @@ -69,12 +69,13 @@ ccl_device void bssrdf_setup_radius(ccl_private Bssrdf *bssrdf, const float fourthirdA = (4.0f / 3.0f) * (1.0f + F_dr) / (1.0f - F_dr); /* From Jensen's `Fdr` ratio formula. */ - const float3 alpha_prime = make_float3( - bssrdf_dipole_compute_alpha_prime(bssrdf->albedo.x, fourthirdA), - bssrdf_dipole_compute_alpha_prime(bssrdf->albedo.y, fourthirdA), - bssrdf_dipole_compute_alpha_prime(bssrdf->albedo.z, fourthirdA)); + Spectrum alpha_prime; + FOREACH_SPECTRUM_CHANNEL (i) { + GET_SPECTRUM_CHANNEL(alpha_prime, i) = bssrdf_dipole_compute_alpha_prime( + GET_SPECTRUM_CHANNEL(bssrdf->albedo, i), fourthirdA); + } - bssrdf->radius *= sqrt(3.0f * (one_float3() - alpha_prime)); + bssrdf->radius *= sqrt(3.0f * (one_spectrum() - alpha_prime)); } } @@ -98,7 +99,7 @@ ccl_device_inline float bssrdf_burley_fitting(float A) /* Scale mean free path length so it gives similar looking result * to Cubic and Gaussian models. */ -ccl_device_inline float3 bssrdf_burley_compatible_mfp(float3 r) +ccl_device_inline Spectrum bssrdf_burley_compatible_mfp(Spectrum r) { return 0.25f * M_1_PI_F * r; } @@ -106,11 +107,13 @@ ccl_device_inline float3 bssrdf_burley_compatible_mfp(float3 r) ccl_device void bssrdf_burley_setup(ccl_private Bssrdf *bssrdf) { /* Mean free path length. */ - const float3 l = bssrdf_burley_compatible_mfp(bssrdf->radius); + const Spectrum l = bssrdf_burley_compatible_mfp(bssrdf->radius); /* Surface albedo. */ - const float3 A = bssrdf->albedo; - const float3 s = make_float3( - bssrdf_burley_fitting(A.x), bssrdf_burley_fitting(A.y), bssrdf_burley_fitting(A.z)); + const Spectrum A = bssrdf->albedo; + Spectrum s; + FOREACH_SPECTRUM_CHANNEL (i) { + GET_SPECTRUM_CHANNEL(s, i) = bssrdf_burley_fitting(GET_SPECTRUM_CHANNEL(A, i)); + } bssrdf->radius = l / s; } @@ -198,22 +201,18 @@ ccl_device void bssrdf_burley_sample(const float d, *h = safe_sqrtf(Rm * Rm - r_ * r_); } -ccl_device float bssrdf_num_channels(const float3 radius) +ccl_device float bssrdf_num_channels(const Spectrum radius) { float channels = 0; - if (radius.x > 0.0f) { - channels += 1.0f; - } - if (radius.y > 0.0f) { - channels += 1.0f; - } - if (radius.z > 0.0f) { - channels += 1.0f; + FOREACH_SPECTRUM_CHANNEL (i) { + if (GET_SPECTRUM_CHANNEL(radius, i) > 0.0f) { + channels += 1.0f; + } } return channels; } -ccl_device void bssrdf_sample(const float3 radius, +ccl_device void bssrdf_sample(const Spectrum radius, float xi, ccl_private float *r, ccl_private float *h) @@ -224,39 +223,44 @@ ccl_device void bssrdf_sample(const float3 radius, /* Sample color channel and reuse random number. Only a subset of channels * may be used if their radius was too small to handle as BSSRDF. */ xi *= num_channels; - - if (xi < 1.0f) { - sampled_radius = (radius.x > 0.0f) ? radius.x : (radius.y > 0.0f) ? radius.y : radius.z; - } - else if (xi < 2.0f) { - xi -= 1.0f; - sampled_radius = (radius.x > 0.0f && radius.y > 0.0f) ? radius.y : radius.z; - } - else { - xi -= 2.0f; - sampled_radius = radius.z; + sampled_radius = 0.0f; + + float sum = 0.0f; + FOREACH_SPECTRUM_CHANNEL (i) { + const float channel_radius = GET_SPECTRUM_CHANNEL(radius, i); + if (channel_radius > 0.0f) { + const float next_sum = sum + 1.0f; + if (xi < next_sum) { + xi -= sum; + sampled_radius = channel_radius; + break; + } + sum = next_sum; + } } /* Sample BSSRDF. */ bssrdf_burley_sample(sampled_radius, xi, r, h); } -ccl_device_forceinline float3 bssrdf_eval(const float3 radius, float r) +ccl_device_forceinline Spectrum bssrdf_eval(const Spectrum radius, float r) { - return make_float3(bssrdf_burley_pdf(radius.x, r), - bssrdf_burley_pdf(radius.y, r), - bssrdf_burley_pdf(radius.z, r)); + Spectrum result; + FOREACH_SPECTRUM_CHANNEL (i) { + GET_SPECTRUM_CHANNEL(result, i) = bssrdf_burley_pdf(GET_SPECTRUM_CHANNEL(radius, i), r); + } + return result; } -ccl_device_forceinline float bssrdf_pdf(const float3 radius, float r) +ccl_device_forceinline float bssrdf_pdf(const Spectrum radius, float r) { - float3 pdf = bssrdf_eval(radius, r); - return (pdf.x + pdf.y + pdf.z) / bssrdf_num_channels(radius); + Spectrum pdf = bssrdf_eval(radius, r); + return reduce_add(pdf) / bssrdf_num_channels(radius); } /* Setup */ -ccl_device_inline ccl_private Bssrdf *bssrdf_alloc(ccl_private ShaderData *sd, float3 weight) +ccl_device_inline ccl_private Bssrdf *bssrdf_alloc(ccl_private ShaderData *sd, Spectrum weight) { ccl_private Bssrdf *bssrdf = (ccl_private Bssrdf *)closure_alloc( sd, sizeof(Bssrdf), CLOSURE_NONE_ID, weight); @@ -294,29 +298,19 @@ ccl_device int bssrdf_setup(ccl_private ShaderData *sd, } /* Verify if the radii are large enough to sample without precision issues. */ - int bssrdf_channels = 3; - float3 diffuse_weight = make_float3(0.0f, 0.0f, 0.0f); - - if (bssrdf->radius.x < BSSRDF_MIN_RADIUS) { - diffuse_weight.x = bssrdf->weight.x; - bssrdf->weight.x = 0.0f; - bssrdf->radius.x = 0.0f; - bssrdf_channels--; - } - if (bssrdf->radius.y < BSSRDF_MIN_RADIUS) { - diffuse_weight.y = bssrdf->weight.y; - bssrdf->weight.y = 0.0f; - bssrdf->radius.y = 0.0f; - bssrdf_channels--; - } - if (bssrdf->radius.z < BSSRDF_MIN_RADIUS) { - diffuse_weight.z = bssrdf->weight.z; - bssrdf->weight.z = 0.0f; - bssrdf->radius.z = 0.0f; - bssrdf_channels--; + int bssrdf_channels = SPECTRUM_CHANNELS; + Spectrum diffuse_weight = zero_spectrum(); + + FOREACH_SPECTRUM_CHANNEL (i) { + if (GET_SPECTRUM_CHANNEL(bssrdf->radius, i) < BSSRDF_MIN_RADIUS) { + GET_SPECTRUM_CHANNEL(diffuse_weight, i) = GET_SPECTRUM_CHANNEL(bssrdf->weight, i); + GET_SPECTRUM_CHANNEL(bssrdf->weight, i) = 0.0f; + GET_SPECTRUM_CHANNEL(bssrdf->radius, i) = 0.0f; + bssrdf_channels--; + } } - if (bssrdf_channels < 3) { + if (bssrdf_channels < SPECTRUM_CHANNELS) { /* Add diffuse BSDF if any radius too small. */ #ifdef __PRINCIPLED__ if (bssrdf->roughness != FLT_MAX) { diff --git a/intern/cycles/kernel/closure/emissive.h b/intern/cycles/kernel/closure/emissive.h index 03e19cbde21..d896721f77b 100644 --- a/intern/cycles/kernel/closure/emissive.h +++ b/intern/cycles/kernel/closure/emissive.h @@ -12,7 +12,7 @@ CCL_NAMESPACE_BEGIN /* BACKGROUND CLOSURE */ -ccl_device void background_setup(ccl_private ShaderData *sd, const float3 weight) +ccl_device void background_setup(ccl_private ShaderData *sd, const Spectrum weight) { if (sd->flag & SD_EMISSION) { sd->closure_emission_background += weight; @@ -25,7 +25,7 @@ ccl_device void background_setup(ccl_private ShaderData *sd, const float3 weight /* EMISSION CLOSURE */ -ccl_device void emission_setup(ccl_private ShaderData *sd, const float3 weight) +ccl_device void emission_setup(ccl_private ShaderData *sd, const Spectrum weight) { if (sd->flag & SD_EMISSION) { sd->closure_emission_background += weight; @@ -54,11 +54,11 @@ ccl_device void emissive_sample(const float3 Ng, /* todo: not implemented and used yet */ } -ccl_device float3 emissive_simple_eval(const float3 Ng, const float3 I) +ccl_device Spectrum emissive_simple_eval(const float3 Ng, const float3 I) { float res = emissive_pdf(Ng, I); - return make_float3(res, res, res); + return make_spectrum(res); } CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/closure/volume.h b/intern/cycles/kernel/closure/volume.h index ef414c7b821..10494be87cb 100644 --- a/intern/cycles/kernel/closure/volume.h +++ b/intern/cycles/kernel/closure/volume.h @@ -7,7 +7,7 @@ CCL_NAMESPACE_BEGIN /* VOLUME EXTINCTION */ -ccl_device void volume_extinction_setup(ccl_private ShaderData *sd, float3 weight) +ccl_device void volume_extinction_setup(ccl_private ShaderData *sd, Spectrum weight) { if (sd->flag & SD_EXTINCTION) { sd->closure_transparent_extinction += weight; @@ -48,10 +48,10 @@ ccl_device int volume_henyey_greenstein_setup(ccl_private HenyeyGreensteinVolume return SD_SCATTER; } -ccl_device float3 volume_henyey_greenstein_eval_phase(ccl_private const ShaderVolumeClosure *svc, - const float3 I, - float3 omega_in, - ccl_private float *pdf) +ccl_device Spectrum volume_henyey_greenstein_eval_phase(ccl_private const ShaderVolumeClosure *svc, + const float3 I, + float3 omega_in, + ccl_private float *pdf) { float g = svc->g; @@ -64,7 +64,7 @@ ccl_device float3 volume_henyey_greenstein_eval_phase(ccl_private const ShaderVo *pdf = single_peaked_henyey_greenstein(cos_theta, g); } - return make_float3(*pdf, *pdf, *pdf); + return make_spectrum(*pdf); } ccl_device float3 @@ -105,7 +105,7 @@ ccl_device int volume_henyey_greenstein_sample(ccl_private const ShaderVolumeClo float3 dIdy, float randu, float randv, - ccl_private float3 *eval, + ccl_private Spectrum *eval, ccl_private float3 *omega_in, ccl_private float3 *domega_in_dx, ccl_private float3 *domega_in_dy, @@ -115,7 +115,7 @@ ccl_device int volume_henyey_greenstein_sample(ccl_private const ShaderVolumeClo /* note that I points towards the viewer and so is used negated */ *omega_in = henyey_greenstrein_sample(-I, g, randu, randv, pdf); - *eval = make_float3(*pdf, *pdf, *pdf); /* perfect importance sampling */ + *eval = make_spectrum(*pdf); /* perfect importance sampling */ #ifdef __RAY_DIFFERENTIALS__ /* todo: implement ray differential estimation */ @@ -128,10 +128,10 @@ ccl_device int volume_henyey_greenstein_sample(ccl_private const ShaderVolumeClo /* VOLUME CLOSURE */ -ccl_device float3 volume_phase_eval(ccl_private const ShaderData *sd, - ccl_private const ShaderVolumeClosure *svc, - float3 omega_in, - ccl_private float *pdf) +ccl_device Spectrum volume_phase_eval(ccl_private const ShaderData *sd, + ccl_private const ShaderVolumeClosure *svc, + float3 omega_in, + ccl_private float *pdf) { return volume_henyey_greenstein_eval_phase(svc, sd->I, omega_in, pdf); } @@ -140,7 +140,7 @@ ccl_device int volume_phase_sample(ccl_private const ShaderData *sd, ccl_private const ShaderVolumeClosure *svc, float randu, float randv, - ccl_private float3 *eval, + ccl_private Spectrum *eval, ccl_private float3 *omega_in, ccl_private differential3 *domega_in, ccl_private float *pdf) @@ -164,45 +164,44 @@ ccl_device int volume_phase_sample(ccl_private const ShaderData *sd, * unnecessary work in volumes and subsurface scattering. */ #define VOLUME_THROUGHPUT_EPSILON 1e-6f -ccl_device float3 volume_color_transmittance(float3 sigma, float t) +ccl_device Spectrum volume_color_transmittance(Spectrum sigma, float t) { return exp(-sigma * t); } -ccl_device float volume_channel_get(float3 value, int channel) +ccl_device float volume_channel_get(Spectrum value, int channel) { - return (channel == 0) ? value.x : ((channel == 1) ? value.y : value.z); + return GET_SPECTRUM_CHANNEL(value, channel); } -ccl_device int volume_sample_channel(float3 albedo, - float3 throughput, +ccl_device int volume_sample_channel(Spectrum albedo, + Spectrum throughput, float rand, - ccl_private float3 *pdf) + ccl_private Spectrum *pdf) { /* Sample color channel proportional to throughput and single scattering * albedo, to significantly reduce noise with many bounce, following: * * "Practical and Controllable Subsurface Scattering for Production Path * Tracing". Matt Jen-Yuan Chiang, Peter Kutz, Brent Burley. SIGGRAPH 2016. */ - float3 weights = fabs(throughput * albedo); - float sum_weights = weights.x + weights.y + weights.z; + Spectrum weights = fabs(throughput * albedo); + float sum_weights = reduce_add(weights); if (sum_weights > 0.0f) { *pdf = weights / sum_weights; } else { - *pdf = make_float3(1.0f / 3.0f, 1.0f / 3.0f, 1.0f / 3.0f); + *pdf = make_spectrum(1.0f / SPECTRUM_CHANNELS); } - if (rand < pdf->x) { - return 0; - } - else if (rand < pdf->x + pdf->y) { - return 1; - } - else { - return 2; + float pdf_sum = 0.0f; + FOREACH_SPECTRUM_CHANNEL (i) { + pdf_sum += GET_SPECTRUM_CHANNEL(*pdf, i); + if (rand < pdf_sum) { + return i; + } } + return SPECTRUM_CHANNELS - 1; } CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/device/cpu/compat.h b/intern/cycles/kernel/device/cpu/compat.h index 631e55e0d42..1e3e790ca1f 100644 --- a/intern/cycles/kernel/device/cpu/compat.h +++ b/intern/cycles/kernel/device/cpu/compat.h @@ -33,38 +33,4 @@ CCL_NAMESPACE_BEGIN #define kernel_assert(cond) assert(cond) -/* Macros to handle different memory storage on different devices */ - -#ifdef __KERNEL_SSE2__ -typedef vector3<sseb> sse3b; -typedef vector3<ssef> sse3f; -typedef vector3<ssei> sse3i; - -ccl_device_inline void print_sse3b(const char *label, sse3b &a) -{ - print_sseb(label, a.x); - print_sseb(label, a.y); - print_sseb(label, a.z); -} - -ccl_device_inline void print_sse3f(const char *label, sse3f &a) -{ - print_ssef(label, a.x); - print_ssef(label, a.y); - print_ssef(label, a.z); -} - -ccl_device_inline void print_sse3i(const char *label, sse3i &a) -{ - print_ssei(label, a.x); - print_ssei(label, a.y); - print_ssei(label, a.z); -} - -# if defined(__KERNEL_AVX__) || defined(__KERNEL_AVX2__) -typedef vector3<avxf> avx3f; -# endif - -#endif - CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/device/metal/compat.h b/intern/cycles/kernel/device/metal/compat.h index 80ee8ef5b57..b20cfca9a9c 100644 --- a/intern/cycles/kernel/device/metal/compat.h +++ b/intern/cycles/kernel/device/metal/compat.h @@ -189,35 +189,46 @@ void kernel_gpu_##name::run(thread MetalKernelContext& context, \ } volume_write_lambda_pass{kg, this, state}; /* make_type definitions with Metal style element initializers */ -#ifdef make_float2 -# undef make_float2 -#endif -#ifdef make_float3 -# undef make_float3 -#endif -#ifdef make_float4 -# undef make_float4 -#endif -#ifdef make_int2 -# undef make_int2 -#endif -#ifdef make_int3 -# undef make_int3 -#endif -#ifdef make_int4 -# undef make_int4 -#endif -#ifdef make_uchar4 -# undef make_uchar4 -#endif - -#define make_float2(x, y) float2(x, y) -#define make_float3(x, y, z) float3(x, y, z) -#define make_float4(x, y, z, w) float4(x, y, z, w) -#define make_int2(x, y) int2(x, y) -#define make_int3(x, y, z) int3(x, y, z) -#define make_int4(x, y, z, w) int4(x, y, z, w) -#define make_uchar4(x, y, z, w) uchar4(x, y, z, w) +ccl_device_forceinline float2 make_float2(const float x, const float y) +{ + return float2(x, y); +} + +ccl_device_forceinline float3 make_float3(const float x, const float y, const float z) +{ + return float3(x, y, z); +} + +ccl_device_forceinline float4 make_float4(const float x, + const float y, + const float z, + const float w) +{ + return float4(x, y, z, w); +} + +ccl_device_forceinline int2 make_int2(const int x, const int y) +{ + return int2(x, y); +} + +ccl_device_forceinline int3 make_int3(const int x, const int y, const int z) +{ + return int3(x, y, z); +} + +ccl_device_forceinline int4 make_int4(const int x, const int y, const int z, const int w) +{ + return int4(x, y, z, w); +} + +ccl_device_forceinline uchar4 make_uchar4(const uchar x, + const uchar y, + const uchar z, + const uchar w) +{ + return uchar4(x, y, z, w); +} /* Math functions */ diff --git a/intern/cycles/kernel/device/oneapi/compat.h b/intern/cycles/kernel/device/oneapi/compat.h index d8234ee1400..5c49674f247 100644 --- a/intern/cycles/kernel/device/oneapi/compat.h +++ b/intern/cycles/kernel/device/oneapi/compat.h @@ -149,25 +149,13 @@ void oneapi_kernel_##name(KernelGlobalsGPU *ccl_restrict kg, \ /* clang-format on */ /* Types */ + /* It's not possible to use sycl types like sycl::float3, sycl::int3, etc - * because these types have different interfaces from blender version */ + * because these types have different interfaces from blender version. */ using uchar = unsigned char; using sycl::half; -struct float3 { - float x, y, z; -}; - -ccl_always_inline float3 make_float3(float x, float y, float z) -{ - return {x, y, z}; -} -ccl_always_inline float3 make_float3(float x) -{ - return {x, x, x}; -} - /* math functions */ #define fabsf(x) sycl::fabs((x)) #define copysignf(x, y) sycl::copysign((x), (y)) diff --git a/intern/cycles/kernel/film/accumulate.h b/intern/cycles/kernel/film/accumulate.h index 33c35a68ad0..97ec915a8ad 100644 --- a/intern/cycles/kernel/film/accumulate.h +++ b/intern/cycles/kernel/film/accumulate.h @@ -21,10 +21,10 @@ CCL_NAMESPACE_BEGIN ccl_device_inline void bsdf_eval_init(ccl_private BsdfEval *eval, const ClosureType closure_type, - float3 value) + Spectrum value) { - eval->diffuse = zero_float3(); - eval->glossy = zero_float3(); + eval->diffuse = zero_spectrum(); + eval->glossy = zero_spectrum(); if (CLOSURE_IS_BSDF_DIFFUSE(closure_type)) { eval->diffuse = value; @@ -38,7 +38,7 @@ ccl_device_inline void bsdf_eval_init(ccl_private BsdfEval *eval, ccl_device_inline void bsdf_eval_accum(ccl_private BsdfEval *eval, const ClosureType closure_type, - float3 value) + Spectrum value) { if (CLOSURE_IS_BSDF_DIFFUSE(closure_type)) { eval->diffuse += value; @@ -62,26 +62,26 @@ ccl_device_inline void bsdf_eval_mul(ccl_private BsdfEval *eval, float value) eval->sum *= value; } -ccl_device_inline void bsdf_eval_mul(ccl_private BsdfEval *eval, float3 value) +ccl_device_inline void bsdf_eval_mul(ccl_private BsdfEval *eval, Spectrum value) { eval->diffuse *= value; eval->glossy *= value; eval->sum *= value; } -ccl_device_inline float3 bsdf_eval_sum(ccl_private const BsdfEval *eval) +ccl_device_inline Spectrum bsdf_eval_sum(ccl_private const BsdfEval *eval) { return eval->sum; } -ccl_device_inline float3 bsdf_eval_pass_diffuse_weight(ccl_private const BsdfEval *eval) +ccl_device_inline Spectrum bsdf_eval_pass_diffuse_weight(ccl_private const BsdfEval *eval) { /* Ratio of diffuse weight to recover proportions for writing to render pass. * We assume reflection, transmission and volume scatter to be exclusive. */ return safe_divide(eval->diffuse, eval->sum); } -ccl_device_inline float3 bsdf_eval_pass_glossy_weight(ccl_private const BsdfEval *eval) +ccl_device_inline Spectrum bsdf_eval_pass_glossy_weight(ccl_private const BsdfEval *eval) { /* Ratio of glossy weight to recover proportions for writing to render pass. * We assume reflection, transmission and volume scatter to be exclusive. */ @@ -95,7 +95,9 @@ ccl_device_inline float3 bsdf_eval_pass_glossy_weight(ccl_private const BsdfEval * to render buffers instead of using per-thread memory, and to avoid the * impact of clamping on other contributions. */ -ccl_device_forceinline void kernel_accum_clamp(KernelGlobals kg, ccl_private float3 *L, int bounce) +ccl_device_forceinline void kernel_accum_clamp(KernelGlobals kg, + ccl_private Spectrum *L, + int bounce) { #ifdef __KERNEL_DEBUG_NAN__ if (!isfinite_safe(*L)) { @@ -154,7 +156,7 @@ ccl_device_inline int kernel_accum_sample(KernelGlobals kg, ccl_device void kernel_accum_adaptive_buffer(KernelGlobals kg, const int sample, - const float3 contribution, + const Spectrum contribution, ccl_global float *ccl_restrict buffer) { /* Adaptive Sampling. Fill the additional buffer with the odd samples and calculate our stopping @@ -167,9 +169,13 @@ ccl_device void kernel_accum_adaptive_buffer(KernelGlobals kg, } if (sample_is_even(kernel_data.integrator.sampling_pattern, sample)) { - kernel_write_pass_float4( - buffer + kernel_data.film.pass_adaptive_aux_buffer, - make_float4(contribution.x * 2.0f, contribution.y * 2.0f, contribution.z * 2.0f, 0.0f)); + const float3 contribution_rgb = spectrum_to_rgb(contribution); + + kernel_write_pass_float4(buffer + kernel_data.film.pass_adaptive_aux_buffer, + make_float4(contribution_rgb.x * 2.0f, + contribution_rgb.y * 2.0f, + contribution_rgb.z * 2.0f, + 0.0f)); } } @@ -186,7 +192,7 @@ ccl_device void kernel_accum_adaptive_buffer(KernelGlobals kg, ccl_device bool kernel_accum_shadow_catcher(KernelGlobals kg, const uint32_t path_flag, - const float3 contribution, + const Spectrum contribution, ccl_global float *ccl_restrict buffer) { if (!kernel_data.integrator.has_shadow_catcher) { @@ -198,7 +204,7 @@ ccl_device bool kernel_accum_shadow_catcher(KernelGlobals kg, /* Matte pass. */ if (kernel_shadow_catcher_is_matte_path(path_flag)) { - kernel_write_pass_float3(buffer + kernel_data.film.pass_shadow_catcher_matte, contribution); + kernel_write_pass_spectrum(buffer + kernel_data.film.pass_shadow_catcher_matte, contribution); /* NOTE: Accumulate the combined pass and to the samples count pass, so that the adaptive * sampling is based on how noisy the combined pass is as if there were no catchers in the * scene. */ @@ -206,7 +212,7 @@ ccl_device bool kernel_accum_shadow_catcher(KernelGlobals kg, /* Shadow catcher pass. */ if (kernel_shadow_catcher_is_object_pass(path_flag)) { - kernel_write_pass_float3(buffer + kernel_data.film.pass_shadow_catcher, contribution); + kernel_write_pass_spectrum(buffer + kernel_data.film.pass_shadow_catcher, contribution); return true; } @@ -215,7 +221,7 @@ ccl_device bool kernel_accum_shadow_catcher(KernelGlobals kg, ccl_device bool kernel_accum_shadow_catcher_transparent(KernelGlobals kg, const uint32_t path_flag, - const float3 contribution, + const Spectrum contribution, const float transparent, ccl_global float *ccl_restrict buffer) { @@ -232,9 +238,11 @@ ccl_device bool kernel_accum_shadow_catcher_transparent(KernelGlobals kg, /* Matte pass. */ if (kernel_shadow_catcher_is_matte_path(path_flag)) { + const float3 contribution_rgb = spectrum_to_rgb(contribution); + kernel_write_pass_float4( buffer + kernel_data.film.pass_shadow_catcher_matte, - make_float4(contribution.x, contribution.y, contribution.z, transparent)); + make_float4(contribution_rgb.x, contribution_rgb.y, contribution_rgb.z, transparent)); /* NOTE: Accumulate the combined pass and to the samples count pass, so that the adaptive * sampling is based on how noisy the combined pass is as if there were no catchers in the * scene. */ @@ -245,7 +253,7 @@ ccl_device bool kernel_accum_shadow_catcher_transparent(KernelGlobals kg, /* NOTE: The transparency of the shadow catcher pass is ignored. It is not needed for the * calculation and the alpha channel of the pass contains numbers of samples contributed to a * pixel of the pass. */ - kernel_write_pass_float3(buffer + kernel_data.film.pass_shadow_catcher, contribution); + kernel_write_pass_spectrum(buffer + kernel_data.film.pass_shadow_catcher, contribution); return true; } @@ -279,7 +287,7 @@ ccl_device void kernel_accum_shadow_catcher_transparent_only(KernelGlobals kg, ccl_device_inline void kernel_accum_combined_pass(KernelGlobals kg, const uint32_t path_flag, const int sample, - const float3 contribution, + const Spectrum contribution, ccl_global float *ccl_restrict buffer) { #ifdef __SHADOW_CATCHER__ @@ -289,7 +297,7 @@ ccl_device_inline void kernel_accum_combined_pass(KernelGlobals kg, #endif if (kernel_data.film.light_pass_flag & PASSMASK(COMBINED)) { - kernel_write_pass_float3(buffer + kernel_data.film.pass_combined, contribution); + kernel_write_pass_spectrum(buffer + kernel_data.film.pass_combined, contribution); } kernel_accum_adaptive_buffer(kg, sample, contribution, buffer); @@ -299,7 +307,7 @@ ccl_device_inline void kernel_accum_combined_pass(KernelGlobals kg, ccl_device_inline void kernel_accum_combined_transparent_pass(KernelGlobals kg, const uint32_t path_flag, const int sample, - const float3 contribution, + const Spectrum contribution, const float transparent, ccl_global float *ccl_restrict buffer) @@ -311,9 +319,11 @@ ccl_device_inline void kernel_accum_combined_transparent_pass(KernelGlobals kg, #endif if (kernel_data.film.light_pass_flag & PASSMASK(COMBINED)) { + const float3 contribution_rgb = spectrum_to_rgb(contribution); + kernel_write_pass_float4( buffer + kernel_data.film.pass_combined, - make_float4(contribution.x, contribution.y, contribution.z, transparent)); + make_float4(contribution_rgb.x, contribution_rgb.y, contribution_rgb.z, transparent)); } kernel_accum_adaptive_buffer(kg, sample, contribution, buffer); @@ -323,7 +333,7 @@ ccl_device_inline void kernel_accum_combined_transparent_pass(KernelGlobals kg, ccl_device_inline void kernel_accum_emission_or_background_pass( KernelGlobals kg, ConstIntegratorState state, - float3 contribution, + Spectrum contribution, ccl_global float *ccl_restrict buffer, const int pass, const int lightgroup = LIGHTGROUP_NONE) @@ -340,17 +350,18 @@ ccl_device_inline void kernel_accum_emission_or_background_pass( # ifdef __DENOISING_FEATURES__ if (path_flag & PATH_RAY_DENOISING_FEATURES) { if (kernel_data.film.pass_denoising_albedo != PASS_UNUSED) { - const float3 denoising_feature_throughput = INTEGRATOR_STATE( + const Spectrum denoising_feature_throughput = INTEGRATOR_STATE( state, path, denoising_feature_throughput); - const float3 denoising_albedo = denoising_feature_throughput * contribution; - kernel_write_pass_float3(buffer + kernel_data.film.pass_denoising_albedo, denoising_albedo); + const Spectrum denoising_albedo = denoising_feature_throughput * contribution; + kernel_write_pass_spectrum(buffer + kernel_data.film.pass_denoising_albedo, + denoising_albedo); } } # endif /* __DENOISING_FEATURES__ */ if (lightgroup != LIGHTGROUP_NONE && kernel_data.film.pass_lightgroup != PASS_UNUSED) { - kernel_write_pass_float3(buffer + kernel_data.film.pass_lightgroup + 3 * lightgroup, - contribution); + kernel_write_pass_spectrum(buffer + kernel_data.film.pass_lightgroup + 3 * lightgroup, + contribution); } if (!(path_flag & PATH_RAY_ANY_PASS)) { @@ -366,15 +377,15 @@ ccl_device_inline void kernel_accum_emission_or_background_pass( if (path_flag & PATH_RAY_SURFACE_PASS) { /* Indirectly visible through reflection. */ - const float3 diffuse_weight = INTEGRATOR_STATE(state, path, pass_diffuse_weight); - const float3 glossy_weight = INTEGRATOR_STATE(state, path, pass_glossy_weight); + const Spectrum diffuse_weight = INTEGRATOR_STATE(state, path, pass_diffuse_weight); + const Spectrum glossy_weight = INTEGRATOR_STATE(state, path, pass_glossy_weight); /* Glossy */ const int glossy_pass_offset = ((INTEGRATOR_STATE(state, path, bounce) == 1) ? kernel_data.film.pass_glossy_direct : kernel_data.film.pass_glossy_indirect); if (glossy_pass_offset != PASS_UNUSED) { - kernel_write_pass_float3(buffer + glossy_pass_offset, glossy_weight * contribution); + kernel_write_pass_spectrum(buffer + glossy_pass_offset, glossy_weight * contribution); } /* Transmission */ @@ -385,9 +396,9 @@ ccl_device_inline void kernel_accum_emission_or_background_pass( if (transmission_pass_offset != PASS_UNUSED) { /* Transmission is what remains if not diffuse and glossy, not stored explicitly to save * GPU memory. */ - const float3 transmission_weight = one_float3() - diffuse_weight - glossy_weight; - kernel_write_pass_float3(buffer + transmission_pass_offset, - transmission_weight * contribution); + const Spectrum transmission_weight = one_spectrum() - diffuse_weight - glossy_weight; + kernel_write_pass_spectrum(buffer + transmission_pass_offset, + transmission_weight * contribution); } /* Reconstruct diffuse subset of throughput. */ @@ -408,7 +419,7 @@ ccl_device_inline void kernel_accum_emission_or_background_pass( /* Single write call for GPU coherence. */ if (pass_offset != PASS_UNUSED) { - kernel_write_pass_float3(buffer + pass_offset, contribution); + kernel_write_pass_spectrum(buffer + pass_offset, contribution); } #endif /* __PASSES__ */ } @@ -419,7 +430,7 @@ ccl_device_inline void kernel_accum_light(KernelGlobals kg, ccl_global float *ccl_restrict render_buffer) { /* The throughput for shadow paths already contains the light shader evaluation. */ - float3 contribution = INTEGRATOR_STATE(state, shadow_path, throughput); + Spectrum contribution = INTEGRATOR_STATE(state, shadow_path, throughput); kernel_accum_clamp(kg, &contribution, INTEGRATOR_STATE(state, shadow_path, bounce)); const uint32_t render_pixel_index = INTEGRATOR_STATE(state, shadow_path, render_pixel_index); @@ -433,10 +444,10 @@ ccl_device_inline void kernel_accum_light(KernelGlobals kg, /* Ambient occlusion. */ if (path_flag & PATH_RAY_SHADOW_FOR_AO) { if ((kernel_data.kernel_features & KERNEL_FEATURE_AO_PASS) && (path_flag & PATH_RAY_CAMERA)) { - kernel_write_pass_float3(buffer + kernel_data.film.pass_ao, contribution); + kernel_write_pass_spectrum(buffer + kernel_data.film.pass_ao, contribution); } if (kernel_data.kernel_features & KERNEL_FEATURE_AO_ADDITIVE) { - const float3 ao_weight = INTEGRATOR_STATE(state, shadow_path, unshadowed_throughput); + const Spectrum ao_weight = INTEGRATOR_STATE(state, shadow_path, unshadowed_throughput); kernel_accum_combined_pass(kg, path_flag, sample, contribution * ao_weight, buffer); } return; @@ -458,8 +469,8 @@ ccl_device_inline void kernel_accum_light(KernelGlobals kg, /* Write lightgroup pass. LIGHTGROUP_NONE is ~0 so decode from unsigned to signed */ const int lightgroup = (int)(INTEGRATOR_STATE(state, shadow_path, lightgroup)) - 1; if (lightgroup != LIGHTGROUP_NONE && kernel_data.film.pass_lightgroup != PASS_UNUSED) { - kernel_write_pass_float3(buffer + kernel_data.film.pass_lightgroup + 3 * lightgroup, - contribution); + kernel_write_pass_spectrum(buffer + kernel_data.film.pass_lightgroup + 3 * lightgroup, + contribution); } if (kernel_data.kernel_features & KERNEL_FEATURE_LIGHT_PASSES) { @@ -467,15 +478,15 @@ ccl_device_inline void kernel_accum_light(KernelGlobals kg, if (path_flag & PATH_RAY_SURFACE_PASS) { /* Indirectly visible through reflection. */ - const float3 diffuse_weight = INTEGRATOR_STATE(state, shadow_path, pass_diffuse_weight); - const float3 glossy_weight = INTEGRATOR_STATE(state, shadow_path, pass_glossy_weight); + const Spectrum diffuse_weight = INTEGRATOR_STATE(state, shadow_path, pass_diffuse_weight); + const Spectrum glossy_weight = INTEGRATOR_STATE(state, shadow_path, pass_glossy_weight); /* Glossy */ const int glossy_pass_offset = ((INTEGRATOR_STATE(state, shadow_path, bounce) == 0) ? kernel_data.film.pass_glossy_direct : kernel_data.film.pass_glossy_indirect); if (glossy_pass_offset != PASS_UNUSED) { - kernel_write_pass_float3(buffer + glossy_pass_offset, glossy_weight * contribution); + kernel_write_pass_spectrum(buffer + glossy_pass_offset, glossy_weight * contribution); } /* Transmission */ @@ -486,9 +497,9 @@ ccl_device_inline void kernel_accum_light(KernelGlobals kg, if (transmission_pass_offset != PASS_UNUSED) { /* Transmission is what remains if not diffuse and glossy, not stored explicitly to save * GPU memory. */ - const float3 transmission_weight = one_float3() - diffuse_weight - glossy_weight; - kernel_write_pass_float3(buffer + transmission_pass_offset, - transmission_weight * contribution); + const Spectrum transmission_weight = one_spectrum() - diffuse_weight - glossy_weight; + kernel_write_pass_spectrum(buffer + transmission_pass_offset, + transmission_weight * contribution); } /* Reconstruct diffuse subset of throughput. */ @@ -508,19 +519,19 @@ ccl_device_inline void kernel_accum_light(KernelGlobals kg, /* Single write call for GPU coherence. */ if (pass_offset != PASS_UNUSED) { - kernel_write_pass_float3(buffer + pass_offset, contribution); + kernel_write_pass_spectrum(buffer + pass_offset, contribution); } } /* Write shadow pass. */ if (kernel_data.film.pass_shadow != PASS_UNUSED && (path_flag & PATH_RAY_SHADOW_FOR_LIGHT) && (path_flag & PATH_RAY_TRANSPARENT_BACKGROUND)) { - const float3 unshadowed_throughput = INTEGRATOR_STATE( + const Spectrum unshadowed_throughput = INTEGRATOR_STATE( state, shadow_path, unshadowed_throughput); - const float3 shadowed_throughput = INTEGRATOR_STATE(state, shadow_path, throughput); - const float3 shadow = safe_divide(shadowed_throughput, unshadowed_throughput) * - kernel_data.film.pass_shadow_scale; - kernel_write_pass_float3(buffer + kernel_data.film.pass_shadow, shadow); + const Spectrum shadowed_throughput = INTEGRATOR_STATE(state, shadow_path, throughput); + const Spectrum shadow = safe_divide(shadowed_throughput, unshadowed_throughput) * + kernel_data.film.pass_shadow_scale; + kernel_write_pass_spectrum(buffer + kernel_data.film.pass_shadow, shadow); } } #endif @@ -560,12 +571,12 @@ ccl_device_inline void kernel_accum_holdout(KernelGlobals kg, * Includes transparency, matching kernel_accum_transparent. */ ccl_device_inline void kernel_accum_background(KernelGlobals kg, ConstIntegratorState state, - const float3 L, + const Spectrum L, const float transparent, const bool is_transparent_background_ray, ccl_global float *ccl_restrict render_buffer) { - float3 contribution = float3(INTEGRATOR_STATE(state, path, throughput)) * L; + Spectrum contribution = INTEGRATOR_STATE(state, path, throughput) * L; kernel_accum_clamp(kg, &contribution, INTEGRATOR_STATE(state, path, bounce) - 1); ccl_global float *buffer = kernel_accum_pixel_render_buffer(kg, state, render_buffer); @@ -590,11 +601,11 @@ ccl_device_inline void kernel_accum_background(KernelGlobals kg, /* Write emission to render buffer. */ ccl_device_inline void kernel_accum_emission(KernelGlobals kg, ConstIntegratorState state, - const float3 L, + const Spectrum L, ccl_global float *ccl_restrict render_buffer, const int lightgroup = LIGHTGROUP_NONE) { - float3 contribution = L; + Spectrum contribution = L; kernel_accum_clamp(kg, &contribution, INTEGRATOR_STATE(state, path, bounce) - 1); ccl_global float *buffer = kernel_accum_pixel_render_buffer(kg, state, render_buffer); diff --git a/intern/cycles/kernel/film/passes.h b/intern/cycles/kernel/film/passes.h index 1f5cf2048f1..bea23411000 100644 --- a/intern/cycles/kernel/film/passes.h +++ b/intern/cycles/kernel/film/passes.h @@ -40,7 +40,7 @@ ccl_device_forceinline void kernel_write_denoising_features_surface( ccl_global float *buffer = kernel_pass_pixel_render_buffer(kg, state, render_buffer); if (kernel_data.film.pass_denoising_depth != PASS_UNUSED) { - const float3 denoising_feature_throughput = INTEGRATOR_STATE( + const Spectrum denoising_feature_throughput = INTEGRATOR_STATE( state, path, denoising_feature_throughput); const float denoising_depth = ensure_finite(average(denoising_feature_throughput) * sd->ray_length); @@ -48,8 +48,8 @@ ccl_device_forceinline void kernel_write_denoising_features_surface( } float3 normal = zero_float3(); - float3 diffuse_albedo = zero_float3(); - float3 specular_albedo = zero_float3(); + Spectrum diffuse_albedo = zero_spectrum(); + Spectrum specular_albedo = zero_spectrum(); float sum_weight = 0.0f, sum_nonspecular_weight = 0.0f; for (int i = 0; i < sd->num_closure; i++) { @@ -63,7 +63,7 @@ ccl_device_forceinline void kernel_write_denoising_features_surface( normal += sc->N * sc->sample_weight; sum_weight += sc->sample_weight; - float3 closure_albedo = sc->weight; + Spectrum closure_albedo = sc->weight; /* Closures that include a Fresnel term typically have weights close to 1 even though their * actual contribution is significantly lower. * To account for this, we scale their weight by the average fresnel factor (the same is also @@ -113,10 +113,12 @@ ccl_device_forceinline void kernel_write_denoising_features_surface( } if (kernel_data.film.pass_denoising_albedo != PASS_UNUSED) { - const float3 denoising_feature_throughput = INTEGRATOR_STATE( + const Spectrum denoising_feature_throughput = INTEGRATOR_STATE( state, path, denoising_feature_throughput); - const float3 denoising_albedo = ensure_finite(denoising_feature_throughput * diffuse_albedo); - kernel_write_pass_float3(buffer + kernel_data.film.pass_denoising_albedo, denoising_albedo); + const Spectrum denoising_albedo = ensure_finite(denoising_feature_throughput * + diffuse_albedo); + kernel_write_pass_spectrum(buffer + kernel_data.film.pass_denoising_albedo, + denoising_albedo); } INTEGRATOR_STATE_WRITE(state, path, flag) &= ~PATH_RAY_DENOISING_FEATURES; @@ -128,13 +130,13 @@ ccl_device_forceinline void kernel_write_denoising_features_surface( ccl_device_forceinline void kernel_write_denoising_features_volume(KernelGlobals kg, IntegratorState state, - const float3 albedo, + const Spectrum albedo, const bool scatter, ccl_global float *ccl_restrict render_buffer) { ccl_global float *buffer = kernel_pass_pixel_render_buffer(kg, state, render_buffer); - const float3 denoising_feature_throughput = INTEGRATOR_STATE( + const Spectrum denoising_feature_throughput = INTEGRATOR_STATE( state, path, denoising_feature_throughput); if (scatter && kernel_data.film.pass_denoising_normal != PASS_UNUSED) { @@ -148,8 +150,8 @@ ccl_device_forceinline void kernel_write_denoising_features_volume(KernelGlobals if (kernel_data.film.pass_denoising_albedo != PASS_UNUSED) { /* Write albedo. */ - const float3 denoising_albedo = ensure_finite(denoising_feature_throughput * albedo); - kernel_write_pass_float3(buffer + kernel_data.film.pass_denoising_albedo, denoising_albedo); + const Spectrum denoising_albedo = ensure_finite(denoising_feature_throughput * albedo); + kernel_write_pass_spectrum(buffer + kernel_data.film.pass_denoising_albedo, denoising_albedo); } } #endif /* __DENOISING_FEATURES__ */ @@ -228,7 +230,7 @@ ccl_device_inline void kernel_write_data_passes(KernelGlobals kg, } if (kernel_data.film.cryptomatte_passes) { - const float3 throughput = INTEGRATOR_STATE(state, path, throughput); + const Spectrum throughput = INTEGRATOR_STATE(state, path, throughput); const float matte_weight = average(throughput) * (1.0f - average(shader_bsdf_transparency(kg, sd))); if (matte_weight > 0.0f) { @@ -252,19 +254,19 @@ ccl_device_inline void kernel_write_data_passes(KernelGlobals kg, } if (flag & PASSMASK(DIFFUSE_COLOR)) { - const float3 throughput = INTEGRATOR_STATE(state, path, throughput); - kernel_write_pass_float3(buffer + kernel_data.film.pass_diffuse_color, - shader_bsdf_diffuse(kg, sd) * throughput); + const Spectrum throughput = INTEGRATOR_STATE(state, path, throughput); + kernel_write_pass_spectrum(buffer + kernel_data.film.pass_diffuse_color, + shader_bsdf_diffuse(kg, sd) * throughput); } if (flag & PASSMASK(GLOSSY_COLOR)) { - const float3 throughput = INTEGRATOR_STATE(state, path, throughput); - kernel_write_pass_float3(buffer + kernel_data.film.pass_glossy_color, - shader_bsdf_glossy(kg, sd) * throughput); + const Spectrum throughput = INTEGRATOR_STATE(state, path, throughput); + kernel_write_pass_spectrum(buffer + kernel_data.film.pass_glossy_color, + shader_bsdf_glossy(kg, sd) * throughput); } if (flag & PASSMASK(TRANSMISSION_COLOR)) { - const float3 throughput = INTEGRATOR_STATE(state, path, throughput); - kernel_write_pass_float3(buffer + kernel_data.film.pass_transmission_color, - shader_bsdf_transmission(kg, sd) * throughput); + const Spectrum throughput = INTEGRATOR_STATE(state, path, throughput); + kernel_write_pass_spectrum(buffer + kernel_data.film.pass_transmission_color, + shader_bsdf_transmission(kg, sd) * throughput); } if (flag & PASSMASK(MIST)) { /* Bring depth into 0..1 range. */ @@ -287,8 +289,8 @@ ccl_device_inline void kernel_write_data_passes(KernelGlobals kg, mist = powf(mist, mist_falloff); /* Modulate by transparency */ - const float3 throughput = INTEGRATOR_STATE(state, path, throughput); - const float3 alpha = shader_bsdf_alpha(kg, sd); + const Spectrum throughput = INTEGRATOR_STATE(state, path, throughput); + const Spectrum alpha = shader_bsdf_alpha(kg, sd); const float mist_output = (1.0f - mist) * average(throughput * alpha); /* Note that the final value in the render buffer we want is 1 - mist_output, diff --git a/intern/cycles/kernel/film/write_passes.h b/intern/cycles/kernel/film/write_passes.h index 9148d73518f..c78116cedc6 100644 --- a/intern/cycles/kernel/film/write_passes.h +++ b/intern/cycles/kernel/film/write_passes.h @@ -3,6 +3,8 @@ #pragma once +#include "kernel/util/color.h" + #ifdef __KERNEL_GPU__ # define __ATOMIC_PASS_WRITE__ #endif @@ -36,6 +38,12 @@ ccl_device_inline void kernel_write_pass_float3(ccl_global float *ccl_restrict b #endif } +ccl_device_inline void kernel_write_pass_spectrum(ccl_global float *ccl_restrict buffer, + Spectrum value) +{ + kernel_write_pass_float3(buffer, spectrum_to_rgb(value)); +} + ccl_device_inline void kernel_write_pass_float4(ccl_global float *ccl_restrict buffer, float4 value) { diff --git a/intern/cycles/kernel/integrator/mnee.h b/intern/cycles/kernel/integrator/mnee.h index aa72b93c9d2..c95f1557f04 100644 --- a/intern/cycles/kernel/integrator/mnee.h +++ b/intern/cycles/kernel/integrator/mnee.h @@ -392,7 +392,7 @@ ccl_device_forceinline bool mnee_compute_constraint_derivatives( /* Invert (block) constraint derivative matrix and solve linear system so we can map dh back to dx: * dh / dx = A * dx = inverse(A) x dh - * to use for specular specular manifold walk + * to use for specular manifold walk * (See for example http://faculty.washington.edu/finlayso/ebook/algebraic/advanced/LUtri.htm * for block tridiagonal matrix based linear system solve) */ ccl_device_forceinline bool mnee_solve_matrix_h_to_x(int vertex_count, @@ -634,9 +634,9 @@ mnee_sample_bsdf_dh(ClosureType type, float alpha_x, float alpha_y, float sample * We assume here that the pdf (in half-vector measure) is the same as * the one calculation when sampling the microfacet normals from the * specular chain above: this allows us to simplify the bsdf weight */ -ccl_device_forceinline float3 mnee_eval_bsdf_contribution(ccl_private ShaderClosure *closure, - float3 wi, - float3 wo) +ccl_device_forceinline Spectrum mnee_eval_bsdf_contribution(ccl_private ShaderClosure *closure, + float3 wi, + float3 wo) { ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)closure; @@ -835,7 +835,7 @@ ccl_device_forceinline bool mnee_path_contribution(KernelGlobals kg, 1; INTEGRATOR_STATE_WRITE(state, path, bounce) = bounce + vertex_count; - float3 light_eval = light_sample_shader_eval(kg, state, sd_mnee, ls, sd->time); + Spectrum light_eval = light_sample_shader_eval(kg, state, sd_mnee, ls, sd->time); bsdf_eval_mul(throughput, light_eval / ls->pdf); /* Generalized geometry term. */ @@ -924,7 +924,7 @@ ccl_device_forceinline bool mnee_path_contribution(KernelGlobals kg, /* Evaluate product term inside eq.6 at solution interface. vi * divided by corresponding sampled pdf: * fr(vi)_do / pdf_dh(vi) x |do/dh| x |n.wo / n.h| */ - float3 bsdf_contribution = mnee_eval_bsdf_contribution(v.bsdf, wi, wo); + Spectrum bsdf_contribution = mnee_eval_bsdf_contribution(v.bsdf, wi, wo); bsdf_eval_mul(throughput, bsdf_contribution); } diff --git a/intern/cycles/kernel/integrator/path_state.h b/intern/cycles/kernel/integrator/path_state.h index b09bc117d78..5ec94b934ca 100644 --- a/intern/cycles/kernel/integrator/path_state.h +++ b/intern/cycles/kernel/integrator/path_state.h @@ -54,7 +54,7 @@ ccl_device_inline void path_state_init_integrator(KernelGlobals kg, INTEGRATOR_STATE_WRITE(state, path, mis_ray_pdf) = 0.0f; INTEGRATOR_STATE_WRITE(state, path, min_ray_pdf) = FLT_MAX; INTEGRATOR_STATE_WRITE(state, path, continuation_probability) = 1.0f; - INTEGRATOR_STATE_WRITE(state, path, throughput) = make_float3(1.0f, 1.0f, 1.0f); + INTEGRATOR_STATE_WRITE(state, path, throughput) = one_spectrum(); #ifdef __MNEE__ INTEGRATOR_STATE_WRITE(state, path, mnee) = 0; @@ -74,7 +74,7 @@ ccl_device_inline void path_state_init_integrator(KernelGlobals kg, #ifdef __DENOISING_FEATURES__ if (kernel_data.kernel_features & KERNEL_FEATURE_DENOISING) { INTEGRATOR_STATE_WRITE(state, path, flag) |= PATH_RAY_DENOISING_FEATURES; - INTEGRATOR_STATE_WRITE(state, path, denoising_feature_throughput) = one_float3(); + INTEGRATOR_STATE_WRITE(state, path, denoising_feature_throughput) = one_spectrum(); } #endif } diff --git a/intern/cycles/kernel/integrator/shade_background.h b/intern/cycles/kernel/integrator/shade_background.h index a7edfffd175..57d060d58df 100644 --- a/intern/cycles/kernel/integrator/shade_background.h +++ b/intern/cycles/kernel/integrator/shade_background.h @@ -10,9 +10,9 @@ CCL_NAMESPACE_BEGIN -ccl_device float3 integrator_eval_background_shader(KernelGlobals kg, - IntegratorState state, - ccl_global float *ccl_restrict render_buffer) +ccl_device Spectrum integrator_eval_background_shader(KernelGlobals kg, + IntegratorState state, + ccl_global float *ccl_restrict render_buffer) { #ifdef __BACKGROUND__ const int shader = kernel_data.background.surface_shader; @@ -26,11 +26,11 @@ ccl_device float3 integrator_eval_background_shader(KernelGlobals kg, ((shader & SHADER_EXCLUDE_TRANSMIT) && (path_flag & PATH_RAY_TRANSMIT)) || ((shader & SHADER_EXCLUDE_CAMERA) && (path_flag & PATH_RAY_CAMERA)) || ((shader & SHADER_EXCLUDE_SCATTER) && (path_flag & PATH_RAY_VOLUME_SCATTER))) - return zero_float3(); + return zero_spectrum(); } /* Use fast constant background color if available. */ - float3 L = zero_float3(); + Spectrum L = zero_spectrum(); if (!shader_constant_emission_eval(kg, shader, &L)) { /* Evaluate background shader. */ @@ -73,7 +73,7 @@ ccl_device float3 integrator_eval_background_shader(KernelGlobals kg, return L; #else - return make_float3(0.8f, 0.8f, 0.8f); + return make_spectrum(0.8f); #endif } @@ -117,8 +117,8 @@ ccl_device_inline void integrate_background(KernelGlobals kg, #endif /* __MNEE__ */ /* Evaluate background shader. */ - float3 L = (eval_background) ? integrator_eval_background_shader(kg, state, render_buffer) : - zero_float3(); + Spectrum L = (eval_background) ? integrator_eval_background_shader(kg, state, render_buffer) : + zero_spectrum(); /* When using the ao bounces approximation, adjust background * shader intensity with ao factor. */ @@ -169,7 +169,7 @@ ccl_device_inline void integrate_distant_lights(KernelGlobals kg, /* TODO: does aliasing like this break automatic SoA in CUDA? */ ShaderDataTinyStorage emission_sd_storage; ccl_private ShaderData *emission_sd = AS_SHADER_DATA(&emission_sd_storage); - float3 light_eval = light_sample_shader_eval(kg, state, emission_sd, &ls, ray_time); + Spectrum light_eval = light_sample_shader_eval(kg, state, emission_sd, &ls, ray_time); if (is_zero(light_eval)) { return; } @@ -184,7 +184,7 @@ ccl_device_inline void integrate_distant_lights(KernelGlobals kg, } /* Write to render buffer. */ - const float3 throughput = INTEGRATOR_STATE(state, path, throughput); + const Spectrum throughput = INTEGRATOR_STATE(state, path, throughput); kernel_accum_emission( kg, state, throughput * light_eval, render_buffer, kernel_data.background.lightgroup); } diff --git a/intern/cycles/kernel/integrator/shade_light.h b/intern/cycles/kernel/integrator/shade_light.h index 910e3383f51..ac9d1415abb 100644 --- a/intern/cycles/kernel/integrator/shade_light.h +++ b/intern/cycles/kernel/integrator/shade_light.h @@ -51,7 +51,7 @@ ccl_device_inline void integrate_light(KernelGlobals kg, /* TODO: does aliasing like this break automatic SoA in CUDA? */ ShaderDataTinyStorage emission_sd_storage; ccl_private ShaderData *emission_sd = AS_SHADER_DATA(&emission_sd_storage); - float3 light_eval = light_sample_shader_eval(kg, state, emission_sd, &ls, ray_time); + Spectrum light_eval = light_sample_shader_eval(kg, state, emission_sd, &ls, ray_time); if (is_zero(light_eval)) { return; } @@ -66,7 +66,7 @@ ccl_device_inline void integrate_light(KernelGlobals kg, } /* Write to render buffer. */ - const float3 throughput = INTEGRATOR_STATE(state, path, throughput); + const Spectrum throughput = INTEGRATOR_STATE(state, path, throughput); kernel_accum_emission(kg, state, throughput * light_eval, render_buffer, ls.group); } diff --git a/intern/cycles/kernel/integrator/shade_shadow.h b/intern/cycles/kernel/integrator/shade_shadow.h index 4b002a47bee..a52706a77f1 100644 --- a/intern/cycles/kernel/integrator/shade_shadow.h +++ b/intern/cycles/kernel/integrator/shade_shadow.h @@ -15,9 +15,9 @@ ccl_device_inline bool shadow_intersections_has_remaining(const uint num_hits) } #ifdef __TRANSPARENT_SHADOWS__ -ccl_device_inline float3 integrate_transparent_surface_shadow(KernelGlobals kg, - IntegratorShadowState state, - const int hit) +ccl_device_inline Spectrum integrate_transparent_surface_shadow(KernelGlobals kg, + IntegratorShadowState state, + const int hit) { PROFILING_INIT(kg, PROFILING_SHADE_SHADOW_SURFACE); @@ -58,7 +58,7 @@ ccl_device_inline void integrate_transparent_volume_shadow(KernelGlobals kg, IntegratorShadowState state, const int hit, const int num_recorded_hits, - ccl_private float3 *ccl_restrict + ccl_private Spectrum *ccl_restrict throughput) { PROFILING_INIT(kg, PROFILING_SHADE_SHADOW_VOLUME); @@ -100,7 +100,7 @@ ccl_device_inline bool integrate_transparent_shadow(KernelGlobals kg, if (hit < num_recorded_hits || !shadow_intersections_has_remaining(num_hits)) { # ifdef __VOLUME__ if (!integrator_state_shadow_volume_stack_is_empty(kg, state)) { - float3 throughput = INTEGRATOR_STATE(state, shadow_path, throughput); + Spectrum throughput = INTEGRATOR_STATE(state, shadow_path, throughput); integrate_transparent_volume_shadow(kg, state, hit, num_recorded_hits, &throughput); if (is_zero(throughput)) { return true; @@ -113,8 +113,8 @@ ccl_device_inline bool integrate_transparent_shadow(KernelGlobals kg, /* Surface shaders. */ if (hit < num_recorded_hits) { - const float3 shadow = integrate_transparent_surface_shadow(kg, state, hit); - const float3 throughput = INTEGRATOR_STATE(state, shadow_path, throughput) * shadow; + const Spectrum shadow = integrate_transparent_surface_shadow(kg, state, hit); + const Spectrum throughput = INTEGRATOR_STATE(state, shadow_path, throughput) * shadow; if (is_zero(throughput)) { return true; } diff --git a/intern/cycles/kernel/integrator/shade_surface.h b/intern/cycles/kernel/integrator/shade_surface.h index 19b8946e865..4eb50171532 100644 --- a/intern/cycles/kernel/integrator/shade_surface.h +++ b/intern/cycles/kernel/integrator/shade_surface.h @@ -44,7 +44,7 @@ ccl_device_forceinline float3 integrate_surface_ray_offset(KernelGlobals kg, /* Self intersection tests already account for the case where a ray hits the * same primitive. However precision issues can still cause neighboring * triangles to be hit. Here we test if the ray-triangle intersection with - * the same primitive would miss, implying that a neighbouring triangle would + * the same primitive would miss, implying that a neighboring triangle would * be hit instead. * * This relies on triangle intersection to be watertight, and the object inverse @@ -88,11 +88,11 @@ ccl_device_forceinline bool integrate_surface_holdout(KernelGlobals kg, if (((sd->flag & SD_HOLDOUT) || (sd->object_flag & SD_OBJECT_HOLDOUT_MASK)) && (path_flag & PATH_RAY_TRANSPARENT_BACKGROUND)) { - const float3 holdout_weight = shader_holdout_apply(kg, sd); - const float3 throughput = INTEGRATOR_STATE(state, path, throughput); + const Spectrum holdout_weight = shader_holdout_apply(kg, sd); + const Spectrum throughput = INTEGRATOR_STATE(state, path, throughput); const float transparent = average(holdout_weight * throughput); kernel_accum_holdout(kg, state, path_flag, transparent, render_buffer); - if (isequal(holdout_weight, one_float3())) { + if (isequal(holdout_weight, one_spectrum())) { return false; } } @@ -111,7 +111,7 @@ ccl_device_forceinline void integrate_surface_emission(KernelGlobals kg, const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag); /* Evaluate emissive closure. */ - float3 L = shader_emissive_eval(sd); + Spectrum L = shader_emissive_eval(sd); # ifdef __HAIR__ if (!(path_flag & PATH_RAY_MIS_SKIP) && (sd->flag & SD_USE_MIS) && @@ -130,7 +130,7 @@ ccl_device_forceinline void integrate_surface_emission(KernelGlobals kg, L *= mis_weight; } - const float3 throughput = INTEGRATOR_STATE(state, path, throughput); + const Spectrum throughput = INTEGRATOR_STATE(state, path, throughput); kernel_accum_emission( kg, state, throughput * L, render_buffer, object_lightgroup(kg, sd->object)); } @@ -207,7 +207,7 @@ ccl_device_forceinline void integrate_surface_direct_light(KernelGlobals kg, else # endif /* __MNEE__ */ { - const float3 light_eval = light_sample_shader_eval(kg, state, emission_sd, &ls, sd->time); + const Spectrum light_eval = light_sample_shader_eval(kg, state, emission_sd, &ls, sd->time); if (is_zero(light_eval)) { return; } @@ -261,11 +261,12 @@ ccl_device_forceinline void integrate_surface_direct_light(KernelGlobals kg, /* Copy state from main path to shadow path. */ uint32_t shadow_flag = INTEGRATOR_STATE(state, path, flag); shadow_flag |= (is_light) ? PATH_RAY_SHADOW_FOR_LIGHT : 0; - const float3 throughput = INTEGRATOR_STATE(state, path, throughput) * bsdf_eval_sum(&bsdf_eval); + const Spectrum throughput = INTEGRATOR_STATE(state, path, throughput) * + bsdf_eval_sum(&bsdf_eval); if (kernel_data.kernel_features & KERNEL_FEATURE_LIGHT_PASSES) { - packed_float3 pass_diffuse_weight; - packed_float3 pass_glossy_weight; + PackedSpectrum pass_diffuse_weight; + PackedSpectrum pass_glossy_weight; if (shadow_flag & PATH_RAY_ANY_PASS) { /* Indirect bounce, use weights from earlier surface or volume bounce. */ @@ -275,8 +276,8 @@ ccl_device_forceinline void integrate_surface_direct_light(KernelGlobals kg, else { /* Direct light, use BSDFs at this bounce. */ shadow_flag |= PATH_RAY_SURFACE_PASS; - pass_diffuse_weight = packed_float3(bsdf_eval_pass_diffuse_weight(&bsdf_eval)); - pass_glossy_weight = packed_float3(bsdf_eval_pass_glossy_weight(&bsdf_eval)); + pass_diffuse_weight = PackedSpectrum(bsdf_eval_pass_diffuse_weight(&bsdf_eval)); + pass_glossy_weight = PackedSpectrum(bsdf_eval_pass_glossy_weight(&bsdf_eval)); } INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, pass_diffuse_weight) = pass_diffuse_weight; @@ -389,7 +390,7 @@ ccl_device_forceinline int integrate_surface_bsdf_bssrdf_bounce( } /* Update throughput. */ - float3 throughput = INTEGRATOR_STATE(state, path, throughput); + Spectrum throughput = INTEGRATOR_STATE(state, path, throughput); throughput *= bsdf_eval_sum(&bsdf_eval) / bsdf_pdf; INTEGRATOR_STATE_WRITE(state, path, throughput) = throughput; @@ -461,7 +462,7 @@ ccl_device_forceinline void integrate_surface_ao(KernelGlobals kg, path_state_rng_2D(kg, rng_state, PRNG_BSDF_U, &bsdf_u, &bsdf_v); float3 ao_N; - const float3 ao_weight = shader_bsdf_ao( + const Spectrum ao_weight = shader_bsdf_ao( kg, sd, kernel_data.integrator.ao_additive_factor, &ao_N); float3 ao_D; @@ -504,7 +505,8 @@ ccl_device_forceinline void integrate_surface_ao(KernelGlobals kg, const uint16_t bounce = INTEGRATOR_STATE(state, path, bounce); const uint16_t transparent_bounce = INTEGRATOR_STATE(state, path, transparent_bounce); uint32_t shadow_flag = INTEGRATOR_STATE(state, path, flag) | PATH_RAY_SHADOW_FOR_AO; - const float3 throughput = INTEGRATOR_STATE(state, path, throughput) * shader_bsdf_alpha(kg, sd); + const Spectrum throughput = INTEGRATOR_STATE(state, path, throughput) * + shader_bsdf_alpha(kg, sd); INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, render_pixel_index) = INTEGRATOR_STATE( state, path, render_pixel_index); diff --git a/intern/cycles/kernel/integrator/shade_volume.h b/intern/cycles/kernel/integrator/shade_volume.h index 4aab097a7d8..0d35011c359 100644 --- a/intern/cycles/kernel/integrator/shade_volume.h +++ b/intern/cycles/kernel/integrator/shade_volume.h @@ -29,13 +29,13 @@ typedef enum VolumeIntegrateEvent { typedef struct VolumeIntegrateResult { /* Throughput and offset for direct light scattering. */ bool direct_scatter; - float3 direct_throughput; + Spectrum direct_throughput; float direct_t; ShaderVolumePhases direct_phases; /* Throughput and offset for indirect light scattering. */ bool indirect_scatter; - float3 indirect_throughput; + Spectrum indirect_throughput; float indirect_t; ShaderVolumePhases indirect_phases; } VolumeIntegrateResult; @@ -52,16 +52,16 @@ typedef struct VolumeIntegrateResult { * sigma_t = sigma_a + sigma_s */ typedef struct VolumeShaderCoefficients { - float3 sigma_t; - float3 sigma_s; - float3 emission; + Spectrum sigma_t; + Spectrum sigma_s; + Spectrum emission; } VolumeShaderCoefficients; /* Evaluate shader to get extinction coefficient at P. */ ccl_device_inline bool shadow_volume_shader_sample(KernelGlobals kg, IntegratorShadowState state, ccl_private ShaderData *ccl_restrict sd, - ccl_private float3 *ccl_restrict extinction) + ccl_private Spectrum *ccl_restrict extinction) { VOLUME_READ_LAMBDA(integrator_state_read_shadow_volume_stack(state, i)) shader_eval_volume<true>(kg, state, sd, PATH_RAY_SHADOW, volume_read_lambda_pass); @@ -89,9 +89,10 @@ ccl_device_inline bool volume_shader_sample(KernelGlobals kg, return false; } - coeff->sigma_s = zero_float3(); - coeff->sigma_t = (sd->flag & SD_EXTINCTION) ? sd->closure_transparent_extinction : zero_float3(); - coeff->emission = (sd->flag & SD_EMISSION) ? sd->closure_emission_background : zero_float3(); + coeff->sigma_s = zero_spectrum(); + coeff->sigma_t = (sd->flag & SD_EXTINCTION) ? sd->closure_transparent_extinction : + zero_spectrum(); + coeff->emission = (sd->flag & SD_EMISSION) ? sd->closure_emission_background : zero_spectrum(); if (sd->flag & SD_SCATTER) { for (int i = 0; i < sd->num_closure; i++) { @@ -162,9 +163,9 @@ ccl_device_forceinline void volume_step_init(KernelGlobals kg, ccl_device void volume_shadow_homogeneous(KernelGlobals kg, IntegratorState state, ccl_private Ray *ccl_restrict ray, ccl_private ShaderData *ccl_restrict sd, - ccl_global float3 *ccl_restrict throughput) + ccl_global Spectrum *ccl_restrict throughput) { - float3 sigma_t = zero_float3(); + Spectrum sigma_t = zero_spectrum(); if (shadow_volume_shader_sample(kg, state, sd, &sigma_t)) { *throughput *= volume_color_transmittance(sigma_t, ray->tmax - ray->tmin); @@ -178,14 +179,14 @@ ccl_device void volume_shadow_heterogeneous(KernelGlobals kg, IntegratorShadowState state, ccl_private Ray *ccl_restrict ray, ccl_private ShaderData *ccl_restrict sd, - ccl_private float3 *ccl_restrict throughput, + ccl_private Spectrum *ccl_restrict throughput, const float object_step_size) { /* Load random number state. */ RNGState rng_state; shadow_path_state_rng_load(state, &rng_state); - float3 tp = *throughput; + Spectrum tp = *throughput; /* Prepare for stepping. * For shadows we do not offset all segments, since the starting point is @@ -207,7 +208,7 @@ ccl_device void volume_shadow_heterogeneous(KernelGlobals kg, /* compute extinction at the start */ float t = ray->tmin; - float3 sum = zero_float3(); + Spectrum sum = zero_spectrum(); for (int i = 0; i < max_steps; i++) { /* advance to new position */ @@ -215,7 +216,7 @@ ccl_device void volume_shadow_heterogeneous(KernelGlobals kg, float dt = new_t - t; float3 new_P = ray->P + ray->D * (t + dt * step_shade_offset); - float3 sigma_t = zero_float3(); + Spectrum sigma_t = zero_spectrum(); /* compute attenuation over segment */ sd->P = new_P; @@ -228,8 +229,7 @@ ccl_device void volume_shadow_heterogeneous(KernelGlobals kg, tp = *throughput * exp(sum); /* stop if nearly all light is blocked */ - if (tp.x < VOLUME_THROUGHPUT_EPSILON && tp.y < VOLUME_THROUGHPUT_EPSILON && - tp.z < VOLUME_THROUGHPUT_EPSILON) + if (reduce_max(tp) < VOLUME_THROUGHPUT_EPSILON) break; } } @@ -334,22 +334,22 @@ ccl_device float volume_equiangular_cdf(ccl_private const Ray *ccl_restrict ray, /* Distance sampling */ ccl_device float volume_distance_sample(float max_t, - float3 sigma_t, + Spectrum sigma_t, int channel, float xi, - ccl_private float3 *transmittance, - ccl_private float3 *pdf) + ccl_private Spectrum *transmittance, + ccl_private Spectrum *pdf) { /* xi is [0, 1[ so log(0) should never happen, division by zero is * avoided because sample_sigma_t > 0 when SD_SCATTER is set */ float sample_sigma_t = volume_channel_get(sigma_t, channel); - float3 full_transmittance = volume_color_transmittance(sigma_t, max_t); + Spectrum full_transmittance = volume_color_transmittance(sigma_t, max_t); float sample_transmittance = volume_channel_get(full_transmittance, channel); float sample_t = min(max_t, -logf(1.0f - xi * (1.0f - sample_transmittance)) / sample_sigma_t); *transmittance = volume_color_transmittance(sigma_t, sample_t); - *pdf = safe_divide_color(sigma_t * *transmittance, one_float3() - full_transmittance); + *pdf = safe_divide_color(sigma_t * *transmittance, one_spectrum() - full_transmittance); /* todo: optimization: when taken together with hit/miss decision, * the full_transmittance cancels out drops out and xi does not @@ -358,33 +358,36 @@ ccl_device float volume_distance_sample(float max_t, return sample_t; } -ccl_device float3 volume_distance_pdf(float max_t, float3 sigma_t, float sample_t) +ccl_device Spectrum volume_distance_pdf(float max_t, Spectrum sigma_t, float sample_t) { - float3 full_transmittance = volume_color_transmittance(sigma_t, max_t); - float3 transmittance = volume_color_transmittance(sigma_t, sample_t); + Spectrum full_transmittance = volume_color_transmittance(sigma_t, max_t); + Spectrum transmittance = volume_color_transmittance(sigma_t, sample_t); - return safe_divide_color(sigma_t * transmittance, one_float3() - full_transmittance); + return safe_divide_color(sigma_t * transmittance, one_spectrum() - full_transmittance); } /* Emission */ -ccl_device float3 volume_emission_integrate(ccl_private VolumeShaderCoefficients *coeff, - int closure_flag, - float3 transmittance, - float t) +ccl_device Spectrum volume_emission_integrate(ccl_private VolumeShaderCoefficients *coeff, + int closure_flag, + Spectrum transmittance, + float t) { /* integral E * exp(-sigma_t * t) from 0 to t = E * (1 - exp(-sigma_t * t))/sigma_t * this goes to E * t as sigma_t goes to zero * * todo: we should use an epsilon to avoid precision issues near zero sigma_t */ - float3 emission = coeff->emission; + Spectrum emission = coeff->emission; if (closure_flag & SD_EXTINCTION) { - float3 sigma_t = coeff->sigma_t; + Spectrum sigma_t = coeff->sigma_t; - emission.x *= (sigma_t.x > 0.0f) ? (1.0f - transmittance.x) / sigma_t.x : t; - emission.y *= (sigma_t.y > 0.0f) ? (1.0f - transmittance.y) / sigma_t.y : t; - emission.z *= (sigma_t.z > 0.0f) ? (1.0f - transmittance.z) / sigma_t.z : t; + FOREACH_SPECTRUM_CHANNEL (i) { + GET_SPECTRUM_CHANNEL(emission, i) *= (GET_SPECTRUM_CHANNEL(sigma_t, i) > 0.0f) ? + (1.0f - GET_SPECTRUM_CHANNEL(transmittance, i)) / + GET_SPECTRUM_CHANNEL(sigma_t, i) : + t; + } } else emission *= t; @@ -419,14 +422,14 @@ ccl_device_forceinline void volume_integrate_step_scattering( ccl_private const Ray *ray, const float3 equiangular_light_P, ccl_private const VolumeShaderCoefficients &ccl_restrict coeff, - const float3 transmittance, + const Spectrum transmittance, ccl_private VolumeIntegrateState &ccl_restrict vstate, ccl_private VolumeIntegrateResult &ccl_restrict result) { /* Pick random color channel, we use the Veach one-sample * model with balance heuristic for the channels. */ - const float3 albedo = safe_divide_color(coeff.sigma_s, coeff.sigma_t); - float3 channel_pdf; + const Spectrum albedo = safe_divide_color(coeff.sigma_s, coeff.sigma_t); + Spectrum channel_pdf; const int channel = volume_sample_channel( albedo, result.indirect_throughput, vstate.rphase, &channel_pdf); @@ -435,7 +438,7 @@ ccl_device_forceinline void volume_integrate_step_scattering( if (result.direct_t >= vstate.tmin && result.direct_t <= vstate.tmax && vstate.equiangular_pdf > VOLUME_SAMPLE_PDF_CUTOFF) { const float new_dt = result.direct_t - vstate.tmin; - const float3 new_transmittance = volume_color_transmittance(coeff.sigma_t, new_dt); + const Spectrum new_transmittance = volume_color_transmittance(coeff.sigma_t, new_dt); result.direct_scatter = true; result.direct_throughput *= coeff.sigma_s * new_transmittance / vstate.equiangular_pdf; @@ -467,7 +470,7 @@ ccl_device_forceinline void volume_integrate_step_scattering( const float new_t = vstate.tmin + new_dt; /* transmittance and pdf */ - const float3 new_transmittance = volume_color_transmittance(coeff.sigma_t, new_dt); + const Spectrum new_transmittance = volume_color_transmittance(coeff.sigma_t, new_dt); const float distance_pdf = dot(channel_pdf, coeff.sigma_t * new_transmittance); if (vstate.distance_pdf * distance_pdf > VOLUME_SAMPLE_PDF_CUTOFF) { @@ -566,7 +569,7 @@ ccl_device_forceinline void volume_integrate_heterogeneous( vstate.distance_pdf = 1.0f; /* Initialize volume integration result. */ - const float3 throughput = INTEGRATOR_STATE(state, path, throughput); + const Spectrum throughput = INTEGRATOR_STATE(state, path, throughput); result.direct_throughput = throughput; result.indirect_throughput = throughput; @@ -579,9 +582,9 @@ ccl_device_forceinline void volume_integrate_heterogeneous( # ifdef __DENOISING_FEATURES__ const bool write_denoising_features = (INTEGRATOR_STATE(state, path, flag) & PATH_RAY_DENOISING_FEATURES); - float3 accum_albedo = zero_float3(); + Spectrum accum_albedo = zero_spectrum(); # endif - float3 accum_emission = zero_float3(); + Spectrum accum_emission = zero_spectrum(); for (int i = 0; i < max_steps; i++) { /* Advance to new position */ @@ -596,16 +599,16 @@ ccl_device_forceinline void volume_integrate_heterogeneous( /* Evaluate transmittance over segment. */ const float dt = (vstate.tmax - vstate.tmin); - const float3 transmittance = (closure_flag & SD_EXTINCTION) ? - volume_color_transmittance(coeff.sigma_t, dt) : - one_float3(); + const Spectrum transmittance = (closure_flag & SD_EXTINCTION) ? + volume_color_transmittance(coeff.sigma_t, dt) : + one_spectrum(); /* Emission. */ if (closure_flag & SD_EMISSION) { /* Only write emission before indirect light scatter position, since we terminate * stepping at that point if we have already found a direct light scatter position. */ if (!result.indirect_scatter) { - const float3 emission = volume_emission_integrate( + const Spectrum emission = volume_emission_integrate( &coeff, closure_flag, transmittance, dt); accum_emission += result.indirect_throughput * emission; } @@ -616,8 +619,8 @@ ccl_device_forceinline void volume_integrate_heterogeneous( # ifdef __DENOISING_FEATURES__ /* Accumulate albedo for denoising features. */ if (write_denoising_features && (closure_flag & SD_SCATTER)) { - const float3 albedo = safe_divide_color(coeff.sigma_s, coeff.sigma_t); - accum_albedo += result.indirect_throughput * albedo * (one_float3() - transmittance); + const Spectrum albedo = safe_divide_color(coeff.sigma_s, coeff.sigma_t); + accum_albedo += result.indirect_throughput * albedo * (one_spectrum() - transmittance); } # endif @@ -634,7 +637,7 @@ ccl_device_forceinline void volume_integrate_heterogeneous( /* Stop if nearly all light blocked. */ if (!result.indirect_scatter) { if (reduce_max(result.indirect_throughput) < VOLUME_THROUGHPUT_EPSILON) { - result.indirect_throughput = zero_float3(); + result.indirect_throughput = zero_spectrum(); break; } } @@ -715,7 +718,7 @@ ccl_device_forceinline void integrate_volume_direct_light( ccl_private const RNGState *ccl_restrict rng_state, const float3 P, ccl_private const ShaderVolumePhases *ccl_restrict phases, - ccl_private const float3 throughput, + ccl_private const Spectrum throughput, ccl_private LightSample *ccl_restrict ls) { PROFILING_INIT(kg, PROFILING_SHADE_VOLUME_DIRECT_LIGHT); @@ -753,7 +756,7 @@ ccl_device_forceinline void integrate_volume_direct_light( * non-constant light sources. */ ShaderDataTinyStorage emission_sd_storage; ccl_private ShaderData *emission_sd = AS_SHADER_DATA(&emission_sd_storage); - const float3 light_eval = light_sample_shader_eval(kg, state, emission_sd, ls, sd->time); + const Spectrum light_eval = light_sample_shader_eval(kg, state, emission_sd, ls, sd->time); if (is_zero(light_eval)) { return; } @@ -796,11 +799,11 @@ ccl_device_forceinline void integrate_volume_direct_light( const uint16_t transparent_bounce = INTEGRATOR_STATE(state, path, transparent_bounce); uint32_t shadow_flag = INTEGRATOR_STATE(state, path, flag); shadow_flag |= (is_light) ? PATH_RAY_SHADOW_FOR_LIGHT : 0; - const float3 throughput_phase = throughput * bsdf_eval_sum(&phase_eval); + const Spectrum throughput_phase = throughput * bsdf_eval_sum(&phase_eval); if (kernel_data.kernel_features & KERNEL_FEATURE_LIGHT_PASSES) { - packed_float3 pass_diffuse_weight; - packed_float3 pass_glossy_weight; + PackedSpectrum pass_diffuse_weight; + PackedSpectrum pass_glossy_weight; if (shadow_flag & PATH_RAY_ANY_PASS) { /* Indirect bounce, use weights from earlier surface or volume bounce. */ @@ -810,8 +813,8 @@ ccl_device_forceinline void integrate_volume_direct_light( else { /* Direct light, no diffuse/glossy distinction needed for volumes. */ shadow_flag |= PATH_RAY_VOLUME_PASS; - pass_diffuse_weight = packed_float3(one_float3()); - pass_glossy_weight = packed_float3(zero_float3()); + pass_diffuse_weight = one_spectrum(); + pass_glossy_weight = zero_spectrum(); } INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, pass_diffuse_weight) = pass_diffuse_weight; @@ -898,13 +901,13 @@ ccl_device_forceinline bool integrate_volume_phase_scatter( INTEGRATOR_STATE_WRITE(state, isect, object) = sd->object; /* Update throughput. */ - const float3 throughput = INTEGRATOR_STATE(state, path, throughput); - const float3 throughput_phase = throughput * bsdf_eval_sum(&phase_eval) / phase_pdf; + const Spectrum throughput = INTEGRATOR_STATE(state, path, throughput); + const Spectrum throughput_phase = throughput * bsdf_eval_sum(&phase_eval) / phase_pdf; INTEGRATOR_STATE_WRITE(state, path, throughput) = throughput_phase; if (kernel_data.kernel_features & KERNEL_FEATURE_LIGHT_PASSES) { - INTEGRATOR_STATE_WRITE(state, path, pass_diffuse_weight) = one_float3(); - INTEGRATOR_STATE_WRITE(state, path, pass_glossy_weight) = zero_float3(); + INTEGRATOR_STATE_WRITE(state, path, pass_diffuse_weight) = one_spectrum(); + INTEGRATOR_STATE_WRITE(state, path, pass_glossy_weight) = zero_spectrum(); } /* Update path state */ diff --git a/intern/cycles/kernel/integrator/shader_eval.h b/intern/cycles/kernel/integrator/shader_eval.h index ed4d973e864..d9c14b25a4b 100644 --- a/intern/cycles/kernel/integrator/shader_eval.h +++ b/intern/cycles/kernel/integrator/shader_eval.h @@ -98,7 +98,7 @@ ccl_device_inline void shader_prepare_surface_closures(KernelGlobals kg, /* Filter out closures. */ if (kernel_data.integrator.filter_closures) { if (kernel_data.integrator.filter_closures & FILTER_CLOSURE_EMISSION) { - sd->closure_emission_background = zero_float3(); + sd->closure_emission_background = zero_spectrum(); } if (kernel_data.integrator.filter_closures & FILTER_CLOSURE_DIRECT_LIGHT) { @@ -231,7 +231,7 @@ ccl_device_inline float _shader_bsdf_multi_eval(KernelGlobals kg, if (CLOSURE_IS_BSDF_OR_BSSRDF(sc->type)) { if (CLOSURE_IS_BSDF(sc->type) && !_shader_bsdf_exclude(sc->type, light_shader_flags)) { float bsdf_pdf = 0.0f; - float3 eval = bsdf_eval(kg, sd, sc, omega_in, is_transmission, &bsdf_pdf); + Spectrum eval = bsdf_eval(kg, sd, sc, omega_in, is_transmission, &bsdf_pdf); if (bsdf_pdf != 0.0f) { bsdf_eval_accum(result_eval, sc->type, eval * sc->weight); @@ -259,7 +259,7 @@ ccl_device_inline ccl_private BsdfEval *bsdf_eval, const uint light_shader_flags) { - bsdf_eval_init(bsdf_eval, CLOSURE_NONE_ID, zero_float3()); + bsdf_eval_init(bsdf_eval, CLOSURE_NONE_ID, zero_spectrum()); return _shader_bsdf_multi_eval( kg, sd, omega_in, is_transmission, NULL, bsdf_eval, 0.0f, 0.0f, light_shader_flags); @@ -309,11 +309,11 @@ ccl_device_inline ccl_private const ShaderClosure *shader_bsdf_bssrdf_pick( } /* Return weight for picked BSSRDF. */ -ccl_device_inline float3 +ccl_device_inline Spectrum shader_bssrdf_sample_weight(ccl_private const ShaderData *ccl_restrict sd, ccl_private const ShaderClosure *ccl_restrict bssrdf_sc) { - float3 weight = bssrdf_sc->weight; + Spectrum weight = bssrdf_sc->weight; if (sd->num_closure > 1) { float sum = 0.0f; @@ -346,7 +346,7 @@ ccl_device int shader_bsdf_sample_closure(KernelGlobals kg, kernel_assert(CLOSURE_IS_BSDF(sc->type)); int label; - float3 eval = zero_float3(); + Spectrum eval = zero_spectrum(); *pdf = 0.0f; label = bsdf_sample(kg, sd, sc, randu, randv, &eval, omega_in, domega_in, pdf); @@ -385,16 +385,16 @@ ccl_device float shader_bsdf_average_roughness(ccl_private const ShaderData *sd) return (sum_weight > 0.0f) ? roughness / sum_weight : 0.0f; } -ccl_device float3 shader_bsdf_transparency(KernelGlobals kg, ccl_private const ShaderData *sd) +ccl_device Spectrum shader_bsdf_transparency(KernelGlobals kg, ccl_private const ShaderData *sd) { if (sd->flag & SD_HAS_ONLY_VOLUME) { - return one_float3(); + return one_spectrum(); } else if (sd->flag & SD_TRANSPARENT) { return sd->closure_transparent_extinction; } else { - return zero_float3(); + return zero_spectrum(); } } @@ -406,7 +406,7 @@ ccl_device void shader_bsdf_disable_transparency(KernelGlobals kg, ccl_private S if (sc->type == CLOSURE_BSDF_TRANSPARENT_ID) { sc->sample_weight = 0.0f; - sc->weight = zero_float3(); + sc->weight = zero_spectrum(); } } @@ -414,19 +414,18 @@ ccl_device void shader_bsdf_disable_transparency(KernelGlobals kg, ccl_private S } } -ccl_device float3 shader_bsdf_alpha(KernelGlobals kg, ccl_private const ShaderData *sd) +ccl_device Spectrum shader_bsdf_alpha(KernelGlobals kg, ccl_private const ShaderData *sd) { - float3 alpha = one_float3() - shader_bsdf_transparency(kg, sd); + Spectrum alpha = one_spectrum() - shader_bsdf_transparency(kg, sd); - alpha = max(alpha, zero_float3()); - alpha = min(alpha, one_float3()); + alpha = saturate(alpha); return alpha; } -ccl_device float3 shader_bsdf_diffuse(KernelGlobals kg, ccl_private const ShaderData *sd) +ccl_device Spectrum shader_bsdf_diffuse(KernelGlobals kg, ccl_private const ShaderData *sd) { - float3 eval = zero_float3(); + Spectrum eval = zero_spectrum(); for (int i = 0; i < sd->num_closure; i++) { ccl_private const ShaderClosure *sc = &sd->closure[i]; @@ -438,9 +437,9 @@ ccl_device float3 shader_bsdf_diffuse(KernelGlobals kg, ccl_private const Shader return eval; } -ccl_device float3 shader_bsdf_glossy(KernelGlobals kg, ccl_private const ShaderData *sd) +ccl_device Spectrum shader_bsdf_glossy(KernelGlobals kg, ccl_private const ShaderData *sd) { - float3 eval = zero_float3(); + Spectrum eval = zero_spectrum(); for (int i = 0; i < sd->num_closure; i++) { ccl_private const ShaderClosure *sc = &sd->closure[i]; @@ -452,9 +451,9 @@ ccl_device float3 shader_bsdf_glossy(KernelGlobals kg, ccl_private const ShaderD return eval; } -ccl_device float3 shader_bsdf_transmission(KernelGlobals kg, ccl_private const ShaderData *sd) +ccl_device Spectrum shader_bsdf_transmission(KernelGlobals kg, ccl_private const ShaderData *sd) { - float3 eval = zero_float3(); + Spectrum eval = zero_spectrum(); for (int i = 0; i < sd->num_closure; i++) { ccl_private const ShaderClosure *sc = &sd->closure[i]; @@ -479,12 +478,12 @@ ccl_device float3 shader_bsdf_average_normal(KernelGlobals kg, ccl_private const return (is_zero(N)) ? sd->N : normalize(N); } -ccl_device float3 shader_bsdf_ao(KernelGlobals kg, - ccl_private const ShaderData *sd, - const float ao_factor, - ccl_private float3 *N_) +ccl_device Spectrum shader_bsdf_ao(KernelGlobals kg, + ccl_private const ShaderData *sd, + const float ao_factor, + ccl_private float3 *N_) { - float3 eval = zero_float3(); + Spectrum eval = zero_spectrum(); float3 N = zero_float3(); for (int i = 0; i < sd->num_closure; i++) { @@ -525,15 +524,17 @@ ccl_device float3 shader_bssrdf_normal(ccl_private const ShaderData *sd) ccl_device bool shader_constant_emission_eval(KernelGlobals kg, int shader, - ccl_private float3 *eval) + ccl_private Spectrum *eval) { int shader_index = shader & SHADER_MASK; int shader_flag = kernel_data_fetch(shaders, shader_index).flags; if (shader_flag & SD_HAS_CONSTANT_EMISSION) { - *eval = make_float3(kernel_data_fetch(shaders, shader_index).constant_emission[0], - kernel_data_fetch(shaders, shader_index).constant_emission[1], - kernel_data_fetch(shaders, shader_index).constant_emission[2]); + const float3 emission_rgb = make_float3( + kernel_data_fetch(shaders, shader_index).constant_emission[0], + kernel_data_fetch(shaders, shader_index).constant_emission[1], + kernel_data_fetch(shaders, shader_index).constant_emission[2]); + *eval = rgb_to_spectrum(emission_rgb); return true; } @@ -543,39 +544,39 @@ ccl_device bool shader_constant_emission_eval(KernelGlobals kg, /* Background */ -ccl_device float3 shader_background_eval(ccl_private const ShaderData *sd) +ccl_device Spectrum shader_background_eval(ccl_private const ShaderData *sd) { if (sd->flag & SD_EMISSION) { return sd->closure_emission_background; } else { - return zero_float3(); + return zero_spectrum(); } } /* Emission */ -ccl_device float3 shader_emissive_eval(ccl_private const ShaderData *sd) +ccl_device Spectrum shader_emissive_eval(ccl_private const ShaderData *sd) { if (sd->flag & SD_EMISSION) { return emissive_simple_eval(sd->Ng, sd->I) * sd->closure_emission_background; } else { - return zero_float3(); + return zero_spectrum(); } } /* Holdout */ -ccl_device float3 shader_holdout_apply(KernelGlobals kg, ccl_private ShaderData *sd) +ccl_device Spectrum shader_holdout_apply(KernelGlobals kg, ccl_private ShaderData *sd) { - float3 weight = zero_float3(); + Spectrum weight = zero_spectrum(); /* For objects marked as holdout, preserve transparency and remove all other * closures, replacing them with a holdout weight. */ if (sd->object_flag & SD_OBJECT_HOLDOUT_MASK) { if ((sd->flag & SD_TRANSPARENT) && !(sd->flag & SD_HAS_ONLY_VOLUME)) { - weight = one_float3() - sd->closure_transparent_extinction; + weight = one_spectrum() - sd->closure_transparent_extinction; for (int i = 0; i < sd->num_closure; i++) { ccl_private ShaderClosure *sc = &sd->closure[i]; @@ -587,7 +588,7 @@ ccl_device float3 shader_holdout_apply(KernelGlobals kg, ccl_private ShaderData sd->flag &= ~(SD_CLOSURE_FLAGS - (SD_TRANSPARENT | SD_BSDF)); } else { - weight = one_float3(); + weight = one_spectrum(); } } else { @@ -642,12 +643,12 @@ ccl_device void shader_eval_surface(KernelGlobals kg, svm_eval_nodes<node_feature_mask, SHADER_TYPE_SURFACE>(kg, state, sd, buffer, path_flag); #else if (sd->object == OBJECT_NONE) { - sd->closure_emission_background = make_float3(0.8f, 0.8f, 0.8f); + sd->closure_emission_background = make_spectrum(0.8f); sd->flag |= SD_EMISSION; } else { ccl_private DiffuseBsdf *bsdf = (ccl_private DiffuseBsdf *)bsdf_alloc( - sd, sizeof(DiffuseBsdf), make_float3(0.8f, 0.8f, 0.8f)); + sd, sizeof(DiffuseBsdf), make_spectrum(0.8f)); if (bsdf != NULL) { bsdf->N = sd->N; sd->flag |= bsdf_diffuse_setup(bsdf); @@ -676,7 +677,7 @@ ccl_device_inline float _shader_volume_phase_multi_eval( ccl_private const ShaderVolumeClosure *svc = &phases->closure[i]; float phase_pdf = 0.0f; - float3 eval = volume_phase_eval(sd, svc, omega_in, &phase_pdf); + Spectrum eval = volume_phase_eval(sd, svc, omega_in, &phase_pdf); if (phase_pdf != 0.0f) { bsdf_eval_accum(result_eval, CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID, eval); @@ -695,7 +696,7 @@ ccl_device float shader_volume_phase_eval(KernelGlobals kg, const float3 omega_in, ccl_private BsdfEval *phase_eval) { - bsdf_eval_init(phase_eval, CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID, zero_float3()); + bsdf_eval_init(phase_eval, CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID, zero_spectrum()); return _shader_volume_phase_multi_eval(sd, phases, omega_in, -1, phase_eval, 0.0f, 0.0f); } @@ -747,7 +748,7 @@ ccl_device int shader_volume_phase_sample(KernelGlobals kg, * depending on color channels, even if this is perhaps not a common case */ ccl_private const ShaderVolumeClosure *svc = &phases->closure[sampled]; int label; - float3 eval = zero_float3(); + Spectrum eval = zero_spectrum(); *pdf = 0.0f; label = volume_phase_sample(sd, svc, randu, randv, &eval, omega_in, domega_in, pdf); @@ -770,7 +771,7 @@ ccl_device int shader_phase_sample_closure(KernelGlobals kg, ccl_private float *pdf) { int label; - float3 eval = zero_float3(); + Spectrum eval = zero_spectrum(); *pdf = 0.0f; label = volume_phase_sample(sd, sc, randu, randv, &eval, omega_in, domega_in, pdf); diff --git a/intern/cycles/kernel/integrator/shadow_catcher.h b/intern/cycles/kernel/integrator/shadow_catcher.h index ff63625aceb..7103b6032ac 100644 --- a/intern/cycles/kernel/integrator/shadow_catcher.h +++ b/intern/cycles/kernel/integrator/shadow_catcher.h @@ -93,7 +93,7 @@ ccl_device_forceinline void kernel_write_shadow_catcher_bounce_data( /* Since the split is done, the sample does not contribute to the matte, so accumulate it as * transparency to the matte. */ - const float3 throughput = INTEGRATOR_STATE(state, path, throughput); + const Spectrum throughput = INTEGRATOR_STATE(state, path, throughput); kernel_write_pass_float(buffer + kernel_data.film.pass_shadow_catcher_matte + 3, average(throughput)); } diff --git a/intern/cycles/kernel/integrator/shadow_state_template.h b/intern/cycles/kernel/integrator/shadow_state_template.h index c340467606d..3b490ecffdd 100644 --- a/intern/cycles/kernel/integrator/shadow_state_template.h +++ b/intern/cycles/kernel/integrator/shadow_state_template.h @@ -27,15 +27,15 @@ KERNEL_STRUCT_MEMBER(shadow_path, uint16_t, queued_kernel, KERNEL_FEATURE_PATH_T /* enum PathRayFlag */ KERNEL_STRUCT_MEMBER(shadow_path, uint32_t, flag, KERNEL_FEATURE_PATH_TRACING) /* Throughput. */ -KERNEL_STRUCT_MEMBER(shadow_path, packed_float3, throughput, KERNEL_FEATURE_PATH_TRACING) +KERNEL_STRUCT_MEMBER(shadow_path, PackedSpectrum, throughput, KERNEL_FEATURE_PATH_TRACING) /* Throughput for shadow pass. */ KERNEL_STRUCT_MEMBER(shadow_path, - packed_float3, + PackedSpectrum, unshadowed_throughput, KERNEL_FEATURE_SHADOW_PASS | KERNEL_FEATURE_AO_ADDITIVE) /* Ratio of throughput to distinguish diffuse / glossy / transmission render passes. */ -KERNEL_STRUCT_MEMBER(shadow_path, packed_float3, pass_diffuse_weight, KERNEL_FEATURE_LIGHT_PASSES) -KERNEL_STRUCT_MEMBER(shadow_path, packed_float3, pass_glossy_weight, KERNEL_FEATURE_LIGHT_PASSES) +KERNEL_STRUCT_MEMBER(shadow_path, PackedSpectrum, pass_diffuse_weight, KERNEL_FEATURE_LIGHT_PASSES) +KERNEL_STRUCT_MEMBER(shadow_path, PackedSpectrum, pass_glossy_weight, KERNEL_FEATURE_LIGHT_PASSES) /* Number of intersections found by ray-tracing. */ KERNEL_STRUCT_MEMBER(shadow_path, uint16_t, num_hits, KERNEL_FEATURE_PATH_TRACING) /* Light group. */ diff --git a/intern/cycles/kernel/integrator/state_template.h b/intern/cycles/kernel/integrator/state_template.h index 5c2af131945..f4e280e4cb2 100644 --- a/intern/cycles/kernel/integrator/state_template.h +++ b/intern/cycles/kernel/integrator/state_template.h @@ -46,12 +46,12 @@ KERNEL_STRUCT_MEMBER(path, float, min_ray_pdf, KERNEL_FEATURE_PATH_TRACING) /* Continuation probability for path termination. */ KERNEL_STRUCT_MEMBER(path, float, continuation_probability, KERNEL_FEATURE_PATH_TRACING) /* Throughput. */ -KERNEL_STRUCT_MEMBER(path, packed_float3, throughput, KERNEL_FEATURE_PATH_TRACING) +KERNEL_STRUCT_MEMBER(path, PackedSpectrum, throughput, KERNEL_FEATURE_PATH_TRACING) /* Ratio of throughput to distinguish diffuse / glossy / transmission render passes. */ -KERNEL_STRUCT_MEMBER(path, packed_float3, pass_diffuse_weight, KERNEL_FEATURE_LIGHT_PASSES) -KERNEL_STRUCT_MEMBER(path, packed_float3, pass_glossy_weight, KERNEL_FEATURE_LIGHT_PASSES) +KERNEL_STRUCT_MEMBER(path, PackedSpectrum, pass_diffuse_weight, KERNEL_FEATURE_LIGHT_PASSES) +KERNEL_STRUCT_MEMBER(path, PackedSpectrum, pass_glossy_weight, KERNEL_FEATURE_LIGHT_PASSES) /* Denoising. */ -KERNEL_STRUCT_MEMBER(path, packed_float3, denoising_feature_throughput, KERNEL_FEATURE_DENOISING) +KERNEL_STRUCT_MEMBER(path, PackedSpectrum, denoising_feature_throughput, KERNEL_FEATURE_DENOISING) /* Shader sorting. */ /* TODO: compress as uint16? or leave out entirely and recompute key in sorting code? */ KERNEL_STRUCT_MEMBER(path, uint32_t, shader_sort_key, KERNEL_FEATURE_PATH_TRACING) @@ -84,8 +84,8 @@ KERNEL_STRUCT_END(isect) /*************** Subsurface closure state for subsurface kernel ***************/ KERNEL_STRUCT_BEGIN(subsurface) -KERNEL_STRUCT_MEMBER(subsurface, packed_float3, albedo, KERNEL_FEATURE_SUBSURFACE) -KERNEL_STRUCT_MEMBER(subsurface, packed_float3, radius, KERNEL_FEATURE_SUBSURFACE) +KERNEL_STRUCT_MEMBER(subsurface, PackedSpectrum, albedo, KERNEL_FEATURE_SUBSURFACE) +KERNEL_STRUCT_MEMBER(subsurface, PackedSpectrum, radius, KERNEL_FEATURE_SUBSURFACE) KERNEL_STRUCT_MEMBER(subsurface, float, anisotropy, KERNEL_FEATURE_SUBSURFACE) KERNEL_STRUCT_MEMBER(subsurface, packed_float3, Ng, KERNEL_FEATURE_SUBSURFACE) KERNEL_STRUCT_END(subsurface) diff --git a/intern/cycles/kernel/integrator/subsurface.h b/intern/cycles/kernel/integrator/subsurface.h index 2f96f215d8a..ee3a619f968 100644 --- a/intern/cycles/kernel/integrator/subsurface.h +++ b/intern/cycles/kernel/integrator/subsurface.h @@ -51,7 +51,7 @@ ccl_device int subsurface_bounce(KernelGlobals kg, PATH_RAY_SUBSURFACE_RANDOM_WALK); /* Compute weight, optionally including Fresnel from entry point. */ - float3 weight = shader_bssrdf_sample_weight(sd, sc); + Spectrum weight = shader_bssrdf_sample_weight(sd, sc); # ifdef __PRINCIPLED__ if (bssrdf->roughness != FLT_MAX) { path_flag |= PATH_RAY_SUBSURFACE_USE_FRESNEL; @@ -70,8 +70,8 @@ ccl_device int subsurface_bounce(KernelGlobals kg, if (kernel_data.kernel_features & KERNEL_FEATURE_LIGHT_PASSES) { if (INTEGRATOR_STATE(state, path, bounce) == 0) { - INTEGRATOR_STATE_WRITE(state, path, pass_diffuse_weight) = one_float3(); - INTEGRATOR_STATE_WRITE(state, path, pass_glossy_weight) = zero_float3(); + INTEGRATOR_STATE_WRITE(state, path, pass_diffuse_weight) = one_spectrum(); + INTEGRATOR_STATE_WRITE(state, path, pass_glossy_weight) = zero_spectrum(); } } @@ -99,7 +99,7 @@ ccl_device void subsurface_shader_data_setup(KernelGlobals kg, sd->num_closure = 0; sd->num_closure_left = kernel_data.max_closures; - const float3 weight = one_float3(); + const Spectrum weight = one_spectrum(); # ifdef __PRINCIPLED__ if (path_flag & PATH_RAY_SUBSURFACE_USE_FRESNEL) { diff --git a/intern/cycles/kernel/integrator/subsurface_disk.h b/intern/cycles/kernel/integrator/subsurface_disk.h index 60b63c075a0..77763f702d8 100644 --- a/intern/cycles/kernel/integrator/subsurface_disk.h +++ b/intern/cycles/kernel/integrator/subsurface_disk.h @@ -9,11 +9,11 @@ CCL_NAMESPACE_BEGIN * http://library.imageworks.com/pdfs/imageworks-library-BSSRDF-sampling.pdf */ -ccl_device_inline float3 subsurface_disk_eval(const float3 radius, float disk_r, float r) +ccl_device_inline Spectrum subsurface_disk_eval(const Spectrum radius, float disk_r, float r) { - const float3 eval = bssrdf_eval(radius, r); + const Spectrum eval = bssrdf_eval(radius, r); const float pdf = bssrdf_pdf(radius, disk_r); - return (pdf > 0.0f) ? eval / pdf : zero_float3(); + return (pdf > 0.0f) ? eval / pdf : zero_spectrum(); } /* Subsurface scattering step, from a point on the surface to other @@ -37,7 +37,7 @@ ccl_device_inline bool subsurface_disk(KernelGlobals kg, const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag); /* Read subsurface scattering parameters. */ - const float3 radius = INTEGRATOR_STATE(state, subsurface, radius); + const Spectrum radius = INTEGRATOR_STATE(state, subsurface, radius); /* Pick random axis in local frame and point on disk. */ float3 disk_N, disk_T, disk_B; @@ -108,7 +108,7 @@ ccl_device_inline bool subsurface_disk(KernelGlobals kg, * traversal algorithm. */ sort_intersections_and_normals(ss_isect.hits, ss_isect.Ng, num_eval_hits); - float3 weights[BSSRDF_MAX_HITS]; /* TODO: zero? */ + Spectrum weights[BSSRDF_MAX_HITS]; /* TODO: zero? */ float sum_weights = 0.0f; for (int hit = 0; hit < num_eval_hits; hit++) { @@ -150,7 +150,7 @@ ccl_device_inline bool subsurface_disk(KernelGlobals kg, const float r = len(hit_P - P); /* Evaluate profiles. */ - const float3 weight = subsurface_disk_eval(radius, disk_r, r) * w; + const Spectrum weight = subsurface_disk_eval(radius, disk_r, r) * w; /* Store result. */ ss_isect.Ng[hit] = hit_Ng; @@ -167,7 +167,7 @@ ccl_device_inline bool subsurface_disk(KernelGlobals kg, float partial_sum = 0.0f; for (int hit = 0; hit < num_eval_hits; hit++) { - const float3 weight = weights[hit]; + const Spectrum weight = weights[hit]; const float sample_weight = average(fabs(weight)); float next_sum = partial_sum + sample_weight; diff --git a/intern/cycles/kernel/integrator/subsurface_random_walk.h b/intern/cycles/kernel/integrator/subsurface_random_walk.h index e43bbb3c50a..9c67d909bd4 100644 --- a/intern/cycles/kernel/integrator/subsurface_random_walk.h +++ b/intern/cycles/kernel/integrator/subsurface_random_walk.h @@ -65,19 +65,20 @@ ccl_device void subsurface_random_walk_remap(const float albedo, *sigma_t = sigma_t_prime / (1.0f - g); } -ccl_device void subsurface_random_walk_coefficients(const float3 albedo, - const float3 radius, +ccl_device void subsurface_random_walk_coefficients(const Spectrum albedo, + const Spectrum radius, const float anisotropy, - ccl_private float3 *sigma_t, - ccl_private float3 *alpha, - ccl_private float3 *throughput) + ccl_private Spectrum *sigma_t, + ccl_private Spectrum *alpha, + ccl_private Spectrum *throughput) { - float sigma_t_x, sigma_t_y, sigma_t_z; - float alpha_x, alpha_y, alpha_z; - - subsurface_random_walk_remap(albedo.x, radius.x, anisotropy, &sigma_t_x, &alpha_x); - subsurface_random_walk_remap(albedo.y, radius.y, anisotropy, &sigma_t_y, &alpha_y); - subsurface_random_walk_remap(albedo.z, radius.z, anisotropy, &sigma_t_z, &alpha_z); + FOREACH_SPECTRUM_CHANNEL (i) { + subsurface_random_walk_remap(GET_SPECTRUM_CHANNEL(albedo, i), + GET_SPECTRUM_CHANNEL(radius, i), + anisotropy, + &GET_SPECTRUM_CHANNEL(*sigma_t, i), + &GET_SPECTRUM_CHANNEL(*alpha, i)); + } /* Throughput already contains closure weight at this point, which includes the * albedo, as well as closure mixing and Fresnel weights. Divide out the albedo @@ -88,21 +89,12 @@ ccl_device void subsurface_random_walk_coefficients(const float3 albedo, * infinite phase functions. To avoid a sharp discontinuity as we go from * such values to 0.0, increase alpha and reduce the throughput to compensate. */ const float min_alpha = 0.2f; - if (alpha_x < min_alpha) { - (*throughput).x *= alpha_x / min_alpha; - alpha_x = min_alpha; - } - if (alpha_y < min_alpha) { - (*throughput).y *= alpha_y / min_alpha; - alpha_y = min_alpha; - } - if (alpha_z < min_alpha) { - (*throughput).z *= alpha_z / min_alpha; - alpha_z = min_alpha; + FOREACH_SPECTRUM_CHANNEL (i) { + if (GET_SPECTRUM_CHANNEL(*alpha, i) < min_alpha) { + GET_SPECTRUM_CHANNEL(*throughput, i) *= GET_SPECTRUM_CHANNEL(*alpha, i) / min_alpha; + GET_SPECTRUM_CHANNEL(*alpha, i) = min_alpha; + } } - - *sigma_t = make_float3(sigma_t_x, sigma_t_y, sigma_t_z); - *alpha = make_float3(alpha_x, alpha_y, alpha_z); } /* References for Dwivedi sampling: @@ -151,12 +143,12 @@ ccl_device_forceinline float3 direction_from_cosine(float3 D, float cos_theta, f return dir.x * T + dir.y * B + dir.z * D; } -ccl_device_forceinline float3 subsurface_random_walk_pdf(float3 sigma_t, - float t, - bool hit, - ccl_private float3 *transmittance) +ccl_device_forceinline Spectrum subsurface_random_walk_pdf(Spectrum sigma_t, + float t, + bool hit, + ccl_private Spectrum *transmittance) { - float3 T = volume_color_transmittance(sigma_t, t); + Spectrum T = volume_color_transmittance(sigma_t, t); if (transmittance) { *transmittance = T; } @@ -207,14 +199,14 @@ ccl_device_inline bool subsurface_random_walk(KernelGlobals kg, /* Convert subsurface to volume coefficients. * The single-scattering albedo is named alpha to avoid confusion with the surface albedo. */ - const float3 albedo = INTEGRATOR_STATE(state, subsurface, albedo); - const float3 radius = INTEGRATOR_STATE(state, subsurface, radius); + const Spectrum albedo = INTEGRATOR_STATE(state, subsurface, albedo); + const Spectrum radius = INTEGRATOR_STATE(state, subsurface, radius); const float anisotropy = INTEGRATOR_STATE(state, subsurface, anisotropy); - float3 sigma_t, alpha; - float3 throughput = INTEGRATOR_STATE_WRITE(state, path, throughput); + Spectrum sigma_t, alpha; + Spectrum throughput = INTEGRATOR_STATE_WRITE(state, path, throughput); subsurface_random_walk_coefficients(albedo, radius, anisotropy, &sigma_t, &alpha, &throughput); - float3 sigma_s = sigma_t * alpha; + Spectrum sigma_s = sigma_t * alpha; /* Theoretically it should be better to use the exact alpha for the channel we're sampling at * each bounce, but in practice there doesn't seem to be a noticeable difference in exchange @@ -249,10 +241,10 @@ ccl_device_inline bool subsurface_random_walk(KernelGlobals kg, const float guided_fraction = 1.0f - fmaxf(0.5f, powf(fabsf(anisotropy), 0.125f)); #ifdef SUBSURFACE_RANDOM_WALK_SIMILARITY_LEVEL - float3 sigma_s_star = sigma_s * (1.0f - anisotropy); - float3 sigma_t_star = sigma_t - sigma_s + sigma_s_star; - float3 sigma_t_org = sigma_t; - float3 sigma_s_org = sigma_s; + Spectrum sigma_s_star = sigma_s * (1.0f - anisotropy); + Spectrum sigma_t_star = sigma_t - sigma_s + sigma_s_star; + Spectrum sigma_t_org = sigma_t; + Spectrum sigma_s_org = sigma_s; const float anisotropy_org = anisotropy; const float guided_fraction_org = guided_fraction; #endif @@ -264,7 +256,7 @@ ccl_device_inline bool subsurface_random_walk(KernelGlobals kg, #ifdef SUBSURFACE_RANDOM_WALK_SIMILARITY_LEVEL // shadow with local variables according to depth float anisotropy, guided_fraction; - float3 sigma_s, sigma_t; + Spectrum sigma_s, sigma_t; if (bounce <= SUBSURFACE_RANDOM_WALK_SIMILARITY_LEVEL) { anisotropy = anisotropy_org; guided_fraction = guided_fraction_org; @@ -281,7 +273,7 @@ ccl_device_inline bool subsurface_random_walk(KernelGlobals kg, /* Sample color channel, use MIS with balance heuristic. */ float rphase = path_state_rng_1D(kg, &rng_state, PRNG_PHASE_CHANNEL); - float3 channel_pdf; + Spectrum channel_pdf; int channel = volume_sample_channel(alpha, throughput, rphase, &channel_pdf); float sample_sigma_t = volume_channel_get(sigma_t, channel); float randt = path_state_rng_1D(kg, &rng_state, PRNG_SCATTER_DISTANCE); @@ -399,16 +391,17 @@ ccl_device_inline bool subsurface_random_walk(KernelGlobals kg, /* Advance to new scatter location. */ ray.P += t * ray.D; - float3 transmittance; - float3 pdf = subsurface_random_walk_pdf(sigma_t, t, hit, &transmittance); + Spectrum transmittance; + Spectrum pdf = subsurface_random_walk_pdf(sigma_t, t, hit, &transmittance); if (bounce > 0) { /* Compute PDF just like we do for classic sampling, but with the stretched sigma_t. */ - float3 guided_pdf = subsurface_random_walk_pdf(forward_stretching * sigma_t, t, hit, NULL); + Spectrum guided_pdf = subsurface_random_walk_pdf(forward_stretching * sigma_t, t, hit, NULL); if (have_opposite_interface) { /* First step of MIS: Depending on geometry we might have two methods for guided * sampling, so perform MIS between them. */ - float3 back_pdf = subsurface_random_walk_pdf(backward_stretching * sigma_t, t, hit, NULL); + Spectrum back_pdf = subsurface_random_walk_pdf( + backward_stretching * sigma_t, t, hit, NULL); guided_pdf = mix( guided_pdf * forward_pdf_factor, back_pdf * backward_pdf_factor, backward_fraction); } @@ -430,9 +423,7 @@ ccl_device_inline bool subsurface_random_walk(KernelGlobals kg, /* If we hit the surface, we are done. */ break; } - else if (throughput.x < VOLUME_THROUGHPUT_EPSILON && - throughput.y < VOLUME_THROUGHPUT_EPSILON && - throughput.z < VOLUME_THROUGHPUT_EPSILON) { + else if (reduce_max(throughput) < VOLUME_THROUGHPUT_EPSILON) { /* Avoid unnecessary work and precision issue when throughput gets really small. */ break; } diff --git a/intern/cycles/kernel/light/sample.h b/intern/cycles/kernel/light/sample.h index 2e309cee43f..4195675dd13 100644 --- a/intern/cycles/kernel/light/sample.h +++ b/intern/cycles/kernel/light/sample.h @@ -14,7 +14,7 @@ CCL_NAMESPACE_BEGIN /* Evaluate shader on light. */ -ccl_device_noinline_cpu float3 +ccl_device_noinline_cpu Spectrum light_sample_shader_eval(KernelGlobals kg, IntegratorState state, ccl_private ShaderData *ccl_restrict emission_sd, @@ -22,7 +22,7 @@ light_sample_shader_eval(KernelGlobals kg, float time) { /* setup shading at emitter */ - float3 eval = zero_float3(); + Spectrum eval = zero_spectrum(); if (shader_constant_emission_eval(kg, ls->shader, &eval)) { if ((ls->prim != PRIM_NONE) && dot(ls->Ng, ls->D) > 0.0f) { @@ -82,7 +82,8 @@ light_sample_shader_eval(KernelGlobals kg, if (ls->lamp != LAMP_NONE) { ccl_global const KernelLight *klight = &kernel_data_fetch(lights, ls->lamp); - eval *= make_float3(klight->strength[0], klight->strength[1], klight->strength[2]); + eval *= rgb_to_spectrum( + make_float3(klight->strength[0], klight->strength[1], klight->strength[2])); } return eval; diff --git a/intern/cycles/kernel/osl/background.cpp b/intern/cycles/kernel/osl/background.cpp index 865ff4ddc6d..4b5a2686117 100644 --- a/intern/cycles/kernel/osl/background.cpp +++ b/intern/cycles/kernel/osl/background.cpp @@ -14,8 +14,12 @@ // clang-format off #include "kernel/device/cpu/compat.h" +#include "kernel/device/cpu/globals.h" + #include "kernel/closure/alloc.h" #include "kernel/closure/emissive.h" + +#include "kernel/util/color.h" // clang-format on CCL_NAMESPACE_BEGIN @@ -32,7 +36,7 @@ class GenericBackgroundClosure : public CClosurePrimitive { public: void setup(ShaderData *sd, uint32_t /* path_flag */, float3 weight) { - background_setup(sd, weight); + background_setup(sd, rgb_to_spectrum(weight)); } }; @@ -47,7 +51,7 @@ class HoldoutClosure : CClosurePrimitive { public: void setup(ShaderData *sd, uint32_t /* path_flag */, float3 weight) { - closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_HOLDOUT_ID, weight); + closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_HOLDOUT_ID, rgb_to_spectrum(weight)); sd->flag |= SD_HOLDOUT; } }; diff --git a/intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp b/intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp index 39fcee1ac0d..667207ec6bf 100644 --- a/intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp +++ b/intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp @@ -14,10 +14,15 @@ #include "kernel/osl/closures.h" // clang-format off +#include "kernel/device/cpu/compat.h" +#include "kernel/device/cpu/globals.h" + #include "kernel/types.h" #include "kernel/closure/alloc.h" #include "kernel/closure/bsdf_diffuse_ramp.h" #include "kernel/closure/bsdf_util.h" + +#include "kernel/util/color.h" // clang-format on CCL_NAMESPACE_BEGIN @@ -34,7 +39,7 @@ class DiffuseRampClosure : public CBSDFClosure { params.N = ensure_valid_reflection(sd->Ng, sd->I, params.N); DiffuseRampBsdf *bsdf = (DiffuseRampBsdf *)bsdf_alloc_osl( - sd, sizeof(DiffuseRampBsdf), weight, ¶ms); + sd, sizeof(DiffuseRampBsdf), rgb_to_spectrum(weight), ¶ms); if (bsdf) { bsdf->colors = (float3 *)closure_alloc_extra(sd, sizeof(float3) * 8); diff --git a/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp b/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp index 972ed7e4a6d..6f54a96e542 100644 --- a/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp +++ b/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp @@ -14,10 +14,15 @@ #include "kernel/osl/closures.h" // clang-format off +#include "kernel/device/cpu/compat.h" +#include "kernel/device/cpu/globals.h" + #include "kernel/types.h" #include "kernel/closure/alloc.h" #include "kernel/closure/bsdf_phong_ramp.h" #include "kernel/closure/bsdf_util.h" + +#include "kernel/util/color.h" // clang-format on CCL_NAMESPACE_BEGIN @@ -34,7 +39,7 @@ class PhongRampClosure : public CBSDFClosure { params.N = ensure_valid_reflection(sd->Ng, sd->I, params.N); PhongRampBsdf *bsdf = (PhongRampBsdf *)bsdf_alloc_osl( - sd, sizeof(PhongRampBsdf), weight, ¶ms); + sd, sizeof(PhongRampBsdf), rgb_to_spectrum(weight), ¶ms); if (bsdf) { bsdf->colors = (float3 *)closure_alloc_extra(sd, sizeof(float3) * 8); diff --git a/intern/cycles/kernel/osl/bssrdf.cpp b/intern/cycles/kernel/osl/bssrdf.cpp index 4b282fddad3..3054946ba5a 100644 --- a/intern/cycles/kernel/osl/bssrdf.cpp +++ b/intern/cycles/kernel/osl/bssrdf.cpp @@ -12,6 +12,9 @@ #include "kernel/osl/closures.h" // clang-format off +#include "kernel/device/cpu/compat.h" +#include "kernel/device/cpu/globals.h" + #include "kernel/types.h" #include "kernel/closure/alloc.h" @@ -19,6 +22,8 @@ #include "kernel/closure/bsdf_diffuse.h" #include "kernel/closure/bsdf_principled_diffuse.h" #include "kernel/closure/bssrdf.h" + +#include "kernel/util/color.h" // clang-format on CCL_NAMESPACE_BEGIN @@ -59,14 +64,14 @@ class CBSSRDFClosure : public CClosurePrimitive { void alloc(ShaderData *sd, uint32_t path_flag, float3 weight, ClosureType type) { - Bssrdf *bssrdf = bssrdf_alloc(sd, weight); + Bssrdf *bssrdf = bssrdf_alloc(sd, rgb_to_spectrum(weight)); if (bssrdf) { /* disable in case of diffuse ancestor, can't see it well then and * adds considerably noise due to probabilities of continuing path * getting lower and lower */ if (path_flag & PATH_RAY_DIFFUSE_ANCESTOR) { - params.radius = make_float3(0.0f, 0.0f, 0.0f); + params.radius = zero_spectrum(); } /* create one closure per color channel */ diff --git a/intern/cycles/kernel/osl/closures.cpp b/intern/cycles/kernel/osl/closures.cpp index 7c6b48154e4..8766fb73dbb 100644 --- a/intern/cycles/kernel/osl/closures.cpp +++ b/intern/cycles/kernel/osl/closures.cpp @@ -38,6 +38,8 @@ #include "kernel/closure/bsdf_principled_diffuse.h" #include "kernel/closure/bsdf_principled_sheen.h" #include "kernel/closure/volume.h" + +#include "kernel/util/color.h" // clang-format on CCL_NAMESPACE_BEGIN @@ -183,7 +185,7 @@ class PrincipledSheenClosure : public CBSDFClosure { params.N = ensure_valid_reflection(sd->Ng, sd->I, params.N); PrincipledSheenBsdf *bsdf = (PrincipledSheenBsdf *)bsdf_alloc_osl( - sd, sizeof(PrincipledSheenBsdf), weight, ¶ms); + sd, sizeof(PrincipledSheenBsdf), rgb_to_spectrum(weight), ¶ms); sd->flag |= (bsdf) ? bsdf_principled_sheen_setup(sd, bsdf) : 0; } } @@ -207,7 +209,7 @@ class PrincipledHairClosure : public CBSDFClosure { PrincipledHairBSDF *alloc(ShaderData *sd, uint32_t path_flag, float3 weight) { PrincipledHairBSDF *bsdf = (PrincipledHairBSDF *)bsdf_alloc_osl( - sd, sizeof(PrincipledHairBSDF), weight, ¶ms); + sd, sizeof(PrincipledHairBSDF), rgb_to_spectrum(weight), ¶ms); if (!bsdf) { return NULL; } @@ -263,7 +265,7 @@ class PrincipledClearcoatClosure : public CBSDFClosure { MicrofacetBsdf *alloc(ShaderData *sd, uint32_t path_flag, float3 weight) { MicrofacetBsdf *bsdf = (MicrofacetBsdf *)bsdf_alloc_osl( - sd, sizeof(MicrofacetBsdf), weight, ¶ms); + sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight), ¶ms); if (!bsdf) { return NULL; } @@ -273,13 +275,13 @@ class PrincipledClearcoatClosure : public CBSDFClosure { return NULL; } - bsdf->T = make_float3(0.0f, 0.0f, 0.0f); + bsdf->T = zero_float3(); bsdf->extra = extra; bsdf->ior = 1.5f; bsdf->alpha_x = clearcoat_roughness; bsdf->alpha_y = clearcoat_roughness; - bsdf->extra->color = make_float3(0.0f, 0.0f, 0.0f); - bsdf->extra->cspec0 = make_float3(0.04f, 0.04f, 0.04f); + bsdf->extra->color = zero_spectrum(); + bsdf->extra->cspec0 = make_spectrum(0.04f); bsdf->extra->clearcoat = clearcoat; return bsdf; } @@ -511,7 +513,7 @@ class MicrofacetClosure : public CBSDFClosure { params.N = ensure_valid_reflection(sd->Ng, sd->I, params.N); MicrofacetBsdf *bsdf = (MicrofacetBsdf *)bsdf_alloc_osl( - sd, sizeof(MicrofacetBsdf), weight, ¶ms); + sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight), ¶ms); if (!bsdf) { return; @@ -586,7 +588,7 @@ class MicrofacetFresnelClosure : public CBSDFClosure { } MicrofacetBsdf *bsdf = (MicrofacetBsdf *)bsdf_alloc_osl( - sd, sizeof(MicrofacetBsdf), weight, ¶ms); + sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight), ¶ms); if (!bsdf) { return NULL; } @@ -597,8 +599,8 @@ class MicrofacetFresnelClosure : public CBSDFClosure { } bsdf->extra = extra; - bsdf->extra->color = color; - bsdf->extra->cspec0 = cspec0; + bsdf->extra->color = rgb_to_spectrum(color); + bsdf->extra->cspec0 = rgb_to_spectrum(cspec0); bsdf->extra->clearcoat = 0.0f; return bsdf; } @@ -615,7 +617,7 @@ class MicrofacetGGXFresnelClosure : public MicrofacetFresnelClosure { return; } - bsdf->T = make_float3(0.0f, 0.0f, 0.0f); + bsdf->T = zero_float3(); bsdf->alpha_y = bsdf->alpha_x; sd->flag |= bsdf_microfacet_ggx_fresnel_setup(bsdf, sd); } @@ -684,7 +686,7 @@ class MicrofacetMultiClosure : public CBSDFClosure { } MicrofacetBsdf *bsdf = (MicrofacetBsdf *)bsdf_alloc_osl( - sd, sizeof(MicrofacetBsdf), weight, ¶ms); + sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight), ¶ms); if (!bsdf) { return NULL; } @@ -695,8 +697,8 @@ class MicrofacetMultiClosure : public CBSDFClosure { } bsdf->extra = extra; - bsdf->extra->color = color; - bsdf->extra->cspec0 = make_float3(0.0f, 0.0f, 0.0f); + bsdf->extra->color = rgb_to_spectrum(color); + bsdf->extra->cspec0 = zero_spectrum(); bsdf->extra->clearcoat = 0.0f; return bsdf; } @@ -714,7 +716,7 @@ class MicrofacetMultiGGXClosure : public MicrofacetMultiClosure { } bsdf->ior = 0.0f; - bsdf->T = make_float3(0.0f, 0.0f, 0.0f); + bsdf->T = zero_float3(); bsdf->alpha_y = bsdf->alpha_x; sd->flag |= bsdf_microfacet_multi_ggx_setup(bsdf); } @@ -777,7 +779,7 @@ class MicrofacetMultiGGXGlassClosure : public MicrofacetMultiClosure { return; } - bsdf->T = make_float3(0.0f, 0.0f, 0.0f); + bsdf->T = zero_float3(); bsdf->alpha_y = bsdf->alpha_x; sd->flag |= bsdf_microfacet_multi_ggx_glass_setup(bsdf); } @@ -814,7 +816,7 @@ class MicrofacetMultiFresnelClosure : public CBSDFClosure { } MicrofacetBsdf *bsdf = (MicrofacetBsdf *)bsdf_alloc_osl( - sd, sizeof(MicrofacetBsdf), weight, ¶ms); + sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight), ¶ms); if (!bsdf) { return NULL; } @@ -825,8 +827,8 @@ class MicrofacetMultiFresnelClosure : public CBSDFClosure { } bsdf->extra = extra; - bsdf->extra->color = color; - bsdf->extra->cspec0 = cspec0; + bsdf->extra->color = rgb_to_spectrum(color); + bsdf->extra->cspec0 = rgb_to_spectrum(cspec0); bsdf->extra->clearcoat = 0.0f; return bsdf; } @@ -843,7 +845,7 @@ class MicrofacetMultiGGXFresnelClosure : public MicrofacetMultiFresnelClosure { return; } - bsdf->T = make_float3(0.0f, 0.0f, 0.0f); + bsdf->T = zero_float3(); bsdf->alpha_y = bsdf->alpha_x; sd->flag |= bsdf_microfacet_multi_ggx_fresnel_setup(bsdf, sd); } @@ -911,7 +913,7 @@ class MicrofacetMultiGGXGlassFresnelClosure : public MicrofacetMultiFresnelClosu return; } - bsdf->T = make_float3(0.0f, 0.0f, 0.0f); + bsdf->T = zero_float3(); bsdf->alpha_y = bsdf->alpha_x; sd->flag |= bsdf_microfacet_multi_ggx_glass_fresnel_setup(bsdf, sd); } @@ -941,7 +943,7 @@ class TransparentClosure : public CBSDFClosure { void setup(ShaderData *sd, uint32_t path_flag, float3 weight) { - bsdf_transparent_setup(sd, weight, path_flag); + bsdf_transparent_setup(sd, rgb_to_spectrum(weight), path_flag); } }; @@ -960,7 +962,7 @@ class VolumeAbsorptionClosure : public CBSDFClosure { public: void setup(ShaderData *sd, uint32_t path_flag, float3 weight) { - volume_extinction_setup(sd, weight); + volume_extinction_setup(sd, rgb_to_spectrum(weight)); } }; @@ -979,10 +981,10 @@ class VolumeHenyeyGreensteinClosure : public CBSDFClosure { void setup(ShaderData *sd, uint32_t path_flag, float3 weight) { - volume_extinction_setup(sd, weight); + volume_extinction_setup(sd, rgb_to_spectrum(weight)); HenyeyGreensteinVolume *volume = (HenyeyGreensteinVolume *)bsdf_alloc_osl( - sd, sizeof(HenyeyGreensteinVolume), weight, ¶ms); + sd, sizeof(HenyeyGreensteinVolume), rgb_to_spectrum(weight), ¶ms); if (!volume) { return; } diff --git a/intern/cycles/kernel/osl/closures.h b/intern/cycles/kernel/osl/closures.h index e10a3d88a04..97666be7a1e 100644 --- a/intern/cycles/kernel/osl/closures.h +++ b/intern/cycles/kernel/osl/closures.h @@ -115,7 +115,8 @@ class CBSDFClosure : public CClosurePrimitive { { \ if (!skip(sd, path_flag, TYPE)) { \ params.N = ensure_valid_reflection(sd->Ng, sd->I, params.N); \ - structname *bsdf = (structname *)bsdf_alloc_osl(sd, sizeof(structname), weight, ¶ms); \ + structname *bsdf = (structname *)bsdf_alloc_osl( \ + sd, sizeof(structname), rgb_to_spectrum(weight), ¶ms); \ sd->flag |= (bsdf) ? bsdf_##lower##_setup(bsdf) : 0; \ } \ } \ diff --git a/intern/cycles/kernel/osl/emissive.cpp b/intern/cycles/kernel/osl/emissive.cpp index 1a01b215836..8d1928d0126 100644 --- a/intern/cycles/kernel/osl/emissive.cpp +++ b/intern/cycles/kernel/osl/emissive.cpp @@ -14,9 +14,13 @@ // clang-format off #include "kernel/device/cpu/compat.h" +#include "kernel/device/cpu/globals.h" + #include "kernel/types.h" #include "kernel/closure/alloc.h" #include "kernel/closure/emissive.h" + +#include "kernel/util/color.h" // clang-format on CCL_NAMESPACE_BEGIN @@ -34,7 +38,7 @@ class GenericEmissiveClosure : public CClosurePrimitive { public: void setup(ShaderData *sd, uint32_t /* path_flag */, float3 weight) { - emission_setup(sd, weight); + emission_setup(sd, rgb_to_spectrum(weight)); } }; diff --git a/intern/cycles/kernel/svm/closure.h b/intern/cycles/kernel/svm/closure.h index 99a8fdd3be9..5e8ef69fd15 100644 --- a/intern/cycles/kernel/svm/closure.h +++ b/intern/cycles/kernel/svm/closure.h @@ -3,6 +3,8 @@ #pragma once +#include "kernel/util/color.h" + CCL_NAMESPACE_BEGIN /* Closure Nodes */ @@ -183,7 +185,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, } float3 subsurface_radius = stack_valid(data_cn_ssr.y) ? stack_load_float3(stack, data_cn_ssr.y) : - make_float3(1.0f, 1.0f, 1.0f); + one_float3(); float subsurface_ior = stack_valid(data_cn_ssr.z) ? stack_load_float(stack, data_cn_ssr.z) : 1.4f; float subsurface_anisotropy = stack_valid(data_cn_ssr.w) ? @@ -198,12 +200,12 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, __uint_as_float(data_subsurface_color.z), __uint_as_float(data_subsurface_color.w)); - float3 weight = sd->svm_closure_weight * mix_weight; + Spectrum weight = sd->svm_closure_weight * mix_weight; # ifdef __SUBSURFACE__ float3 mixed_ss_base_color = subsurface_color * subsurface + base_color * (1.0f - subsurface); - float3 subsurf_weight = weight * mixed_ss_base_color * diffuse_weight; + Spectrum subsurf_weight = weight * rgb_to_spectrum(mixed_ss_base_color) * diffuse_weight; /* disable in case of diffuse ancestor, can't see it well then and * adds considerably noise due to probabilities of continuing path @@ -220,7 +222,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, /* diffuse */ if (fabsf(average(mixed_ss_base_color)) > CLOSURE_WEIGHT_CUTOFF) { if (subsurface <= CLOSURE_WEIGHT_CUTOFF && diffuse_weight > CLOSURE_WEIGHT_CUTOFF) { - float3 diff_weight = weight * base_color * diffuse_weight; + Spectrum diff_weight = weight * rgb_to_spectrum(base_color) * diffuse_weight; ccl_private PrincipledDiffuseBsdf *bsdf = (ccl_private PrincipledDiffuseBsdf *) bsdf_alloc(sd, sizeof(PrincipledDiffuseBsdf), diff_weight); @@ -237,8 +239,8 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, ccl_private Bssrdf *bssrdf = bssrdf_alloc(sd, subsurf_weight); if (bssrdf) { - bssrdf->radius = subsurface_radius * subsurface; - bssrdf->albedo = mixed_ss_base_color; + bssrdf->radius = rgb_to_spectrum(subsurface_radius * subsurface); + bssrdf->albedo = rgb_to_spectrum(mixed_ss_base_color); bssrdf->N = N; bssrdf->roughness = roughness; @@ -254,7 +256,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, # else /* diffuse */ if (diffuse_weight > CLOSURE_WEIGHT_CUTOFF) { - float3 diff_weight = weight * base_color * diffuse_weight; + Spectrum diff_weight = weight * rgb_to_spectrum(base_color) * diffuse_weight; ccl_private PrincipledDiffuseBsdf *bsdf = (ccl_private PrincipledDiffuseBsdf *)bsdf_alloc( sd, sizeof(PrincipledDiffuseBsdf), diff_weight); @@ -272,15 +274,13 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, /* sheen */ if (diffuse_weight > CLOSURE_WEIGHT_CUTOFF && sheen > CLOSURE_WEIGHT_CUTOFF) { float m_cdlum = linear_rgb_to_gray(kg, base_color); - float3 m_ctint = m_cdlum > 0.0f ? - base_color / m_cdlum : - make_float3(1.0f, 1.0f, 1.0f); // normalize lum. to isolate hue+sat + float3 m_ctint = m_cdlum > 0.0f ? base_color / m_cdlum : + one_float3(); // normalize lum. to isolate hue+sat /* color of the sheen component */ - float3 sheen_color = make_float3(1.0f, 1.0f, 1.0f) * (1.0f - sheen_tint) + - m_ctint * sheen_tint; + float3 sheen_color = make_float3(1.0f - sheen_tint) + m_ctint * sheen_tint; - float3 sheen_weight = weight * sheen * sheen_color * diffuse_weight; + Spectrum sheen_weight = weight * sheen * rgb_to_spectrum(sheen_color) * diffuse_weight; ccl_private PrincipledSheenBsdf *bsdf = (ccl_private PrincipledSheenBsdf *)bsdf_alloc( sd, sizeof(PrincipledSheenBsdf), sheen_weight); @@ -299,7 +299,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, # endif if (specular_weight > CLOSURE_WEIGHT_CUTOFF && (specular > CLOSURE_WEIGHT_CUTOFF || metallic > CLOSURE_WEIGHT_CUTOFF)) { - float3 spec_weight = weight * specular_weight; + Spectrum spec_weight = weight * specular_weight; ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc( sd, sizeof(MicrofacetBsdf), spec_weight); @@ -322,16 +322,13 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, float m_cdlum = 0.3f * base_color.x + 0.6f * base_color.y + 0.1f * base_color.z; // luminance approx. - float3 m_ctint = m_cdlum > 0.0f ? - base_color / m_cdlum : - make_float3( - 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 - specular_tint) + - m_ctint * specular_tint; - - bsdf->extra->cspec0 = (specular * 0.08f * tmp_col) * (1.0f - metallic) + - base_color * metallic; - bsdf->extra->color = base_color; + float3 m_ctint = m_cdlum > 0.0f ? base_color / m_cdlum : + one_float3(); // normalize lum. to isolate hue+sat + float3 tmp_col = make_float3(1.0f - specular_tint) + m_ctint * specular_tint; + + bsdf->extra->cspec0 = rgb_to_spectrum( + (specular * 0.08f * tmp_col) * (1.0f - metallic) + base_color * metallic); + bsdf->extra->color = rgb_to_spectrum(base_color); bsdf->extra->clearcoat = 0.0f; /* setup bsdf */ @@ -352,9 +349,8 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, kernel_data.integrator.caustics_refractive || (path_flag & PATH_RAY_DIFFUSE) == 0) { # endif if (final_transmission > CLOSURE_WEIGHT_CUTOFF) { - float3 glass_weight = weight * final_transmission; - float3 cspec0 = base_color * specular_tint + - make_float3(1.0f, 1.0f, 1.0f) * (1.0f - specular_tint); + Spectrum glass_weight = weight * final_transmission; + float3 cspec0 = base_color * specular_tint + make_float3(1.0f - specular_tint); if (roughness <= 5e-2f || distribution == CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID) { /* use single-scatter GGX */ @@ -374,15 +370,15 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, if (bsdf && extra) { bsdf->N = N; - bsdf->T = make_float3(0.0f, 0.0f, 0.0f); + bsdf->T = zero_float3(); bsdf->extra = extra; bsdf->alpha_x = refl_roughness * refl_roughness; bsdf->alpha_y = refl_roughness * refl_roughness; bsdf->ior = ior; - bsdf->extra->color = base_color; - bsdf->extra->cspec0 = cspec0; + bsdf->extra->color = rgb_to_spectrum(base_color); + bsdf->extra->cspec0 = rgb_to_spectrum(cspec0); bsdf->extra->clearcoat = 0.0f; /* setup bsdf */ @@ -398,10 +394,12 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, /* This is to prevent MNEE from receiving a null BSDF. */ float refraction_fresnel = fmaxf(0.0001f, 1.0f - fresnel); ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc( - sd, sizeof(MicrofacetBsdf), base_color * glass_weight * refraction_fresnel); + sd, + sizeof(MicrofacetBsdf), + rgb_to_spectrum(base_color) * glass_weight * refraction_fresnel); if (bsdf) { bsdf->N = N; - bsdf->T = make_float3(0.0f, 0.0f, 0.0f); + bsdf->T = zero_float3(); bsdf->extra = NULL; if (distribution == CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID) @@ -430,14 +428,14 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, if (bsdf && extra) { bsdf->N = N; bsdf->extra = extra; - bsdf->T = make_float3(0.0f, 0.0f, 0.0f); + bsdf->T = zero_float3(); bsdf->alpha_x = roughness * roughness; bsdf->alpha_y = roughness * roughness; bsdf->ior = ior; - bsdf->extra->color = base_color; - bsdf->extra->cspec0 = cspec0; + bsdf->extra->color = rgb_to_spectrum(base_color); + bsdf->extra->cspec0 = rgb_to_spectrum(cspec0); bsdf->extra->clearcoat = 0.0f; /* setup bsdf */ @@ -463,15 +461,15 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, if (bsdf && extra) { bsdf->N = clearcoat_normal; - bsdf->T = make_float3(0.0f, 0.0f, 0.0f); + bsdf->T = zero_float3(); bsdf->ior = 1.5f; bsdf->extra = extra; bsdf->alpha_x = clearcoat_roughness * clearcoat_roughness; bsdf->alpha_y = clearcoat_roughness * clearcoat_roughness; - bsdf->extra->color = make_float3(0.0f, 0.0f, 0.0f); - bsdf->extra->cspec0 = make_float3(0.04f, 0.04f, 0.04f); + bsdf->extra->color = zero_spectrum(); + bsdf->extra->cspec0 = make_spectrum(0.04f); bsdf->extra->clearcoat = clearcoat; /* setup bsdf */ @@ -486,7 +484,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, } #endif /* __PRINCIPLED__ */ case CLOSURE_BSDF_DIFFUSE_ID: { - float3 weight = sd->svm_closure_weight * mix_weight; + Spectrum weight = sd->svm_closure_weight * mix_weight; ccl_private OrenNayarBsdf *bsdf = (ccl_private OrenNayarBsdf *)bsdf_alloc( sd, sizeof(OrenNayarBsdf), weight); @@ -506,7 +504,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, break; } case CLOSURE_BSDF_TRANSLUCENT_ID: { - float3 weight = sd->svm_closure_weight * mix_weight; + Spectrum weight = sd->svm_closure_weight * mix_weight; ccl_private DiffuseBsdf *bsdf = (ccl_private DiffuseBsdf *)bsdf_alloc( sd, sizeof(DiffuseBsdf), weight); @@ -517,7 +515,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, break; } case CLOSURE_BSDF_TRANSPARENT_ID: { - float3 weight = sd->svm_closure_weight * mix_weight; + Spectrum weight = sd->svm_closure_weight * mix_weight; bsdf_transparent_setup(sd, weight, path_flag); break; } @@ -530,7 +528,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, if (!kernel_data.integrator.caustics_reflective && (path_flag & PATH_RAY_DIFFUSE)) break; #endif - float3 weight = sd->svm_closure_weight * mix_weight; + Spectrum weight = sd->svm_closure_weight * mix_weight; ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc( sd, sizeof(MicrofacetBsdf), weight); @@ -545,7 +543,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, bsdf->extra = NULL; if (data_node.y == SVM_STACK_INVALID) { - bsdf->T = make_float3(0.0f, 0.0f, 0.0f); + bsdf->T = zero_float3(); bsdf->alpha_x = roughness; bsdf->alpha_y = roughness; } @@ -581,8 +579,8 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, bsdf->extra = (ccl_private MicrofacetExtra *)closure_alloc_extra(sd, sizeof(MicrofacetExtra)); if (bsdf->extra) { - bsdf->extra->color = stack_load_float3(stack, data_node.w); - bsdf->extra->cspec0 = make_float3(0.0f, 0.0f, 0.0f); + bsdf->extra->color = rgb_to_spectrum(stack_load_float3(stack, data_node.w)); + bsdf->extra->cspec0 = zero_spectrum(); bsdf->extra->clearcoat = 0.0f; sd->flag |= bsdf_microfacet_multi_ggx_setup(bsdf); } @@ -600,13 +598,13 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, if (!kernel_data.integrator.caustics_refractive && (path_flag & PATH_RAY_DIFFUSE)) break; #endif - float3 weight = sd->svm_closure_weight * mix_weight; + Spectrum weight = sd->svm_closure_weight * mix_weight; ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc( sd, sizeof(MicrofacetBsdf), weight); if (bsdf) { bsdf->N = N; - bsdf->T = make_float3(0.0f, 0.0f, 0.0f); + bsdf->T = zero_float3(); bsdf->extra = NULL; float eta = fmaxf(param2, 1e-5f); @@ -644,7 +642,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, break; } #endif - float3 weight = sd->svm_closure_weight * mix_weight; + Spectrum weight = sd->svm_closure_weight * mix_weight; /* index of refraction */ float eta = fmaxf(param2, 1e-5f); @@ -665,7 +663,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, if (bsdf) { bsdf->N = N; - bsdf->T = make_float3(0.0f, 0.0f, 0.0f); + bsdf->T = zero_float3(); bsdf->extra = NULL; svm_node_glass_setup(sd, bsdf, type, eta, roughness, false); } @@ -683,7 +681,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, if (bsdf) { bsdf->N = N; - bsdf->T = make_float3(0.0f, 0.0f, 0.0f); + bsdf->T = zero_float3(); bsdf->extra = NULL; svm_node_glass_setup(sd, bsdf, type, eta, roughness, true); } @@ -697,7 +695,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, !kernel_data.integrator.caustics_refractive && (path_flag & PATH_RAY_DIFFUSE)) break; #endif - float3 weight = sd->svm_closure_weight * mix_weight; + Spectrum weight = sd->svm_closure_weight * mix_weight; ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc( sd, sizeof(MicrofacetBsdf), weight); if (!bsdf) { @@ -712,7 +710,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, bsdf->N = N; bsdf->extra = extra; - bsdf->T = make_float3(0.0f, 0.0f, 0.0f); + bsdf->T = zero_float3(); float roughness = sqr(param1); bsdf->alpha_x = roughness; @@ -721,8 +719,8 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, bsdf->ior = (sd->flag & SD_BACKFACING) ? 1.0f / eta : eta; kernel_assert(stack_valid(data_node.z)); - bsdf->extra->color = stack_load_float3(stack, data_node.z); - bsdf->extra->cspec0 = make_float3(0.0f, 0.0f, 0.0f); + bsdf->extra->color = rgb_to_spectrum(stack_load_float3(stack, data_node.z)); + bsdf->extra->cspec0 = zero_spectrum(); bsdf->extra->clearcoat = 0.0f; /* setup bsdf */ @@ -730,7 +728,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, break; } case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: { - float3 weight = sd->svm_closure_weight * mix_weight; + Spectrum weight = sd->svm_closure_weight * mix_weight; ccl_private VelvetBsdf *bsdf = (ccl_private VelvetBsdf *)bsdf_alloc( sd, sizeof(VelvetBsdf), weight); @@ -749,7 +747,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, ATTR_FALLTHROUGH; #endif case CLOSURE_BSDF_DIFFUSE_TOON_ID: { - float3 weight = sd->svm_closure_weight * mix_weight; + Spectrum weight = sd->svm_closure_weight * mix_weight; ccl_private ToonBsdf *bsdf = (ccl_private ToonBsdf *)bsdf_alloc( sd, sizeof(ToonBsdf), weight); @@ -771,7 +769,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, uint4 data_node3 = read_node(kg, &offset); uint4 data_node4 = read_node(kg, &offset); - float3 weight = sd->svm_closure_weight * mix_weight; + Spectrum weight = sd->svm_closure_weight * mix_weight; uint offset_ofs, ior_ofs, color_ofs, parametrization; svm_unpack_node_uchar4(data_node.y, &offset_ofs, &ior_ofs, &color_ofs, ¶metrization); @@ -829,7 +827,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, switch (parametrization) { case NODE_PRINCIPLED_HAIR_DIRECT_ABSORPTION: { float3 absorption_coefficient = stack_load_float3(stack, absorption_coefficient_ofs); - bsdf->sigma = absorption_coefficient; + bsdf->sigma = rgb_to_spectrum(absorption_coefficient); break; } case NODE_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION: { @@ -849,20 +847,21 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, /* Benedikt Bitterli's melanin ratio remapping. */ float eumelanin = melanin * (1.0f - melanin_redness); float pheomelanin = melanin * melanin_redness; - float3 melanin_sigma = bsdf_principled_hair_sigma_from_concentration(eumelanin, - pheomelanin); + Spectrum melanin_sigma = bsdf_principled_hair_sigma_from_concentration(eumelanin, + pheomelanin); /* Optional tint. */ float3 tint = stack_load_float3(stack, tint_ofs); - float3 tint_sigma = bsdf_principled_hair_sigma_from_reflectance(tint, - radial_roughness); + Spectrum tint_sigma = bsdf_principled_hair_sigma_from_reflectance( + rgb_to_spectrum(tint), radial_roughness); bsdf->sigma = melanin_sigma + tint_sigma; break; } case NODE_PRINCIPLED_HAIR_REFLECTANCE: { float3 color = stack_load_float3(stack, color_ofs); - bsdf->sigma = bsdf_principled_hair_sigma_from_reflectance(color, radial_roughness); + bsdf->sigma = bsdf_principled_hair_sigma_from_reflectance(rgb_to_spectrum(color), + radial_roughness); break; } default: { @@ -879,7 +878,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, } case CLOSURE_BSDF_HAIR_REFLECTION_ID: case CLOSURE_BSDF_HAIR_TRANSMISSION_ID: { - float3 weight = sd->svm_closure_weight * mix_weight; + Spectrum weight = sd->svm_closure_weight * mix_weight; ccl_private HairBsdf *bsdf = (ccl_private HairBsdf *)bsdf_alloc( sd, sizeof(HairBsdf), weight); @@ -916,7 +915,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, case CLOSURE_BSSRDF_BURLEY_ID: case CLOSURE_BSSRDF_RANDOM_WALK_ID: case CLOSURE_BSSRDF_RANDOM_WALK_FIXED_RADIUS_ID: { - float3 weight = sd->svm_closure_weight * mix_weight; + Spectrum weight = sd->svm_closure_weight * mix_weight; ccl_private Bssrdf *bssrdf = bssrdf_alloc(sd, weight); if (bssrdf) { @@ -926,7 +925,7 @@ ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, if (path_flag & PATH_RAY_DIFFUSE_ANCESTOR) param1 = 0.0f; - bssrdf->radius = stack_load_float3(stack, data_node.z) * param1; + bssrdf->radius = rgb_to_spectrum(stack_load_float3(stack, data_node.z) * param1); bssrdf->albedo = sd->svm_closure_weight; bssrdf->N = N; bssrdf->roughness = FLT_MAX; @@ -976,10 +975,10 @@ ccl_device_noinline void svm_node_closure_volume(KernelGlobals kg, density = mix_weight * fmaxf(density, 0.0f); /* Compute scattering coefficient. */ - float3 weight = sd->svm_closure_weight; + Spectrum weight = sd->svm_closure_weight; if (type == CLOSURE_VOLUME_ABSORPTION_ID) { - weight = make_float3(1.0f, 1.0f, 1.0f) - weight; + weight = one_spectrum() - weight; } weight *= density; @@ -1047,11 +1046,11 @@ ccl_device_noinline int svm_node_principled_volume(KernelGlobals kg, if (density > CLOSURE_WEIGHT_CUTOFF) { /* Compute scattering color. */ - float3 color = sd->svm_closure_weight; + Spectrum color = sd->svm_closure_weight; const AttributeDescriptor attr_color = find_attribute(kg, sd, attr_node.y); if (attr_color.offset != ATTR_STD_NOT_FOUND) { - color *= primitive_volume_attribute_float3(kg, sd, attr_color); + color *= rgb_to_spectrum(primitive_volume_attribute_float3(kg, sd, attr_color)); } /* Add closure for volume scattering. */ @@ -1066,10 +1065,13 @@ ccl_device_noinline int svm_node_principled_volume(KernelGlobals kg, } /* Add extinction weight. */ - float3 zero = make_float3(0.0f, 0.0f, 0.0f); - float3 one = make_float3(1.0f, 1.0f, 1.0f); - float3 absorption_color = max(sqrt(stack_load_float3(stack, absorption_color_offset)), zero); - float3 absorption = max(one - color, zero) * max(one - absorption_color, zero); + float3 absorption_color = max(sqrt(stack_load_float3(stack, absorption_color_offset)), + zero_float3()); + + Spectrum zero = zero_spectrum(); + Spectrum one = one_spectrum(); + Spectrum absorption = max(one - color, zero) * + max(one - rgb_to_spectrum(absorption_color), zero); volume_extinction_setup(sd, (color + absorption) * density); } @@ -1089,7 +1091,7 @@ ccl_device_noinline int svm_node_principled_volume(KernelGlobals kg, if (emission > CLOSURE_WEIGHT_CUTOFF) { float3 emission_color = stack_load_float3(stack, emission_color_offset); - emission_setup(sd, emission * emission_color); + emission_setup(sd, rgb_to_spectrum(emission * emission_color)); } if (blackbody > CLOSURE_WEIGHT_CUTOFF) { @@ -1113,7 +1115,7 @@ ccl_device_noinline int svm_node_principled_volume(KernelGlobals kg, float3 blackbody_tint = stack_load_float3(stack, node.w); float3 bb = blackbody_tint * intensity * rec709_to_rgb(kg, svm_math_blackbody_color_rec709(T)); - emission_setup(sd, bb); + emission_setup(sd, rgb_to_spectrum(bb)); } } #endif @@ -1125,7 +1127,7 @@ ccl_device_noinline void svm_node_closure_emission(ccl_private ShaderData *sd, uint4 node) { uint mix_weight_offset = node.y; - float3 weight = sd->svm_closure_weight; + Spectrum weight = sd->svm_closure_weight; if (stack_valid(mix_weight_offset)) { float mix_weight = stack_load_float(stack, mix_weight_offset); @@ -1144,7 +1146,7 @@ ccl_device_noinline void svm_node_closure_background(ccl_private ShaderData *sd, uint4 node) { uint mix_weight_offset = node.y; - float3 weight = sd->svm_closure_weight; + Spectrum weight = sd->svm_closure_weight; if (stack_valid(mix_weight_offset)) { float mix_weight = stack_load_float(stack, mix_weight_offset); @@ -1181,14 +1183,15 @@ ccl_device_noinline void svm_node_closure_holdout(ccl_private ShaderData *sd, /* Closure Nodes */ -ccl_device_inline void svm_node_closure_store_weight(ccl_private ShaderData *sd, float3 weight) +ccl_device_inline void svm_node_closure_store_weight(ccl_private ShaderData *sd, Spectrum weight) { sd->svm_closure_weight = weight; } ccl_device void svm_node_closure_set_weight(ccl_private ShaderData *sd, uint r, uint g, uint b) { - float3 weight = make_float3(__uint_as_float(r), __uint_as_float(g), __uint_as_float(b)); + Spectrum weight = rgb_to_spectrum( + make_float3(__uint_as_float(r), __uint_as_float(g), __uint_as_float(b))); svm_node_closure_store_weight(sd, weight); } @@ -1196,7 +1199,7 @@ ccl_device void svm_node_closure_weight(ccl_private ShaderData *sd, ccl_private float *stack, uint weight_offset) { - float3 weight = stack_load_float3(stack, weight_offset); + Spectrum weight = rgb_to_spectrum(stack_load_float3(stack, weight_offset)); svm_node_closure_store_weight(sd, weight); } @@ -1209,7 +1212,7 @@ ccl_device_noinline void svm_node_emission_weight(KernelGlobals kg, uint strength_offset = node.z; float strength = stack_load_float(stack, strength_offset); - float3 weight = stack_load_float3(stack, color_offset) * strength; + Spectrum weight = rgb_to_spectrum(stack_load_float3(stack, color_offset)) * strength; svm_node_closure_store_weight(sd, weight); } diff --git a/intern/cycles/kernel/types.h b/intern/cycles/kernel/types.h index 7762c95275e..252c27a40f0 100644 --- a/intern/cycles/kernel/types.h +++ b/intern/cycles/kernel/types.h @@ -413,9 +413,9 @@ typedef enum CryptomatteType { } CryptomatteType; typedef struct BsdfEval { - float3 diffuse; - float3 glossy; - float3 sum; + Spectrum diffuse; + Spectrum glossy; + Spectrum sum; } BsdfEval; /* Closure Filter */ @@ -709,7 +709,7 @@ typedef struct AttributeMap { * padded to be 16 bytes, while it's only 12 bytes on the GPU. */ #define SHADER_CLOSURE_BASE \ - float3 weight; \ + Spectrum weight; \ ClosureType type; \ float sample_weight; \ float3 N @@ -718,10 +718,9 @@ typedef struct ccl_align(16) ShaderClosure { SHADER_CLOSURE_BASE; -#ifndef __KERNEL_GPU__ - float pad[2]; -#endif - float data[10]; + /* Extra space for closures to store data, somewhat arbitrary but closures + * assert that their size fits. */ + char pad[sizeof(Spectrum) * 2 + sizeof(float) * 4]; } ShaderClosure; @@ -912,12 +911,12 @@ typedef struct ccl_align(16) ShaderData /* Closure data, we store a fixed array of closures */ int num_closure; int num_closure_left; - float3 svm_closure_weight; + Spectrum svm_closure_weight; /* Closure weights summed directly, so we can evaluate * emission and shadow transparency with MAX_CLOSURE 0. */ - float3 closure_emission_background; - float3 closure_transparent_extinction; + Spectrum closure_emission_background; + Spectrum closure_transparent_extinction; /* At the end so we can adjust size in ShaderDataTinyStorage. */ struct ShaderClosure closure[MAX_CLOSURE]; @@ -948,7 +947,7 @@ ShaderDataCausticsStorage; * Used for decoupled direct/indirect light closure storage. */ typedef struct ShaderVolumeClosure { - float3 weight; + Spectrum weight; float sample_weight; float g; } ShaderVolumeClosure; diff --git a/intern/cycles/kernel/util/color.h b/intern/cycles/kernel/util/color.h index c85ef262d88..4983b9048d4 100644 --- a/intern/cycles/kernel/util/color.h +++ b/intern/cycles/kernel/util/color.h @@ -33,4 +33,19 @@ ccl_device float linear_rgb_to_gray(KernelGlobals kg, float3 c) return dot(c, float4_to_float3(kernel_data.film.rgb_to_y)); } +ccl_device_inline Spectrum rgb_to_spectrum(float3 rgb) +{ + return rgb; +} + +ccl_device_inline float3 spectrum_to_rgb(Spectrum s) +{ + return s; +} + +ccl_device float spectrum_to_gray(KernelGlobals kg, Spectrum c) +{ + return linear_rgb_to_gray(kg, spectrum_to_rgb(c)); +} + CCL_NAMESPACE_END diff --git a/intern/cycles/scene/image_oiio.cpp b/intern/cycles/scene/image_oiio.cpp index 500e53ed763..8792393e5a1 100644 --- a/intern/cycles/scene/image_oiio.cpp +++ b/intern/cycles/scene/image_oiio.cpp @@ -184,9 +184,8 @@ bool OIIOImageLoader::load_pixels(const ImageMetaData &metadata, ImageSpec config = ImageSpec(); /* Load without automatic OIIO alpha conversion, we do it ourselves. OIIO - * will associate alpha in the the 8bit buffer for PNGs, which leads to too - * much precision loss when we load it as half float to do a colorspace - * transform. */ + * will associate alpha in the 8bit buffer for PNGs, which leads to too + * much precision loss when we load it as half float to do a color-space transform. */ config.attribute("oiio:UnassociatedAlpha", 1); if (!in->open(filepath.string(), spec, config)) { diff --git a/intern/cycles/session/session.cpp b/intern/cycles/session/session.cpp index c94b53535a7..e5df22211e7 100644 --- a/intern/cycles/session/session.cpp +++ b/intern/cycles/session/session.cpp @@ -503,7 +503,9 @@ void Session::do_delayed_reset() if (!params.background) { progress.set_start_time(); } + const double time_limit = params.time_limit * ((double)tile_manager_.get_num_tiles()); progress.set_render_start_time(); + progress.set_time_limit(time_limit); } void Session::reset(const SessionParams &session_params, const BufferParams &buffer_params) @@ -598,7 +600,8 @@ double Session::get_estimated_remaining_time() const progress.get_time(total_time, render_time); double remaining = (1.0 - (double)completed) * (render_time / (double)completed); - const double time_limit = render_scheduler_.get_time_limit(); + const double time_limit = render_scheduler_.get_time_limit() * + ((double)tile_manager_.get_num_tiles()); if (time_limit != 0.0) { remaining = min(remaining, max(time_limit - render_time, 0.0)); } diff --git a/intern/cycles/util/CMakeLists.txt b/intern/cycles/util/CMakeLists.txt index f3fc7739f66..81a7607baab 100644 --- a/intern/cycles/util/CMakeLists.txt +++ b/intern/cycles/util/CMakeLists.txt @@ -118,6 +118,7 @@ set(SRC_HEADERS types_int3_impl.h types_int4.h types_int4_impl.h + types_spectrum.h types_uchar2.h types_uchar2_impl.h types_uchar3.h @@ -131,8 +132,6 @@ set(SRC_HEADERS types_uint4.h types_uint4_impl.h types_ushort4.h - types_vector3.h - types_vector3_impl.h unique_ptr.h vector.h version.h diff --git a/intern/cycles/util/debug.cpp b/intern/cycles/util/debug.cpp index faa54a92c24..8210e21f951 100644 --- a/intern/cycles/util/debug.cpp +++ b/intern/cycles/util/debug.cpp @@ -13,7 +13,6 @@ CCL_NAMESPACE_BEGIN DebugFlags::CPU::CPU() - : avx2(true), avx(true), sse41(true), sse3(true), sse2(true), bvh_layout(BVH_LAYOUT_AUTO) { reset(); } @@ -41,17 +40,17 @@ void DebugFlags::CPU::reset() bvh_layout = BVH_LAYOUT_AUTO; } -DebugFlags::CUDA::CUDA() : adaptive_compile(false) +DebugFlags::CUDA::CUDA() { reset(); } -DebugFlags::HIP::HIP() : adaptive_compile(false) +DebugFlags::HIP::HIP() { reset(); } -DebugFlags::Metal::Metal() : adaptive_compile(false) +DebugFlags::Metal::Metal() { reset(); } @@ -84,14 +83,13 @@ void DebugFlags::OptiX::reset() use_debug = false; } -DebugFlags::DebugFlags() : viewport_static_bvh(false), running_inside_blender(false) +DebugFlags::DebugFlags() { /* Nothing for now. */ } void DebugFlags::reset() { - viewport_static_bvh = false; cpu.reset(); cuda.reset(); optix.reset(); diff --git a/intern/cycles/util/debug.h b/intern/cycles/util/debug.h index 3565fdea17f..ab200649f59 100644 --- a/intern/cycles/util/debug.h +++ b/intern/cycles/util/debug.h @@ -17,11 +17,6 @@ CCL_NAMESPACE_BEGIN */ class DebugFlags { public: - /* Use static BVH in viewport, to match final render exactly. */ - bool viewport_static_bvh; - - bool running_inside_blender; - /* Descriptor of CPU feature-set to be used. */ struct CPU { CPU(); @@ -30,11 +25,11 @@ class DebugFlags { void reset(); /* Flags describing which instructions sets are allowed for use. */ - bool avx2; - bool avx; - bool sse41; - bool sse3; - bool sse2; + bool avx2 = true; + bool avx = true; + bool sse41 = true; + bool sse3 = true; + bool sse2 = true; /* Check functions to see whether instructions up to the given one * are allowed for use. @@ -65,7 +60,7 @@ class DebugFlags { * By default the fastest will be used. For debugging the BVH used by other * CPUs and GPUs can be selected here instead. */ - BVHLayout bvh_layout; + BVHLayout bvh_layout = BVH_LAYOUT_AUTO; }; /* Descriptor of CUDA feature-set to be used. */ @@ -77,7 +72,7 @@ class DebugFlags { /* Whether adaptive feature based runtime compile is enabled or not. * Requires the CUDA Toolkit and only works on Linux at the moment. */ - bool adaptive_compile; + bool adaptive_compile = false; }; /* Descriptor of HIP feature-set to be used. */ @@ -88,7 +83,7 @@ class DebugFlags { void reset(); /* Whether adaptive feature based runtime compile is enabled or not. */ - bool adaptive_compile; + bool adaptive_compile = false; }; /* Descriptor of OptiX feature-set to be used. */ @@ -100,7 +95,7 @@ class DebugFlags { /* Load OptiX module with debug capabilities. Will lower logging verbosity level, enable * validations, and lower optimization level. */ - bool use_debug; + bool use_debug = false; }; /* Descriptor of Metal feature-set to be used. */ @@ -111,7 +106,7 @@ class DebugFlags { void reset(); /* Whether adaptive feature based runtime compile is enabled or not. */ - bool adaptive_compile; + bool adaptive_compile = false; }; /* Get instance of debug flags registry. */ @@ -142,15 +137,9 @@ class DebugFlags { private: DebugFlags(); -#if (__cplusplus > 199711L) public: explicit DebugFlags(DebugFlags const & /*other*/) = delete; void operator=(DebugFlags const & /*other*/) = delete; -#else - private: - explicit DebugFlags(DebugFlags const & /*other*/); - void operator=(DebugFlags const & /*other*/); -#endif }; typedef DebugFlags &DebugFlagsRef; diff --git a/intern/cycles/util/defines.h b/intern/cycles/util/defines.h index d0df1a221fc..c7118ca09c9 100644 --- a/intern/cycles/util/defines.h +++ b/intern/cycles/util/defines.h @@ -136,4 +136,7 @@ template<typename T> static inline T decltype_helper(T x) # define util_assert(statement) #endif +#define CONCAT_HELPER(a, ...) a##__VA_ARGS__ +#define CONCAT(a, ...) CONCAT_HELPER(a, __VA_ARGS__) + #endif /* __UTIL_DEFINES_H__ */ diff --git a/intern/cycles/util/math.h b/intern/cycles/util/math.h index f6400cb879f..0585dcc8ad5 100644 --- a/intern/cycles/util/math.h +++ b/intern/cycles/util/math.h @@ -595,26 +595,26 @@ ccl_device_inline void make_orthonormals(const float3 N, /* Color division */ -ccl_device_inline float3 safe_invert_color(float3 a) +ccl_device_inline Spectrum safe_invert_color(Spectrum a) { - float x, y, z; - - x = (a.x != 0.0f) ? 1.0f / a.x : 0.0f; - y = (a.y != 0.0f) ? 1.0f / a.y : 0.0f; - z = (a.z != 0.0f) ? 1.0f / a.z : 0.0f; + FOREACH_SPECTRUM_CHANNEL (i) { + GET_SPECTRUM_CHANNEL(a, i) = (GET_SPECTRUM_CHANNEL(a, i) != 0.0f) ? + 1.0f / GET_SPECTRUM_CHANNEL(a, i) : + 0.0f; + } - return make_float3(x, y, z); + return a; } -ccl_device_inline float3 safe_divide_color(float3 a, float3 b) +ccl_device_inline Spectrum safe_divide_color(Spectrum a, Spectrum b) { - float x, y, z; - - x = (b.x != 0.0f) ? a.x / b.x : 0.0f; - y = (b.y != 0.0f) ? a.y / b.y : 0.0f; - z = (b.z != 0.0f) ? a.z / b.z : 0.0f; + FOREACH_SPECTRUM_CHANNEL (i) { + GET_SPECTRUM_CHANNEL(a, i) = (GET_SPECTRUM_CHANNEL(b, i) != 0.0f) ? + GET_SPECTRUM_CHANNEL(a, i) / GET_SPECTRUM_CHANNEL(b, i) : + 0.0f; + } - return make_float3(x, y, z); + return a; } ccl_device_inline float3 safe_divide_even_color(float3 a, float3 b) diff --git a/intern/cycles/util/progress.h b/intern/cycles/util/progress.h index 37eafd57491..586979d2021 100644 --- a/intern/cycles/util/progress.h +++ b/intern/cycles/util/progress.h @@ -28,6 +28,7 @@ class Progress { denoised_tiles = 0; start_time = time_dt(); render_start_time = time_dt(); + time_limit = 0.0; end_time = 0.0; status = "Initializing"; substatus = ""; @@ -68,6 +69,7 @@ class Progress { denoised_tiles = 0; start_time = time_dt(); render_start_time = time_dt(); + time_limit = 0.0; end_time = 0.0; status = "Initializing"; substatus = ""; @@ -145,6 +147,13 @@ class Progress { render_start_time = time_dt(); } + void set_time_limit(double time_limit_) + { + thread_scoped_lock lock(progress_mutex); + + time_limit = time_limit_; + } + void add_skip_time(const scoped_timer &start_timer, bool only_render) { double skip_time = time_dt() - start_timer.get_start(); @@ -191,8 +200,13 @@ class Progress { { thread_scoped_lock lock(progress_mutex); - if (total_pixel_samples > 0) { - return ((double)pixel_samples) / (double)total_pixel_samples; + if (pixel_samples > 0) { + double progress_percent = (double)pixel_samples / (double)total_pixel_samples; + if (time_limit != 0.0) { + double time_since_render_start = time_dt() - render_start_time; + progress_percent = max(progress_percent, time_since_render_start / time_limit); + } + return min(1.0, progress_percent); } return 0.0; } @@ -335,7 +349,7 @@ class Progress { * in which case the current_tile_sample is displayed. */ int rendered_tiles, denoised_tiles; - double start_time, render_start_time; + double start_time, render_start_time, time_limit; /* End time written when render is done, so it doesn't keep increasing on redraws. */ double end_time; diff --git a/intern/cycles/util/types.h b/intern/cycles/util/types.h index 031c2f7c4c1..1ab6f76f9bc 100644 --- a/intern/cycles/util/types.h +++ b/intern/cycles/util/types.h @@ -12,6 +12,7 @@ #if !defined(__KERNEL_GPU__) # include <stdint.h> +# include <stdio.h> #endif #include "util/defines.h" @@ -70,6 +71,24 @@ ccl_device_inline bool is_power_of_two(size_t x) CCL_NAMESPACE_END +/* Device side printf only tested on CUDA, may work on more GPU devices. */ +#if !defined(__KERNEL_GPU__) || defined(__KERNEL_CUDA__) +# define __KERNEL_PRINTF__ +#endif + +ccl_device_inline void print_float(ccl_private const char *label, const float a) +{ +#ifdef __KERNEL_PRINTF__ + printf("%s: %.8f\n", label, (double)a); +#endif +} + +/* Most GPU APIs matching native vector types, so we only need to implement them for + * CPU and oneAPI. */ +#if defined(__KERNEL_GPU__) && !defined(__KERNEL_ONEAPI__) +# define __KERNEL_NATIVE_VECTOR_TYPES__ +#endif + /* Vectorized types declaration. */ #include "util/types_uchar2.h" #include "util/types_uchar3.h" @@ -90,7 +109,7 @@ CCL_NAMESPACE_END #include "util/types_float4.h" #include "util/types_float8.h" -#include "util/types_vector3.h" +#include "util/types_spectrum.h" /* Vectorized types implementation. */ #include "util/types_uchar2_impl.h" @@ -110,8 +129,6 @@ CCL_NAMESPACE_END #include "util/types_float4_impl.h" #include "util/types_float8_impl.h" -#include "util/types_vector3_impl.h" - /* SSE types. */ #ifndef __KERNEL_GPU__ # include "util/sseb.h" diff --git a/intern/cycles/util/types_float2.h b/intern/cycles/util/types_float2.h index 07b9ec0986b..ea510ef832c 100644 --- a/intern/cycles/util/types_float2.h +++ b/intern/cycles/util/types_float2.h @@ -1,8 +1,7 @@ /* SPDX-License-Identifier: Apache-2.0 * Copyright 2011-2022 Blender Foundation */ -#ifndef __UTIL_TYPES_FLOAT2_H__ -#define __UTIL_TYPES_FLOAT2_H__ +#pragma once #ifndef __UTIL_TYPES_H__ # error "Do not include this file directly, include util/types.h instead." @@ -10,18 +9,19 @@ CCL_NAMESPACE_BEGIN -#if !defined(__KERNEL_GPU__) || defined(__KERNEL_ONEAPI__) +#ifndef __KERNEL_NATIVE_VECTOR_TYPES__ struct float2 { float x, y; +# ifndef __KERNEL_GPU__ __forceinline float operator[](int i) const; __forceinline float &operator[](int i); +# endif }; ccl_device_inline float2 make_float2(float x, float y); -ccl_device_inline void print_float2(const char *label, const float2 &a); -#endif /* !defined(__KERNEL_GPU__) || defined(__KERNEL_ONEAPI__) */ +#endif /* __KERNEL_NATIVE_VECTOR_TYPES__ */ -CCL_NAMESPACE_END +ccl_device_inline void print_float2(ccl_private const char *label, const float2 a); -#endif /* __UTIL_TYPES_FLOAT2_H__ */ +CCL_NAMESPACE_END diff --git a/intern/cycles/util/types_float2_impl.h b/intern/cycles/util/types_float2_impl.h index 45fc90c52bd..7ba7dee2e3a 100644 --- a/intern/cycles/util/types_float2_impl.h +++ b/intern/cycles/util/types_float2_impl.h @@ -1,20 +1,16 @@ /* SPDX-License-Identifier: Apache-2.0 * Copyright 2011-2022 Blender Foundation */ -#ifndef __UTIL_TYPES_FLOAT2_IMPL_H__ -#define __UTIL_TYPES_FLOAT2_IMPL_H__ +#pragma once #ifndef __UTIL_TYPES_H__ # error "Do not include this file directly, include util/types.h instead." #endif -#ifndef __KERNEL_GPU__ -# include <cstdio> -#endif - CCL_NAMESPACE_BEGIN -#if !defined(__KERNEL_GPU__) || defined(__KERNEL_ONEAPI__) +#ifndef __KERNEL_NATIVE_VECTOR_TYPES__ +# ifndef __KERNEL_GPU__ __forceinline float float2::operator[](int i) const { util_assert(i >= 0); @@ -28,19 +24,20 @@ __forceinline float &float2::operator[](int i) util_assert(i < 2); return *(&x + i); } +# endif ccl_device_inline float2 make_float2(float x, float y) { float2 a = {x, y}; return a; } +#endif /* __KERNEL_NATIVE_VECTOR_TYPES__ */ -ccl_device_inline void print_float2(const char *label, const float2 &a) +ccl_device_inline void print_float2(ccl_private const char *label, const float2 a) { +#ifdef __KERNEL_PRINTF__ printf("%s: %.8f %.8f\n", label, (double)a.x, (double)a.y); +#endif } -#endif /* !defined(__KERNEL_GPU__) || defined(__KERNEL_ONEAPI__) */ CCL_NAMESPACE_END - -#endif /* __UTIL_TYPES_FLOAT2_IMPL_H__ */ diff --git a/intern/cycles/util/types_float3.h b/intern/cycles/util/types_float3.h index c7900acaa69..87c6b1d3654 100644 --- a/intern/cycles/util/types_float3.h +++ b/intern/cycles/util/types_float3.h @@ -1,8 +1,7 @@ /* SPDX-License-Identifier: Apache-2.0 * Copyright 2011-2022 Blender Foundation */ -#ifndef __UTIL_TYPES_FLOAT3_H__ -#define __UTIL_TYPES_FLOAT3_H__ +#pragma once #ifndef __UTIL_TYPES_H__ # error "Do not include this file directly, include util/types.h instead." @@ -10,17 +9,28 @@ CCL_NAMESPACE_BEGIN -#if !defined(__KERNEL_GPU__) +#ifndef __KERNEL_NATIVE_VECTOR_TYPES__ struct ccl_try_align(16) float3 { -# ifdef __KERNEL_SSE__ +# ifdef __KERNEL_GPU__ + /* Compact structure for GPU. */ + float x, y, z; +# else + /* SIMD aligned structure for CPU. */ +# ifdef __KERNEL_SSE__ union { __m128 m128; struct { float x, y, z, w; }; }; +# else + float x, y, z, w; +# endif +# endif +# ifdef __KERNEL_SSE__ + /* Convenient constructors and operators for SIMD, otherwise default is enough. */ __forceinline float3(); __forceinline float3(const float3 &a); __forceinline explicit float3(const __m128 &a); @@ -29,18 +39,19 @@ struct ccl_try_align(16) float3 __forceinline operator __m128 &(); __forceinline float3 &operator=(const float3 &a); -# else /* __KERNEL_SSE__ */ - float x, y, z, w; -# endif /* __KERNEL_SSE__ */ +# endif +# ifndef __KERNEL_GPU__ __forceinline float operator[](int i) const; __forceinline float &operator[](int i); +# endif }; -ccl_device_inline float3 make_float3(float f); ccl_device_inline float3 make_float3(float x, float y, float z); -ccl_device_inline void print_float3(const char *label, const float3 &a); -#endif /* !defined(__KERNEL_GPU__) */ +#endif /* __KERNEL_NATIVE_VECTOR_TYPES__ */ + +ccl_device_inline float3 make_float3(float f); +ccl_device_inline void print_float3(ccl_private const char *label, const float3 a); /* Smaller float3 for storage. For math operations this must be converted to float3, so that on the * CPU SIMD instructions can be used. */ @@ -78,5 +89,3 @@ struct packed_float3 { static_assert(sizeof(packed_float3) == 12, "packed_float3 expected to be exactly 12 bytes"); CCL_NAMESPACE_END - -#endif /* __UTIL_TYPES_FLOAT3_H__ */ diff --git a/intern/cycles/util/types_float3_impl.h b/intern/cycles/util/types_float3_impl.h index 2e6e864c8ea..da76ab2ab2a 100644 --- a/intern/cycles/util/types_float3_impl.h +++ b/intern/cycles/util/types_float3_impl.h @@ -1,20 +1,15 @@ /* SPDX-License-Identifier: Apache-2.0 * Copyright 2011-2022 Blender Foundation */ -#ifndef __UTIL_TYPES_FLOAT3_IMPL_H__ -#define __UTIL_TYPES_FLOAT3_IMPL_H__ +#pragma once #ifndef __UTIL_TYPES_H__ # error "Do not include this file directly, include util/types.h instead." #endif -#ifndef __KERNEL_GPU__ -# include <cstdio> -#endif - CCL_NAMESPACE_BEGIN -#if !defined(__KERNEL_GPU__) +#ifndef __KERNEL_NATIVE_VECTOR_TYPES__ # ifdef __KERNEL_SSE__ __forceinline float3::float3() { @@ -45,6 +40,7 @@ __forceinline float3 &float3::operator=(const float3 &a) } # endif /* __KERNEL_SSE__ */ +# ifndef __KERNEL_GPU__ __forceinline float float3::operator[](int i) const { util_assert(i >= 0); @@ -58,33 +54,37 @@ __forceinline float &float3::operator[](int i) util_assert(i < 3); return *(&x + i); } +# endif -ccl_device_inline float3 make_float3(float f) +ccl_device_inline float3 make_float3(float x, float y, float z) { -# ifdef __KERNEL_SSE__ - float3 a(_mm_set1_ps(f)); +# if defined(__KERNEL_GPU__) + return {x, y, z}; +# elif defined(__KERNEL_SSE__) + return float3(_mm_set_ps(0.0f, z, y, x)); # else - float3 a = {f, f, f, f}; + return {x, y, z, 0.0f}; # endif - return a; } -ccl_device_inline float3 make_float3(float x, float y, float z) +#endif /* __KERNEL_NATIVE_VECTOR_TYPES__ */ + +ccl_device_inline float3 make_float3(float f) { -# ifdef __KERNEL_SSE__ - float3 a(_mm_set_ps(0.0f, z, y, x)); -# else - float3 a = {x, y, z, 0.0f}; -# endif - return a; +#if defined(__KERNEL_GPU__) + return make_float3(f, f, f); +#elif defined(__KERNEL_SSE__) + return float3(_mm_set1_ps(f)); +#else + return {f, f, f, f}; +#endif } -ccl_device_inline void print_float3(const char *label, const float3 &a) +ccl_device_inline void print_float3(ccl_private const char *label, const float3 a) { +#ifdef __KERNEL_PRINTF__ printf("%s: %.8f %.8f %.8f\n", label, (double)a.x, (double)a.y, (double)a.z); +#endif } -#endif /* !defined(__KERNEL_GPU__) */ CCL_NAMESPACE_END - -#endif /* __UTIL_TYPES_FLOAT3_IMPL_H__ */ diff --git a/intern/cycles/util/types_float4.h b/intern/cycles/util/types_float4.h index 27453bf39e4..a347cfce9a1 100644 --- a/intern/cycles/util/types_float4.h +++ b/intern/cycles/util/types_float4.h @@ -1,8 +1,7 @@ /* SPDX-License-Identifier: Apache-2.0 * Copyright 2011-2022 Blender Foundation */ -#ifndef __UTIL_TYPES_FLOAT4_H__ -#define __UTIL_TYPES_FLOAT4_H__ +#pragma once #ifndef __UTIL_TYPES_H__ # error "Do not include this file directly, include util/types.h instead." @@ -10,7 +9,7 @@ CCL_NAMESPACE_BEGIN -#if !defined(__KERNEL_GPU__) || defined(__KERNEL_ONEAPI__) +#ifndef __KERNEL_NATIVE_VECTOR_TYPES__ struct int4; struct ccl_try_align(16) float4 @@ -35,16 +34,17 @@ struct ccl_try_align(16) float4 float x, y, z, w; # endif /* __KERNEL_SSE__ */ +# ifndef __KERNEL_GPU__ __forceinline float operator[](int i) const; __forceinline float &operator[](int i); +# endif }; -ccl_device_inline float4 make_float4(float f); ccl_device_inline float4 make_float4(float x, float y, float z, float w); -ccl_device_inline float4 make_float4(const int4 &i); -ccl_device_inline void print_float4(const char *label, const float4 &a); -#endif /* !defined(__KERNEL_GPU__) || defined(__KERNEL_ONEAPI__) */ +#endif /* __KERNEL_NATIVE_VECTOR_TYPES__ */ -CCL_NAMESPACE_END +ccl_device_inline float4 make_float4(float f); +ccl_device_inline float4 make_float4(const int4 i); +ccl_device_inline void print_float4(ccl_private const char *label, const float4 a); -#endif /* __UTIL_TYPES_FLOAT4_H__ */ +CCL_NAMESPACE_END diff --git a/intern/cycles/util/types_float4_impl.h b/intern/cycles/util/types_float4_impl.h index d7858f744e3..420d9316926 100644 --- a/intern/cycles/util/types_float4_impl.h +++ b/intern/cycles/util/types_float4_impl.h @@ -1,20 +1,15 @@ /* SPDX-License-Identifier: Apache-2.0 * Copyright 2011-2022 Blender Foundation */ -#ifndef __UTIL_TYPES_FLOAT4_IMPL_H__ -#define __UTIL_TYPES_FLOAT4_IMPL_H__ +#pragma once #ifndef __UTIL_TYPES_H__ # error "Do not include this file directly, include util/types.h instead." #endif -#ifndef __KERNEL_GPU__ -# include <cstdio> -#endif - CCL_NAMESPACE_BEGIN -#if !defined(__KERNEL_GPU__) || defined(__KERNEL_ONEAPI__) +#ifndef __KERNEL_NATIVE_VECTOR_TYPES__ # ifdef __KERNEL_SSE__ __forceinline float4::float4() { @@ -41,6 +36,7 @@ __forceinline float4 &float4::operator=(const float4 &a) } # endif /* __KERNEL_SSE__ */ +# ifndef __KERNEL_GPU__ __forceinline float float4::operator[](int i) const { util_assert(i >= 0); @@ -54,43 +50,42 @@ __forceinline float &float4::operator[](int i) util_assert(i < 4); return *(&x + i); } +# endif -ccl_device_inline float4 make_float4(float f) +ccl_device_inline float4 make_float4(float x, float y, float z, float w) { # ifdef __KERNEL_SSE__ - float4 a(_mm_set1_ps(f)); + return float4(_mm_set_ps(w, z, y, x)); # else - float4 a = {f, f, f, f}; + return {x, y, z, w}; # endif - return a; } -ccl_device_inline float4 make_float4(float x, float y, float z, float w) +#endif /* __KERNEL_NATIVE_VECTOR_TYPES__ */ + +ccl_device_inline float4 make_float4(float f) { -# ifdef __KERNEL_SSE__ - float4 a(_mm_set_ps(w, z, y, x)); -# else - float4 a = {x, y, z, w}; -# endif - return a; +#ifdef __KERNEL_SSE__ + return float4(_mm_set1_ps(f)); +#else + return make_float4(f, f, f, f); +#endif } -ccl_device_inline float4 make_float4(const int4 &i) +ccl_device_inline float4 make_float4(const int4 i) { -# ifdef __KERNEL_SSE__ - float4 a(_mm_cvtepi32_ps(i.m128)); -# else - float4 a = {(float)i.x, (float)i.y, (float)i.z, (float)i.w}; -# endif - return a; +#ifdef __KERNEL_SSE__ + return float4(_mm_cvtepi32_ps(i.m128)); +#else + return make_float4((float)i.x, (float)i.y, (float)i.z, (float)i.w); +#endif } -ccl_device_inline void print_float4(const char *label, const float4 &a) +ccl_device_inline void print_float4(ccl_private const char *label, const float4 a) { +#ifdef __KERNEL_PRINTF__ printf("%s: %.8f %.8f %.8f %.8f\n", label, (double)a.x, (double)a.y, (double)a.z, (double)a.w); +#endif } -#endif /* !defined(__KERNEL_GPU__) || defined(__KERNEL_ONEAPI__) */ CCL_NAMESPACE_END - -#endif /* __UTIL_TYPES_FLOAT4_IMPL_H__ */ diff --git a/intern/cycles/util/types_float8.h b/intern/cycles/util/types_float8.h index bb9798932ac..29fd632f08e 100644 --- a/intern/cycles/util/types_float8.h +++ b/intern/cycles/util/types_float8.h @@ -2,8 +2,7 @@ * Original code Copyright 2017, Intel Corporation * Modifications Copyright 2018-2022 Blender Foundation. */ -#ifndef __UTIL_TYPES_FLOAT8_H__ -#define __UTIL_TYPES_FLOAT8_H__ +#pragma once #ifndef __UTIL_TYPES_H__ # error "Do not include this file directly, include util/types.h instead." @@ -12,7 +11,7 @@ CCL_NAMESPACE_BEGIN /* float8 is a reserved type in Metal that has not been implemented. For - * that reason this is named float8_t. */ + * that reason this is named float8_t and not using native vector types. */ #ifdef __KERNEL_GPU__ struct float8_t @@ -52,5 +51,3 @@ ccl_device_inline float8_t make_float8_t(float a, float b, float c, float d, float e, float f, float g, float h); CCL_NAMESPACE_END - -#endif /* __UTIL_TYPES_FLOAT8_H__ */ diff --git a/intern/cycles/util/types_float8_impl.h b/intern/cycles/util/types_float8_impl.h index 2ab464a791b..e8576cdaf70 100644 --- a/intern/cycles/util/types_float8_impl.h +++ b/intern/cycles/util/types_float8_impl.h @@ -2,17 +2,12 @@ * Original code Copyright 2017, Intel Corporation * Modifications Copyright 2018-2022 Blender Foundation. */ -#ifndef __UTIL_TYPES_FLOAT8_IMPL_H__ -#define __UTIL_TYPES_FLOAT8_IMPL_H__ +#pragma once #ifndef __UTIL_TYPES_H__ # error "Do not include this file directly, include util/types.h instead." #endif -#ifndef __KERNEL_GPU__ -# include <cstdio> -#endif - CCL_NAMESPACE_BEGIN #ifdef __KERNEL_AVX2__ @@ -83,5 +78,3 @@ make_float8_t(float a, float b, float c, float d, float e, float f, float g, flo } CCL_NAMESPACE_END - -#endif /* __UTIL_TYPES_FLOAT8_IMPL_H__ */ diff --git a/intern/cycles/util/types_int2.h b/intern/cycles/util/types_int2.h index bf69cddc653..604713dffcd 100644 --- a/intern/cycles/util/types_int2.h +++ b/intern/cycles/util/types_int2.h @@ -1,8 +1,7 @@ /* SPDX-License-Identifier: Apache-2.0 * Copyright 2011-2022 Blender Foundation */ -#ifndef __UTIL_TYPES_INT2_H__ -#define __UTIL_TYPES_INT2_H__ +#pragma once #ifndef __UTIL_TYPES_H__ # error "Do not include this file directly, include util/types.h instead." @@ -10,17 +9,17 @@ CCL_NAMESPACE_BEGIN -#if !defined(__KERNEL_GPU__) || defined(__KERNEL_ONEAPI__) +#ifndef __KERNEL_NATIVE_VECTOR_TYPES__ struct int2 { int x, y; +# ifndef __KERNEL_GPU__ __forceinline int operator[](int i) const; __forceinline int &operator[](int i); +# endif }; ccl_device_inline int2 make_int2(int x, int y); -#endif /* !defined(__KERNEL_GPU__) || defined(__KERNEL_ONEAPI__) */ +#endif /* __KERNEL_NATIVE_VECTOR_TYPES__ */ CCL_NAMESPACE_END - -#endif /* __UTIL_TYPES_INT2_H__ */ diff --git a/intern/cycles/util/types_int2_impl.h b/intern/cycles/util/types_int2_impl.h index 7bdc77369ee..f48c6f46729 100644 --- a/intern/cycles/util/types_int2_impl.h +++ b/intern/cycles/util/types_int2_impl.h @@ -1,8 +1,7 @@ /* SPDX-License-Identifier: Apache-2.0 * Copyright 2011-2022 Blender Foundation */ -#ifndef __UTIL_TYPES_INT2_IMPL_H__ -#define __UTIL_TYPES_INT2_IMPL_H__ +#pragma once #ifndef __UTIL_TYPES_H__ # error "Do not include this file directly, include util/types.h instead." @@ -10,7 +9,8 @@ CCL_NAMESPACE_BEGIN -#if !defined(__KERNEL_GPU__) || defined(__KERNEL_ONEAPI__) +#ifndef __KERNEL_NATIVE_VECTOR_TYPES__ +# ifndef __KERNEL_GPU__ int int2::operator[](int i) const { util_assert(i >= 0); @@ -24,14 +24,13 @@ int &int2::operator[](int i) util_assert(i < 2); return *(&x + i); } +# endif ccl_device_inline int2 make_int2(int x, int y) { int2 a = {x, y}; return a; } -#endif /* !defined(__KERNEL_GPU__) || defined(__KERNEL_ONEAPI__) */ +#endif /* __KERNEL_NATIVE_VECTOR_TYPES__ */ CCL_NAMESPACE_END - -#endif /* __UTIL_TYPES_INT2_IMPL_H__ */ diff --git a/intern/cycles/util/types_int3.h b/intern/cycles/util/types_int3.h index f88ff22ac35..e059ddd3660 100644 --- a/intern/cycles/util/types_int3.h +++ b/intern/cycles/util/types_int3.h @@ -1,8 +1,7 @@ /* SPDX-License-Identifier: Apache-2.0 * Copyright 2011-2022 Blender Foundation */ -#ifndef __UTIL_TYPES_INT3_H__ -#define __UTIL_TYPES_INT3_H__ +#pragma once #ifndef __UTIL_TYPES_H__ # error "Do not include this file directly, include util/types.h instead." @@ -10,10 +9,15 @@ CCL_NAMESPACE_BEGIN -#if !defined(__KERNEL_GPU__) || defined(__KERNEL_ONEAPI__) +#ifndef __KERNEL_NATIVE_VECTOR_TYPES__ struct ccl_try_align(16) int3 { -# ifdef __KERNEL_SSE__ +# ifdef __KERNEL_GPU__ + /* Compact structure on the GPU. */ + int x, y, z; +# else + /* SIMD aligned structure for CPU. */ +# ifdef __KERNEL_SSE__ union { __m128i m128; struct { @@ -29,19 +33,21 @@ struct ccl_try_align(16) int3 __forceinline operator __m128i &(); __forceinline int3 &operator=(const int3 &a); -# else /* __KERNEL_SSE__ */ +# else /* __KERNEL_SSE__ */ int x, y, z, w; -# endif /* __KERNEL_SSE__ */ +# endif /* __KERNEL_SSE__ */ +# endif +# ifndef __KERNEL_GPU__ __forceinline int operator[](int i) const; __forceinline int &operator[](int i); +# endif }; -ccl_device_inline int3 make_int3(int i); ccl_device_inline int3 make_int3(int x, int y, int z); -ccl_device_inline void print_int3(const char *label, const int3 &a); -#endif /* !defined(__KERNEL_GPU__) || defined(__KERNEL_ONEAPI__) */ +#endif /* __KERNEL_NATIVE_VECTOR_TYPES__ */ -CCL_NAMESPACE_END +ccl_device_inline int3 make_int3(int i); +ccl_device_inline void print_int3(ccl_private const char *label, const int3 a); -#endif /* __UTIL_TYPES_INT3_H__ */ +CCL_NAMESPACE_END diff --git a/intern/cycles/util/types_int3_impl.h b/intern/cycles/util/types_int3_impl.h index 1c49e97ad32..830dfa3c658 100644 --- a/intern/cycles/util/types_int3_impl.h +++ b/intern/cycles/util/types_int3_impl.h @@ -1,20 +1,15 @@ /* SPDX-License-Identifier: Apache-2.0 * Copyright 2011-2022 Blender Foundation */ -#ifndef __UTIL_TYPES_INT3_IMPL_H__ -#define __UTIL_TYPES_INT3_IMPL_H__ +#pragma once #ifndef __UTIL_TYPES_H__ # error "Do not include this file directly, include util/types.h instead." #endif -#ifndef __KERNEL_GPU__ -# include <cstdio> -#endif - CCL_NAMESPACE_BEGIN -#if !defined(__KERNEL_GPU__) || defined(__KERNEL_ONEAPI__) +#ifndef __KERNEL_NATIVE_VECTOR_TYPES__ # ifdef __KERNEL_SSE__ __forceinline int3::int3() { @@ -45,6 +40,7 @@ __forceinline int3 &int3::operator=(const int3 &a) } # endif /* __KERNEL_SSE__ */ +# ifndef __KERNEL_GPU__ __forceinline int int3::operator[](int i) const { util_assert(i >= 0); @@ -58,34 +54,37 @@ __forceinline int &int3::operator[](int i) util_assert(i < 3); return *(&x + i); } - -ccl_device_inline int3 make_int3(int i) -{ -# ifdef __KERNEL_SSE__ - int3 a(_mm_set1_epi32(i)); -# else - int3 a = {i, i, i, i}; # endif - return a; -} ccl_device_inline int3 make_int3(int x, int y, int z) { -# ifdef __KERNEL_SSE__ - int3 a(_mm_set_epi32(0, z, y, x)); +# if defined(__KERNEL_GPU__) + return {x, y, z}; +# elif defined(__KERNEL_SSE__) + return int3(_mm_set_epi32(0, z, y, x)); # else - int3 a = {x, y, z, 0}; + return {x, y, z, 0}; # endif +} - return a; +#endif /* __KERNEL_NATIVE_VECTOR_TYPES__ */ + +ccl_device_inline int3 make_int3(int i) +{ +#if defined(__KERNEL_GPU__) + return make_int3(i, i, i); +#elif defined(__KERNEL_SSE__) + return int3(_mm_set1_epi32(i)); +#else + return {i, i, i, i}; +#endif } -ccl_device_inline void print_int3(const char *label, const int3 &a) +ccl_device_inline void print_int3(ccl_private const char *label, const int3 a) { +#ifdef __KERNEL_PRINTF__ printf("%s: %d %d %d\n", label, a.x, a.y, a.z); +#endif } -#endif /* !defined(__KERNEL_GPU__) || defined(__KERNEL_ONEAPI__) */ CCL_NAMESPACE_END - -#endif /* __UTIL_TYPES_INT3_IMPL_H__ */ diff --git a/intern/cycles/util/types_int4.h b/intern/cycles/util/types_int4.h index 9d557c01344..1a13c03e60e 100644 --- a/intern/cycles/util/types_int4.h +++ b/intern/cycles/util/types_int4.h @@ -1,8 +1,7 @@ /* SPDX-License-Identifier: Apache-2.0 * Copyright 2011-2022 Blender Foundation */ -#ifndef __UTIL_TYPES_INT4_H__ -#define __UTIL_TYPES_INT4_H__ +#pragma once #ifndef __UTIL_TYPES_H__ # error "Do not include this file directly, include util/types.h instead." @@ -10,7 +9,7 @@ CCL_NAMESPACE_BEGIN -#if !defined(__KERNEL_GPU__) || defined(__KERNEL_ONEAPI__) +#ifndef __KERNEL_NATIVE_VECTOR_TYPES__ struct float3; struct float4; @@ -37,17 +36,18 @@ struct ccl_try_align(16) int4 int x, y, z, w; # endif /* __KERNEL_SSE__ */ +# ifndef __KERNEL_GPU__ __forceinline int operator[](int i) const; __forceinline int &operator[](int i); +# endif }; -ccl_device_inline int4 make_int4(int i); ccl_device_inline int4 make_int4(int x, int y, int z, int w); -ccl_device_inline int4 make_int4(const float3 &f); -ccl_device_inline int4 make_int4(const float4 &f); -ccl_device_inline void print_int4(const char *label, const int4 &a); -#endif /* !defined(__KERNEL_GPU__) || defined(__KERNEL_ONEAPI__) */ +#endif /* __KERNEL_NATIVE_VECTOR_TYPES__ */ -CCL_NAMESPACE_END +ccl_device_inline int4 make_int4(int i); +ccl_device_inline int4 make_int4(const float3 f); +ccl_device_inline int4 make_int4(const float4 f); +ccl_device_inline void print_int4(ccl_private const char *label, const int4 a); -#endif /* __UTIL_TYPES_INT4_H__ */ +CCL_NAMESPACE_END diff --git a/intern/cycles/util/types_int4_impl.h b/intern/cycles/util/types_int4_impl.h index 11e1ede6705..067794e67b4 100644 --- a/intern/cycles/util/types_int4_impl.h +++ b/intern/cycles/util/types_int4_impl.h @@ -1,20 +1,15 @@ /* SPDX-License-Identifier: Apache-2.0 * Copyright 2011-2022 Blender Foundation */ -#ifndef __UTIL_TYPES_INT4_IMPL_H__ -#define __UTIL_TYPES_INT4_IMPL_H__ +#pragma once #ifndef __UTIL_TYPES_H__ # error "Do not include this file directly, include util/types.h instead." #endif -#ifndef __KERNEL_GPU__ -# include <cstdio> -#endif - CCL_NAMESPACE_BEGIN -#if !defined(__KERNEL_GPU__) || defined(__KERNEL_ONEAPI__) +#ifndef __KERNEL_NATIVE_VECTOR_TYPES__ # ifdef __KERNEL_SSE__ __forceinline int4::int4() { @@ -45,6 +40,7 @@ __forceinline int4 &int4::operator=(const int4 &a) } # endif /* __KERNEL_SSE__ */ +# ifndef __KERNEL_GPU__ __forceinline int int4::operator[](int i) const { util_assert(i >= 0); @@ -58,55 +54,53 @@ __forceinline int &int4::operator[](int i) util_assert(i < 4); return *(&x + i); } +# endif -ccl_device_inline int4 make_int4(int i) +ccl_device_inline int4 make_int4(int x, int y, int z, int w) { # ifdef __KERNEL_SSE__ - int4 a(_mm_set1_epi32(i)); + return int4(_mm_set_epi32(w, z, y, x)); # else - int4 a = {i, i, i, i}; + return {x, y, z, w}; # endif - return a; } -ccl_device_inline int4 make_int4(int x, int y, int z, int w) +#endif /* __KERNEL_NATIVE_VECTOR_TYPES__ */ + +ccl_device_inline int4 make_int4(int i) { -# ifdef __KERNEL_SSE__ - int4 a(_mm_set_epi32(w, z, y, x)); -# else - int4 a = {x, y, z, w}; -# endif - return a; +#ifdef __KERNEL_SSE__ + return int4(_mm_set1_epi32(i)); +#else + return make_int4(i, i, i, i); +#endif } -ccl_device_inline int4 make_int4(const float3 &f) +ccl_device_inline int4 make_int4(const float3 f) { -# ifdef __KERNEL_SSE__ - int4 a(_mm_cvtps_epi32(f.m128)); -# elif defined(__KERNEL_ONEAPI__) - int4 a = {(int)f.x, (int)f.y, (int)f.z, 0}; -# else - int4 a = {(int)f.x, (int)f.y, (int)f.z, (int)f.w}; -# endif - return a; +#if defined(__KERNEL_GPU__) + return make_int4((int)f.x, (int)f.y, (int)f.z, 0); +#elif defined(__KERNEL_SSE__) + return int4(_mm_cvtps_epi32(f.m128)); +#else + return make_int4((int)f.x, (int)f.y, (int)f.z, (int)f.w); +#endif } -ccl_device_inline int4 make_int4(const float4 &f) +ccl_device_inline int4 make_int4(const float4 f) { -# ifdef __KERNEL_SSE__ - int4 a(_mm_cvtps_epi32(f.m128)); -# else - int4 a = {(int)f.x, (int)f.y, (int)f.z, (int)f.w}; -# endif - return a; +#ifdef __KERNEL_SSE__ + return int4(_mm_cvtps_epi32(f.m128)); +#else + return make_int4((int)f.x, (int)f.y, (int)f.z, (int)f.w); +#endif } -ccl_device_inline void print_int4(const char *label, const int4 &a) +ccl_device_inline void print_int4(ccl_private const char *label, const int4 a) { +#ifdef __KERNEL_PRINTF__ printf("%s: %d %d %d %d\n", label, a.x, a.y, a.z, a.w); +#endif } -#endif /* !defined(__KERNEL_GPU__) || defined(__KERNEL_ONEAPI__) */ CCL_NAMESPACE_END - -#endif /* __UTIL_TYPES_INT4_IMPL_H__ */ diff --git a/intern/cycles/util/types_spectrum.h b/intern/cycles/util/types_spectrum.h new file mode 100644 index 00000000000..c59230b83ae --- /dev/null +++ b/intern/cycles/util/types_spectrum.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: Apache-2.0 + * Copyright 2022 Blender Foundation */ + +#ifndef __UTIL_TYPES_SPECTRUM_H__ +#define __UTIL_TYPES_SPECTRUM_H__ + +#ifndef __UTIL_TYPES_H__ +# error "Do not include this file directly, include util/types.h instead." +#endif + +CCL_NAMESPACE_BEGIN + +#define SPECTRUM_CHANNELS 3 +#define SPECTRUM_DATA_TYPE float3 +#define PACKED_SPECTRUM_DATA_TYPE packed_float3 + +using Spectrum = SPECTRUM_DATA_TYPE; +using PackedSpectrum = PACKED_SPECTRUM_DATA_TYPE; + +#define make_spectrum(f) CONCAT(make_, SPECTRUM_DATA_TYPE(f)) +#define load_spectrum(f) CONCAT(load_, SPECTRUM_DATA_TYPE(f)) +#define store_spectrum(s, f) CONCAT(store_, SPECTRUM_DATA_TYPE((s), (f))) + +#define zero_spectrum CONCAT(zero_, SPECTRUM_DATA_TYPE) +#define one_spectrum CONCAT(one_, SPECTRUM_DATA_TYPE) + +#define FOREACH_SPECTRUM_CHANNEL(counter) \ + for (int counter = 0; counter < SPECTRUM_CHANNELS; counter++) + +#define GET_SPECTRUM_CHANNEL(v, i) (((ccl_private float *)(&(v)))[i]) + +CCL_NAMESPACE_END + +#endif /* __UTIL_TYPES_SPECTRUM_H__ */ diff --git a/intern/cycles/util/types_uchar2.h b/intern/cycles/util/types_uchar2.h index 0b3c9bd0331..ce617248e6e 100644 --- a/intern/cycles/util/types_uchar2.h +++ b/intern/cycles/util/types_uchar2.h @@ -1,8 +1,7 @@ /* SPDX-License-Identifier: Apache-2.0 * Copyright 2011-2022 Blender Foundation */ -#ifndef __UTIL_TYPES_UCHAR2_H__ -#define __UTIL_TYPES_UCHAR2_H__ +#pragma once #ifndef __UTIL_TYPES_H__ # error "Do not include this file directly, include util/types.h instead." @@ -10,17 +9,17 @@ CCL_NAMESPACE_BEGIN -#if !defined(__KERNEL_GPU__) || defined(__KERNEL_ONEAPI__) +#ifndef __KERNEL_NATIVE_VECTOR_TYPES__ struct uchar2 { uchar x, y; +# ifndef __KERNEL_GPU__ __forceinline uchar operator[](int i) const; __forceinline uchar &operator[](int i); +# endif }; ccl_device_inline uchar2 make_uchar2(uchar x, uchar y); -#endif /* !defined(__KERNEL_GPU__) || defined(__KERNEL_ONEAPI__) */ +#endif /* __KERNEL_NATIVE_VECTOR_TYPES__ */ CCL_NAMESPACE_END - -#endif /* __UTIL_TYPES_UCHAR2_H__ */ diff --git a/intern/cycles/util/types_uchar2_impl.h b/intern/cycles/util/types_uchar2_impl.h index a7254d5eaf2..9f3f3a4efb9 100644 --- a/intern/cycles/util/types_uchar2_impl.h +++ b/intern/cycles/util/types_uchar2_impl.h @@ -10,7 +10,8 @@ CCL_NAMESPACE_BEGIN -#if !defined(__KERNEL_GPU__) || defined(__KERNEL_ONEAPI__) +#ifndef __KERNEL_NATIVE_VECTOR_TYPES__ +# ifndef __KERNEL_GPU__ uchar uchar2::operator[](int i) const { util_assert(i >= 0); @@ -24,13 +25,14 @@ uchar &uchar2::operator[](int i) util_assert(i < 2); return *(&x + i); } +# endif ccl_device_inline uchar2 make_uchar2(uchar x, uchar y) { uchar2 a = {x, y}; return a; } -#endif /* !defined(__KERNEL_GPU__) || defined(__KERNEL_ONEAPI__) */ +#endif /* __KERNEL_NATIVE_VECTOR_TYPES__ */ CCL_NAMESPACE_END diff --git a/intern/cycles/util/types_uchar3.h b/intern/cycles/util/types_uchar3.h index fc213502ada..aed04c4775e 100644 --- a/intern/cycles/util/types_uchar3.h +++ b/intern/cycles/util/types_uchar3.h @@ -10,16 +10,18 @@ CCL_NAMESPACE_BEGIN -#if !defined(__KERNEL_GPU__) || defined(__KERNEL_ONEAPI__) +#ifndef __KERNEL_NATIVE_VECTOR_TYPES__ struct uchar3 { uchar x, y, z; +# ifndef __KERNEL_GPU__ __forceinline uchar operator[](int i) const; __forceinline uchar &operator[](int i); +# endif }; ccl_device_inline uchar3 make_uchar3(uchar x, uchar y, uchar z); -#endif /* !defined(__KERNEL_GPU__) || defined(__KERNEL_ONEAPI__) */ +#endif /* __KERNEL_NATIVE_VECTOR_TYPES__ */ CCL_NAMESPACE_END diff --git a/intern/cycles/util/types_uchar3_impl.h b/intern/cycles/util/types_uchar3_impl.h index 0c24ffb488a..83eb3c99b3c 100644 --- a/intern/cycles/util/types_uchar3_impl.h +++ b/intern/cycles/util/types_uchar3_impl.h @@ -10,7 +10,8 @@ CCL_NAMESPACE_BEGIN -#if !defined(__KERNEL_GPU__) || defined(__KERNEL_ONEAPI__) +#ifndef __KERNEL_NATIVE_VECTOR_TYPES__ +# ifndef __KERNEL_GPU__ uchar uchar3::operator[](int i) const { util_assert(i >= 0); @@ -24,13 +25,14 @@ uchar &uchar3::operator[](int i) util_assert(i < 3); return *(&x + i); } +# endif ccl_device_inline uchar3 make_uchar3(uchar x, uchar y, uchar z) { uchar3 a = {x, y, z}; return a; } -#endif /* !defined(__KERNEL_GPU__) || defined(__KERNEL_ONEAPI__) */ +#endif /* __KERNEL_NATIVE_VECTOR_TYPES__ */ CCL_NAMESPACE_END diff --git a/intern/cycles/util/types_uchar4.h b/intern/cycles/util/types_uchar4.h index a2a2c945aaa..fb13a98875e 100644 --- a/intern/cycles/util/types_uchar4.h +++ b/intern/cycles/util/types_uchar4.h @@ -1,8 +1,7 @@ /* SPDX-License-Identifier: Apache-2.0 * Copyright 2011-2022 Blender Foundation */ -#ifndef __UTIL_TYPES_UCHAR4_H__ -#define __UTIL_TYPES_UCHAR4_H__ +#pragma once #ifndef __UTIL_TYPES_H__ # error "Do not include this file directly, include util/types.h instead." @@ -10,17 +9,17 @@ CCL_NAMESPACE_BEGIN -#if !defined(__KERNEL_GPU__) || defined(__KERNEL_ONEAPI__) +#ifndef __KERNEL_NATIVE_VECTOR_TYPES__ struct uchar4 { uchar x, y, z, w; +# ifndef __KERNEL_GPU__ __forceinline uchar operator[](int i) const; __forceinline uchar &operator[](int i); +# endif }; ccl_device_inline uchar4 make_uchar4(uchar x, uchar y, uchar z, uchar w); -#endif /* !defined(__KERNEL_GPU__) || defined(__KERNEL_ONEAPI__) */ +#endif /* __KERNEL_NATIVE_VECTOR_TYPES__ */ CCL_NAMESPACE_END - -#endif /* __UTIL_TYPES_UCHAR4_H__ */ diff --git a/intern/cycles/util/types_uchar4_impl.h b/intern/cycles/util/types_uchar4_impl.h index 8ec6213a37d..244bb98f883 100644 --- a/intern/cycles/util/types_uchar4_impl.h +++ b/intern/cycles/util/types_uchar4_impl.h @@ -10,7 +10,8 @@ CCL_NAMESPACE_BEGIN -#if !defined(__KERNEL_GPU__) || defined(__KERNEL_ONEAPI__) +#ifndef __KERNEL_NATIVE_VECTOR_TYPES__ +# ifndef __KERNEL_GPU__ uchar uchar4::operator[](int i) const { util_assert(i >= 0); @@ -24,13 +25,14 @@ uchar &uchar4::operator[](int i) util_assert(i < 4); return *(&x + i); } +# endif ccl_device_inline uchar4 make_uchar4(uchar x, uchar y, uchar z, uchar w) { uchar4 a = {x, y, z, w}; return a; } -#endif /* !defined(__KERNEL_GPU__) || defined(__KERNEL_ONEAPI__) */ +#endif /* __KERNEL_NATIVE_VECTOR_TYPES__ */ CCL_NAMESPACE_END diff --git a/intern/cycles/util/types_uint2.h b/intern/cycles/util/types_uint2.h index faa0955f903..4d76b628088 100644 --- a/intern/cycles/util/types_uint2.h +++ b/intern/cycles/util/types_uint2.h @@ -1,8 +1,7 @@ /* SPDX-License-Identifier: Apache-2.0 * Copyright 2011-2022 Blender Foundation */ -#ifndef __UTIL_TYPES_UINT2_H__ -#define __UTIL_TYPES_UINT2_H__ +#pragma once #ifndef __UTIL_TYPES_H__ # error "Do not include this file directly, include util/types.h instead." @@ -10,17 +9,17 @@ CCL_NAMESPACE_BEGIN -#if !defined(__KERNEL_GPU__) || defined(__KERNEL_ONEAPI__) +#ifndef __KERNEL_NATIVE_VECTOR_TYPES__ struct uint2 { uint x, y; +# ifndef __KERNEL_GPU__ __forceinline uint operator[](uint i) const; __forceinline uint &operator[](uint i); +# endif }; ccl_device_inline uint2 make_uint2(uint x, uint y); -#endif /* !defined(__KERNEL_GPU__) || defined(__KERNEL_ONEAPI__) */ +#endif /* __KERNEL_NATIVE_VECTOR_TYPES__ */ CCL_NAMESPACE_END - -#endif /* __UTIL_TYPES_UINT2_H__ */ diff --git a/intern/cycles/util/types_uint2_impl.h b/intern/cycles/util/types_uint2_impl.h index cac0ba6b531..b508aaf2543 100644 --- a/intern/cycles/util/types_uint2_impl.h +++ b/intern/cycles/util/types_uint2_impl.h @@ -1,8 +1,7 @@ /* SPDX-License-Identifier: Apache-2.0 * Copyright 2011-2022 Blender Foundation */ -#ifndef __UTIL_TYPES_UINT2_IMPL_H__ -#define __UTIL_TYPES_UINT2_IMPL_H__ +#pragma once #ifndef __UTIL_TYPES_H__ # error "Do not include this file directly, include util/types.h instead." @@ -10,7 +9,8 @@ CCL_NAMESPACE_BEGIN -#if !defined(__KERNEL_GPU__) || defined(__KERNEL_ONEAPI__) +#ifndef __KERNEL_NATIVE_VECTOR_TYPES__ +# ifndef __KERNEL_GPU__ __forceinline uint uint2::operator[](uint i) const { util_assert(i < 2); @@ -22,14 +22,13 @@ __forceinline uint &uint2::operator[](uint i) util_assert(i < 2); return *(&x + i); } +# endif ccl_device_inline uint2 make_uint2(uint x, uint y) { uint2 a = {x, y}; return a; } -#endif /* !defined(__KERNEL_GPU__) || defined(__KERNEL_ONEAPI__) */ +#endif /* __KERNEL_NATIVE_VECTOR_TYPES__ */ CCL_NAMESPACE_END - -#endif /* __UTIL_TYPES_UINT2_IMPL_H__ */ diff --git a/intern/cycles/util/types_uint3.h b/intern/cycles/util/types_uint3.h index 3ff87bfc791..b1571716fc7 100644 --- a/intern/cycles/util/types_uint3.h +++ b/intern/cycles/util/types_uint3.h @@ -1,8 +1,7 @@ /* SPDX-License-Identifier: Apache-2.0 * Copyright 2011-2022 Blender Foundation */ -#ifndef __UTIL_TYPES_UINT3_H__ -#define __UTIL_TYPES_UINT3_H__ +#pragma once #ifndef __UTIL_TYPES_H__ # error "Do not include this file directly, include util/types.h instead." @@ -10,17 +9,17 @@ CCL_NAMESPACE_BEGIN -#if !defined(__KERNEL_GPU__) || defined(__KERNEL_ONEAPI__) +#ifndef __KERNEL_NATIVE_VECTOR_TYPES__ struct uint3 { uint x, y, z; +# ifndef __KERNEL_GPU__ __forceinline uint operator[](uint i) const; __forceinline uint &operator[](uint i); +# endif }; ccl_device_inline uint3 make_uint3(uint x, uint y, uint z); -#endif /* !defined(__KERNEL_GPU__) || defined(__KERNEL_ONEAPI__) */ +#endif /* __KERNEL_NATIVE_VECTOR_TYPES__ */ CCL_NAMESPACE_END - -#endif /* __UTIL_TYPES_UINT3_H__ */ diff --git a/intern/cycles/util/types_uint3_impl.h b/intern/cycles/util/types_uint3_impl.h index 221883a1adb..d36c9f52de9 100644 --- a/intern/cycles/util/types_uint3_impl.h +++ b/intern/cycles/util/types_uint3_impl.h @@ -1,8 +1,7 @@ /* SPDX-License-Identifier: Apache-2.0 * Copyright 2011-2022 Blender Foundation */ -#ifndef __UTIL_TYPES_UINT3_IMPL_H__ -#define __UTIL_TYPES_UINT3_IMPL_H__ +#pragma once #ifndef __UTIL_TYPES_H__ # error "Do not include this file directly, include util/types.h instead." @@ -10,7 +9,8 @@ CCL_NAMESPACE_BEGIN -#if !defined(__KERNEL_GPU__) || defined(__KERNEL_ONEAPI__) +#ifndef __KERNEL_NATIVE_VECTOR_TYPES__ +# ifndef __KERNEL_GPU__ __forceinline uint uint3::operator[](uint i) const { util_assert(i < 3); @@ -22,14 +22,13 @@ __forceinline uint &uint3::operator[](uint i) util_assert(i < 3); return *(&x + i); } +# endif ccl_device_inline uint3 make_uint3(uint x, uint y, uint z) { uint3 a = {x, y, z}; return a; } -#endif /* !defined(__KERNEL_GPU__) || defined(__KERNEL_ONEAPI__) */ +#endif /* __KERNEL_NATIVE_VECTOR_TYPES__ */ CCL_NAMESPACE_END - -#endif /* __UTIL_TYPES_UINT3_IMPL_H__ */ diff --git a/intern/cycles/util/types_uint4.h b/intern/cycles/util/types_uint4.h index 504095b2383..4982b30f577 100644 --- a/intern/cycles/util/types_uint4.h +++ b/intern/cycles/util/types_uint4.h @@ -1,8 +1,7 @@ /* SPDX-License-Identifier: Apache-2.0 * Copyright 2011-2022 Blender Foundation */ -#ifndef __UTIL_TYPES_UINT4_H__ -#define __UTIL_TYPES_UINT4_H__ +#pragma once #ifndef __UTIL_TYPES_H__ # error "Do not include this file directly, include util/types.h instead." @@ -10,17 +9,17 @@ CCL_NAMESPACE_BEGIN -#if !defined(__KERNEL_GPU__) || defined(__KERNEL_ONEAPI__) +#ifndef __KERNEL_NATIVE_VECTOR_TYPES__ struct uint4 { uint x, y, z, w; +# ifndef __KERNEL_GPU__ __forceinline uint operator[](uint i) const; __forceinline uint &operator[](uint i); +# endif }; ccl_device_inline uint4 make_uint4(uint x, uint y, uint z, uint w); -#endif /* !defined(__KERNEL_GPU__) || defined(__KERNEL_ONEAPI__) */ +#endif /* __KERNEL_NATIVE_VECTOR_TYPES__ */ CCL_NAMESPACE_END - -#endif /* __UTIL_TYPES_UINT4_H__ */ diff --git a/intern/cycles/util/types_uint4_impl.h b/intern/cycles/util/types_uint4_impl.h index d78db944a1f..1cfdb9e0992 100644 --- a/intern/cycles/util/types_uint4_impl.h +++ b/intern/cycles/util/types_uint4_impl.h @@ -1,8 +1,7 @@ /* SPDX-License-Identifier: Apache-2.0 * Copyright 2011-2022 Blender Foundation */ -#ifndef __UTIL_TYPES_UINT4_IMPL_H__ -#define __UTIL_TYPES_UINT4_IMPL_H__ +#pragma once #ifndef __UTIL_TYPES_H__ # error "Do not include this file directly, include util/types.h instead." @@ -10,7 +9,8 @@ CCL_NAMESPACE_BEGIN -#if !defined(__KERNEL_GPU__) || defined(__KERNEL_ONEAPI__) +#ifndef __KERNEL_NATIVE_VECTOR_TYPES__ +# ifndef __KERNEL_GPU__ __forceinline uint uint4::operator[](uint i) const { util_assert(i < 3); @@ -22,14 +22,13 @@ __forceinline uint &uint4::operator[](uint i) util_assert(i < 3); return *(&x + i); } +# endif ccl_device_inline uint4 make_uint4(uint x, uint y, uint z, uint w) { uint4 a = {x, y, z, w}; return a; } -#endif /* !defined(__KERNEL_GPU__) || defined(__KERNEL_ONEAPI__) */ +#endif /* __KERNEL_NATIVE_VECTOR_TYPES__ */ CCL_NAMESPACE_END - -#endif /* __UTIL_TYPES_UINT4_IMPL_H__ */ diff --git a/intern/cycles/util/types_ushort4.h b/intern/cycles/util/types_ushort4.h index 9a6e12095ba..aef36f63285 100644 --- a/intern/cycles/util/types_ushort4.h +++ b/intern/cycles/util/types_ushort4.h @@ -10,7 +10,7 @@ CCL_NAMESPACE_BEGIN -#if !defined(__KERNEL_GPU__) || defined(__KERNEL_ONEAPI__) +#ifndef __KERNEL_NATIVE_VECTOR_TYPES__ struct ushort4 { uint16_t x, y, z, w; diff --git a/intern/cycles/util/types_vector3.h b/intern/cycles/util/types_vector3.h deleted file mode 100644 index 2e0d68e1bd0..00000000000 --- a/intern/cycles/util/types_vector3.h +++ /dev/null @@ -1,26 +0,0 @@ -/* SPDX-License-Identifier: Apache-2.0 - * Copyright 2011-2022 Blender Foundation */ - -#ifndef __UTIL_TYPES_VECTOR3_H__ -#define __UTIL_TYPES_VECTOR3_H__ - -#ifndef __UTIL_TYPES_H__ -# error "Do not include this file directly, include util/types.h instead." -#endif - -CCL_NAMESPACE_BEGIN - -#ifndef __KERNEL_GPU__ -template<typename T> class vector3 { - public: - T x, y, z; - - __forceinline vector3(); - __forceinline vector3(const T &a); - __forceinline vector3(const T &x, const T &y, const T &z); -}; -#endif /* __KERNEL_GPU__ */ - -CCL_NAMESPACE_END - -#endif /* __UTIL_TYPES_VECTOR3_H__ */ diff --git a/intern/cycles/util/types_vector3_impl.h b/intern/cycles/util/types_vector3_impl.h deleted file mode 100644 index a765780e2d3..00000000000 --- a/intern/cycles/util/types_vector3_impl.h +++ /dev/null @@ -1,30 +0,0 @@ -/* SPDX-License-Identifier: Apache-2.0 - * Copyright 2011-2022 Blender Foundation */ - -#ifndef __UTIL_TYPES_VECTOR3_IMPL_H__ -#define __UTIL_TYPES_VECTOR3_IMPL_H__ - -#ifndef __UTIL_TYPES_H__ -# error "Do not include this file directly, include util/types.h instead." -#endif - -CCL_NAMESPACE_BEGIN - -#ifndef __KERNEL_GPU__ -template<typename T> ccl_always_inline vector3<T>::vector3() -{ -} - -template<typename T> ccl_always_inline vector3<T>::vector3(const T &a) : x(a), y(a), z(a) -{ -} - -template<typename T> -ccl_always_inline vector3<T>::vector3(const T &x, const T &y, const T &z) : x(x), y(y), z(z) -{ -} -#endif /* __KERNEL_GPU__ */ - -CCL_NAMESPACE_END - -#endif /* __UTIL_TYPES_VECTOR3_IMPL_H__ */ diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt index c681dc368bb..0ac3a234946 100644 --- a/intern/ghost/CMakeLists.txt +++ b/intern/ghost/CMakeLists.txt @@ -5,6 +5,7 @@ set(INC . ../clog ../glew-mx + ../../source/blender/blenlib ../../source/blender/imbuf ../../source/blender/makesdna ) @@ -25,6 +26,7 @@ set(SRC intern/GHOST_ISystemPaths.cpp intern/GHOST_ModifierKeys.cpp intern/GHOST_Path-api.cpp + intern/GHOST_PathUtils.cpp intern/GHOST_Rect.cpp intern/GHOST_System.cpp intern/GHOST_TimerManager.cpp @@ -59,6 +61,7 @@ set(SRC intern/GHOST_EventTrackpad.h intern/GHOST_EventWheel.h intern/GHOST_ModifierKeys.h + intern/GHOST_PathUtils.h intern/GHOST_System.h intern/GHOST_SystemPaths.h intern/GHOST_TimerManager.h diff --git a/intern/ghost/intern/GHOST_Context.cpp b/intern/ghost/intern/GHOST_Context.cpp index f9aa80dc13d..f4b3d08ffc5 100644 --- a/intern/ghost/intern/GHOST_Context.cpp +++ b/intern/ghost/intern/GHOST_Context.cpp @@ -35,7 +35,7 @@ bool win32_silent_chk(bool result) bool win32_chk(bool result, const char *file, int line, const char *text) { if (!result) { - LPTSTR formattedMsg = NULL; + LPTSTR formattedMsg = nullptr; DWORD error = GetLastError(); @@ -87,12 +87,12 @@ bool win32_chk(bool result, const char *file, int line, const char *text) default: { count = FormatMessage((FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS), - NULL, + nullptr, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)(&formattedMsg), 0, - NULL); + nullptr); msg = count > 0 ? formattedMsg : "<no system message>\n"; break; @@ -113,8 +113,9 @@ bool win32_chk(bool result, const char *file, int line, const char *text) SetLastError(NO_ERROR); - if (count != 0) + if (count != 0) { LocalFree(formattedMsg); + } } return result; diff --git a/intern/ghost/intern/GHOST_DropTargetX11.cpp b/intern/ghost/intern/GHOST_DropTargetX11.cpp index 252a8bfd095..4da3c7c996d 100644 --- a/intern/ghost/intern/GHOST_DropTargetX11.cpp +++ b/intern/ghost/intern/GHOST_DropTargetX11.cpp @@ -7,6 +7,7 @@ #include "GHOST_DropTargetX11.h" #include "GHOST_Debug.h" +#include "GHOST_PathUtils.h" #include "GHOST_utildefines.h" #include <cassert> @@ -97,89 +98,10 @@ GHOST_DropTargetX11::~GHOST_DropTargetX11() } } -/* Based on: https://stackoverflow.com/a/2766963/432509 */ - -using DecodeState_e = enum DecodeState_e { - /** Searching for an ampersand to convert. */ - STATE_SEARCH = 0, - /** Convert the two proceeding characters from hex. */ - STATE_CONVERTING -}; - -void GHOST_DropTargetX11::UrlDecode(char *decodedOut, int bufferSize, const char *encodedIn) -{ - unsigned int i; - unsigned int len = strlen(encodedIn); - DecodeState_e state = STATE_SEARCH; - int j; - unsigned int asciiCharacter; - char tempNumBuf[3] = {0}; - bool bothDigits = true; - - memset(decodedOut, 0, bufferSize); - - for (i = 0; i < len; ++i) { - switch (state) { - case STATE_SEARCH: - if (encodedIn[i] != '%') { - strncat(decodedOut, &encodedIn[i], 1); - assert((int)strlen(decodedOut) < bufferSize); - break; - } - - /* We are now converting */ - state = STATE_CONVERTING; - break; - - case STATE_CONVERTING: - bothDigits = true; - - /* Create a buffer to hold the hex. For example, if %20, this - * buffer would hold 20 (in ASCII) */ - memset(tempNumBuf, 0, sizeof(tempNumBuf)); - - /* Conversion complete (i.e. don't convert again next iter) */ - state = STATE_SEARCH; - - strncpy(tempNumBuf, &encodedIn[i], 2); - - /* Ensure both characters are hexadecimal */ - - for (j = 0; j < 2; ++j) { - if (!isxdigit(tempNumBuf[j])) { - bothDigits = false; - } - } - - if (!bothDigits) { - break; - } - /* Convert two hexadecimal characters into one character */ - sscanf(tempNumBuf, "%x", &asciiCharacter); - - /* Ensure we aren't going to overflow */ - assert((int)strlen(decodedOut) < bufferSize); - - /* Concatenate this character onto the output */ - strncat(decodedOut, (char *)&asciiCharacter, 1); - - /* Skip the next character */ - i++; - break; - } - } -} - char *GHOST_DropTargetX11::FileUrlDecode(char *fileUrl) { if (strncmp(fileUrl, "file://", 7) == 0) { - /* assume one character of encoded URL can be expanded to 4 chars max */ - int decodedSize = 4 * strlen(fileUrl) + 1; - char *decodedPath = (char *)malloc(decodedSize); - - UrlDecode(decodedPath, decodedSize, fileUrl + 7); - - return decodedPath; + return GHOST_URL_decode_alloc(fileUrl + 7); } return nullptr; diff --git a/intern/ghost/intern/GHOST_DropTargetX11.h b/intern/ghost/intern/GHOST_DropTargetX11.h index f0ef27697e1..db73ddff70f 100644 --- a/intern/ghost/intern/GHOST_DropTargetX11.h +++ b/intern/ghost/intern/GHOST_DropTargetX11.h @@ -65,14 +65,6 @@ class GHOST_DropTargetX11 { void *getURIListGhostData(unsigned char *dropBuffer, int dropBufferSize); /** - * Decode URL (i.e. converts `file:///a%20b/test` to `file:///a b/test`) - * \param decodedOut: - buffer for decoded URL. - * \param bufferSize: - size of output buffer. - * \param encodedIn: - input encoded buffer to be decoded. - */ - void UrlDecode(char *decodedOut, int bufferSize, const char *encodedIn); - - /** * Fully decode file URL (i.e. converts `file:///a%20b/test` to `/a b/test`) * \param fileUrl: - file path URL to be fully decoded. * \return decoded file path (result should be free-d). diff --git a/intern/ghost/intern/GHOST_Event.h b/intern/ghost/intern/GHOST_Event.h index 0813378a819..1e1c428e2ae 100644 --- a/intern/ghost/intern/GHOST_Event.h +++ b/intern/ghost/intern/GHOST_Event.h @@ -22,7 +22,7 @@ class GHOST_Event : public GHOST_IEvent { * \param window: The generating window (or NULL if system event). */ GHOST_Event(uint64_t msec, GHOST_TEventType type, GHOST_IWindow *window) - : m_type(type), m_time(msec), m_window(window), m_data(NULL) + : m_type(type), m_time(msec), m_window(window), m_data(nullptr) { } diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index d58fb90f63e..746e3532b03 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -411,8 +411,9 @@ static bool nearHomePosition(GHOST_TEventNDOFMotionData *ndof, float threshold) bool GHOST_NDOFManager::sendMotionEvent() { - if (!m_motionEventPending) + if (!m_motionEventPending) { return false; + } m_motionEventPending = false; /* Any pending motion is handled right now. */ diff --git a/intern/ghost/intern/GHOST_Path-api.cpp b/intern/ghost/intern/GHOST_Path-api.cpp index 1b1c72d8a4b..58f36dc096d 100644 --- a/intern/ghost/intern/GHOST_Path-api.cpp +++ b/intern/ghost/intern/GHOST_Path-api.cpp @@ -49,10 +49,10 @@ const char *GHOST_getBinaryDir() return systemPaths ? systemPaths->getBinaryDir() : nullptr; } -void GHOST_addToSystemRecentFiles(const char *filename) +void GHOST_addToSystemRecentFiles(const char *filepath) { GHOST_ISystemPaths *systemPaths = GHOST_ISystemPaths::get(); if (systemPaths) { - systemPaths->addToSystemRecentFiles(filename); + systemPaths->addToSystemRecentFiles(filepath); } } diff --git a/intern/ghost/intern/GHOST_PathUtils.cpp b/intern/ghost/intern/GHOST_PathUtils.cpp new file mode 100644 index 00000000000..3b57480039a --- /dev/null +++ b/intern/ghost/intern/GHOST_PathUtils.cpp @@ -0,0 +1,101 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2010 Blender Foundation. All rights reserved. */ + +/** \file + * \ingroup GHOST + */ + +#include <cassert> +#include <cctype> +#include <cstdio> +#include <cstdlib> +#include <cstring> + +#include "GHOST_PathUtils.h" +#include "GHOST_Types.h" + +/* Based on: https://stackoverflow.com/a/2766963/432509 */ + +using DecodeState_e = enum DecodeState_e { + /** Searching for an ampersand to convert. */ + STATE_SEARCH = 0, + /** Convert the two proceeding characters from hex. */ + STATE_CONVERTING +}; + +void GHOST_URL_decode(char *buf_dst, int buf_dst_size, const char *buf_src) +{ + const unsigned int buf_src_len = strlen(buf_src); + DecodeState_e state = STATE_SEARCH; + unsigned int ascii_character; + char temp_num_buf[3] = {0}; + + memset(buf_dst, 0, buf_dst_size); + + for (unsigned int i = 0; i < buf_src_len; i++) { + switch (state) { + case STATE_SEARCH: { + if (buf_src[i] != '%') { + strncat(buf_dst, &buf_src[i], 1); + assert((int)strlen(buf_dst) < buf_dst_size); + break; + } + + /* We are now converting. */ + state = STATE_CONVERTING; + break; + } + case STATE_CONVERTING: { + bool both_digits = true; + + /* Create a buffer to hold the hex. For example, if `%20`, + * this buffer would hold 20 (in ASCII). */ + memset(temp_num_buf, 0, sizeof(temp_num_buf)); + + /* Conversion complete (i.e. don't convert again next iteration). */ + state = STATE_SEARCH; + + strncpy(temp_num_buf, &buf_src[i], 2); + + /* Ensure both characters are hexadecimal. */ + for (int j = 0; j < 2; j++) { + if (!isxdigit(temp_num_buf[j])) { + both_digits = false; + } + } + + if (!both_digits) { + break; + } + /* Convert two hexadecimal characters into one character. */ + sscanf(temp_num_buf, "%x", &ascii_character); + + /* Ensure we aren't going to overflow. */ + assert((int)strlen(buf_dst) < buf_dst_size); + + /* Concatenate this character onto the output. */ + strncat(buf_dst, (char *)&ascii_character, 1); + + /* Skip the next character. */ + i++; + break; + } + } + } +} + +char *GHOST_URL_decode_alloc(const char *buf_src) +{ + /* Assume one character of encoded URL can be expanded to 4 chars max. */ + const size_t decoded_size_max = 4 * strlen(buf_src) + 1; + char *buf_dst = (char *)malloc(decoded_size_max); + GHOST_URL_decode(buf_dst, decoded_size_max, buf_src); + const size_t decoded_size = strlen(buf_dst) + 1; + if (decoded_size != decoded_size_max) { + char *buf_dst_trim = (char *)malloc(decoded_size); + memcpy(buf_dst_trim, buf_dst, decoded_size); + free(buf_dst); + buf_dst = buf_dst_trim; + } + return buf_dst; +} diff --git a/intern/ghost/intern/GHOST_PathUtils.h b/intern/ghost/intern/GHOST_PathUtils.h new file mode 100644 index 00000000000..26a31d1f5c6 --- /dev/null +++ b/intern/ghost/intern/GHOST_PathUtils.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright 2010 Blender Foundation. All rights reserved. */ + +/** \file + * \ingroup GHOST + */ + +#pragma once + +/** + * Decode URL (i.e. converts `file:///a%20b/test` to `file:///a b/test`) + * + * \param buf_dst: Buffer for decoded URL. + * \param buf_dst_maxlen: Size of output buffer. + * \param buf_src: Input encoded buffer to be decoded. + */ +void GHOST_URL_decode(char *buf_dst, int buf_dst_size, const char *buf_src); +/** + * A version of #GHOST_URL_decode that allocates the string & returns it. + * + * \param buf_src: Input encoded buffer to be decoded. + * \return The decoded output buffer. + */ +char *GHOST_URL_decode_alloc(const char *buf_src); diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index ebb52bf08cb..18d91d43057 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -11,7 +11,9 @@ #include "GHOST_EventDragnDrop.h" #include "GHOST_EventKey.h" #include "GHOST_EventWheel.h" +#include "GHOST_PathUtils.h" #include "GHOST_TimerManager.h" +#include "GHOST_WaylandUtils.h" #include "GHOST_WindowManager.h" #include "GHOST_utildefines.h" @@ -82,6 +84,10 @@ static void output_handle_done(void *data, struct wl_output *wl_output); static bool use_gnome_confine_hack = false; #endif +#define XKB_STATE_MODS_ALL \ + (enum xkb_state_component)(XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED | \ + XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE) + /* -------------------------------------------------------------------- */ /** \name Inline Event Codes * @@ -306,6 +312,20 @@ struct input_t { */ struct xkb_state *xkb_state_empty_with_numlock = nullptr; + /** + * Cache result of `xkb_keymap_mod_get_index` + * so every time a modifier is accessed a string lookup isn't required. + * Be sure to check for #XKB_MOD_INVALID before using. + */ + struct { + xkb_mod_index_t shift; /* #XKB_MOD_NAME_SHIFT */ + xkb_mod_index_t caps; /* #XKB_MOD_NAME_CAPS */ + xkb_mod_index_t ctrl; /* #XKB_MOD_NAME_CTRL */ + xkb_mod_index_t alt; /* #XKB_MOD_NAME_ALT */ + xkb_mod_index_t num; /* #XKB_MOD_NAME_NUM */ + xkb_mod_index_t logo; /* #XKB_MOD_NAME_LOGO */ + } xkb_keymap_mod_index; + struct { /** Key repetition in character per second. */ int32_t rate = 0; @@ -1138,6 +1158,7 @@ static void data_device_handle_enter(void *data, input_t *input = static_cast<input_t *>(data); std::lock_guard lock{input->data_offer_dnd_mutex}; + delete input->data_offer_dnd; input->data_offer_dnd = static_cast<data_offer_t *>(wl_data_offer_get_user_data(id)); data_offer_t *data_offer = input->data_offer_dnd; @@ -1197,8 +1218,6 @@ static void data_device_handle_drop(void *data, struct wl_data_device * /*wl_dat input_t *input = static_cast<input_t *>(data); std::lock_guard lock{input->data_offer_dnd_mutex}; - CLOG_INFO(LOG, 2, "drop"); - data_offer_t *data_offer = input->data_offer_dnd; const std::string mime_receive = *std::find_first_of(mime_preference_order.begin(), @@ -1206,6 +1225,8 @@ static void data_device_handle_drop(void *data, struct wl_data_device * /*wl_dat data_offer->types.begin(), data_offer->types.end()); + CLOG_INFO(LOG, 2, "drop mime_recieve=%s", mime_receive.c_str()); + auto read_uris_fn = [](input_t *const input, data_offer_t *data_offer, wl_surface *surface, @@ -1214,9 +1235,15 @@ static void data_device_handle_drop(void *data, struct wl_data_device * /*wl_dat const std::string data = read_pipe(data_offer, mime_receive, nullptr); + CLOG_INFO( + LOG, 2, "drop_read_uris mime_receive=%s, data=%s", mime_receive.c_str(), data.c_str()); + wl_data_offer_finish(data_offer->id); wl_data_offer_destroy(data_offer->id); + if (input->data_offer_dnd == data_offer) { + input->data_offer_dnd = nullptr; + } delete data_offer; data_offer = nullptr; @@ -1224,7 +1251,9 @@ static void data_device_handle_drop(void *data, struct wl_data_device * /*wl_dat if (mime_receive == mime_text_uri) { static constexpr const char *file_proto = "file://"; - static constexpr const char *crlf = "\r\n"; + /* NOTE: some applications CRLF (`\r\n`) GTK3 for e.g. & others don't `pcmanfm-qt`. + * So support both, once `\n` is found, strip the preceding `\r` if found. */ + static constexpr const char *lf = "\n"; GHOST_WindowWayland *win = ghost_wl_surface_user_data(surface); std::vector<std::string> uris; @@ -1233,13 +1262,18 @@ static void data_device_handle_drop(void *data, struct wl_data_device * /*wl_dat while (true) { pos = data.find(file_proto, pos); const size_t start = pos + sizeof(file_proto) - 1; - pos = data.find(crlf, pos); - const size_t end = pos; + pos = data.find(lf, pos); if (pos == std::string::npos) { break; } + /* Account for 'CRLF' case. */ + size_t end = pos; + if (data[end - 1] == '\r') { + end -= 1; + } uris.push_back(data.substr(start, end - start)); + CLOG_INFO(LOG, 2, "drop_read_uris pos=%zu, text_uri=\"%s\"", start, uris.back().c_str()); } GHOST_TStringArray *flist = static_cast<GHOST_TStringArray *>( @@ -1247,10 +1281,10 @@ static void data_device_handle_drop(void *data, struct wl_data_device * /*wl_dat flist->count = int(uris.size()); flist->strings = static_cast<uint8_t **>(malloc(uris.size() * sizeof(uint8_t *))); for (size_t i = 0; i < uris.size(); i++) { - flist->strings[i] = static_cast<uint8_t *>(malloc((uris[i].size() + 1) * sizeof(uint8_t))); - memcpy(flist->strings[i], uris[i].data(), uris[i].size() + 1); + flist->strings[i] = (uint8_t *)GHOST_URL_decode_alloc(uris[i].c_str()); } + CLOG_INFO(LOG, 2, "drop_read_uris_fn file_count=%d", flist->count); const wl_fixed_t scale = win->scale(); system->pushEvent(new GHOST_EventDragnDrop(system->getMilliSeconds(), GHOST_kEventDraggingDropDone, @@ -1263,12 +1297,13 @@ static void data_device_handle_drop(void *data, struct wl_data_device * /*wl_dat else if (ELEM(mime_receive, mime_text_plain, mime_text_utf8)) { /* TODO: enable use of internal functions 'txt_insert_buf' and * 'text_update_edited' to behave like dropped text was pasted. */ + CLOG_INFO(LOG, 2, "drop_read_uris_fn (text_plain, text_utf8), unhandled!"); } wl_display_roundtrip(system->display()); }; /* Pass in `input->focus_dnd` instead of accessing it from `input` since the leave callback - * (#data_device_leave) will clear the value once this function starts. */ + * (#data_device_handle_leave) will clear the value once this function starts. */ std::thread read_thread(read_uris_fn, input, data_offer, input->focus_dnd, mime_receive); read_thread.detach(); } @@ -2086,6 +2121,13 @@ static void keyboard_handle_keymap(void *data, } } + input->xkb_keymap_mod_index.shift = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_SHIFT); + input->xkb_keymap_mod_index.caps = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_CAPS); + input->xkb_keymap_mod_index.ctrl = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_CTRL); + input->xkb_keymap_mod_index.alt = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_ALT); + input->xkb_keymap_mod_index.num = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_NUM); + input->xkb_keymap_mod_index.logo = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_LOGO); + xkb_keymap_unref(keymap); } @@ -2099,7 +2141,7 @@ static void keyboard_handle_enter(void *data, struct wl_keyboard * /*wl_keyboard*/, const uint32_t serial, struct wl_surface *surface, - struct wl_array * /*keys*/) + struct wl_array *keys) { if (!ghost_wl_surface_own(surface)) { CLOG_INFO(LOG, 2, "enter (skipped)"); @@ -2110,6 +2152,49 @@ static void keyboard_handle_enter(void *data, input_t *input = static_cast<input_t *>(data); input->keyboard.serial = serial; input->keyboard.wl_surface = surface; + + if (keys->size != 0) { + /* If there are any keys held when activating the window, + * modifiers will be compared against the input state, + * only enabling modifiers that were previously disabled. */ + + const xkb_mod_mask_t state = xkb_state_serialize_mods(input->xkb_state, XKB_STATE_MODS_ALL); + uint32_t *key; + WL_ARRAY_FOR_EACH (key, keys) { + const xkb_keycode_t key_code = *key + EVDEV_OFFSET; + const xkb_keysym_t sym = xkb_state_key_get_one_sym(input->xkb_state, key_code); + GHOST_TKey gkey = GHOST_kKeyUnknown; + +#define MOD_TEST(state, mod) ((mod != XKB_MOD_INVALID) && (state & (1 << mod))) +#define MOD_TEST_CASE(xkb_key, ghost_key, mod_index) \ + case xkb_key: \ + if (!MOD_TEST(state, input->xkb_keymap_mod_index.mod_index)) { \ + gkey = ghost_key; \ + } \ + break + + switch (sym) { + MOD_TEST_CASE(XKB_KEY_Shift_L, GHOST_kKeyLeftShift, shift); + MOD_TEST_CASE(XKB_KEY_Shift_R, GHOST_kKeyRightShift, shift); + MOD_TEST_CASE(XKB_KEY_Control_L, GHOST_kKeyLeftControl, ctrl); + MOD_TEST_CASE(XKB_KEY_Control_R, GHOST_kKeyRightControl, ctrl); + MOD_TEST_CASE(XKB_KEY_Alt_L, GHOST_kKeyLeftAlt, alt); + MOD_TEST_CASE(XKB_KEY_Alt_R, GHOST_kKeyRightAlt, alt); + MOD_TEST_CASE(XKB_KEY_Super_L, GHOST_kKeyOS, logo); + MOD_TEST_CASE(XKB_KEY_Super_R, GHOST_kKeyOS, logo); + } + +#undef MOD_TEST +#undef MOD_TEST_CASE + + if (gkey != GHOST_kKeyUnknown) { + GHOST_IWindow *win = ghost_wl_surface_user_data(surface); + GHOST_SystemWayland *system = input->system; + input->system->pushEvent( + new GHOST_EventKey(system->getMilliSeconds(), GHOST_kEventKeyDown, win, gkey, false)); + } + } + } } /** @@ -2336,7 +2421,13 @@ static void keyboard_handle_modifiers(void *data, const uint32_t mods_locked, const uint32_t group) { - CLOG_INFO(LOG, 2, "modifiers"); + CLOG_INFO(LOG, + 2, + "modifiers (depressed=%u, latched=%u, locked=%u, group=%u)", + mods_depressed, + mods_latched, + mods_locked, + group); input_t *input = static_cast<input_t *>(data); xkb_state_update_mask(input->xkb_state, mods_depressed, mods_latched, mods_locked, 0, 0, group); @@ -2473,7 +2564,7 @@ static void xdg_output_handle_logical_size(void *data, * done (we can't match exactly because fractional scaling can't be * detected otherwise), then override if necessary. */ if ((output->size_logical[0] == width) && (output->scale_fractional == wl_fixed_from_int(1))) { - GHOST_PRINT("xdg_output scale did not match, overriding with wl_output scale"); + GHOST_PRINT("xdg_output scale did not match, overriding with wl_output scale\n"); #ifdef USE_GNOME_CONFINE_HACK /* Use a bug in GNOME to check GNOME is in use. If the bug is fixed this won't cause an issue @@ -2923,32 +3014,36 @@ GHOST_TSuccess GHOST_SystemWayland::getModifierKeys(GHOST_ModifierKeys &keys) co return GHOST_kFailure; } - static const xkb_state_component mods_all = xkb_state_component( - XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_LOCKED | - XKB_STATE_MODS_EFFECTIVE); + input_t *input = d->inputs[0]; bool val; - /* NOTE: XKB doesn't seem to differentiate between left/right modifiers. */ + /* NOTE: XKB doesn't differentiate between left/right modifiers + * for it's internal modifier state storage. */ + const xkb_mod_mask_t state = xkb_state_serialize_mods(input->xkb_state, XKB_STATE_MODS_ALL); + +#define MOD_TEST(state, mod) ((mod != XKB_MOD_INVALID) && (state & (1 << mod))) - val = xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, XKB_MOD_NAME_SHIFT, mods_all) == 1; + val = MOD_TEST(state, input->xkb_keymap_mod_index.shift); keys.set(GHOST_kModifierKeyLeftShift, val); keys.set(GHOST_kModifierKeyRightShift, val); - val = xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, XKB_MOD_NAME_ALT, mods_all) == 1; + val = MOD_TEST(state, input->xkb_keymap_mod_index.alt); keys.set(GHOST_kModifierKeyLeftAlt, val); keys.set(GHOST_kModifierKeyRightAlt, val); - val = xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, XKB_MOD_NAME_CTRL, mods_all) == 1; + val = MOD_TEST(state, input->xkb_keymap_mod_index.ctrl); keys.set(GHOST_kModifierKeyLeftControl, val); keys.set(GHOST_kModifierKeyRightControl, val); - val = xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, XKB_MOD_NAME_LOGO, mods_all) == 1; + val = MOD_TEST(state, input->xkb_keymap_mod_index.logo); keys.set(GHOST_kModifierKeyOS, val); - val = xkb_state_mod_name_is_active(d->inputs[0]->xkb_state, XKB_MOD_NAME_NUM, mods_all) == 1; + val = MOD_TEST(state, input->xkb_keymap_mod_index.num); keys.set(GHOST_kModifierKeyNum, val); +#undef MOD_TEST + return GHOST_kSuccess; } diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index 00cc5f3af8f..0494e462bfc 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -287,7 +287,7 @@ uint8_t GHOST_SystemX11::getNumDisplays() const void GHOST_SystemX11::getMainDisplayDimensions(uint32_t &width, uint32_t &height) const { if (m_display) { - /* NOTE(campbell): for this to work as documented, + /* NOTE(@campbellbarton): for this to work as documented, * we would need to use Xinerama check r54370 for code that did this, * we've since removed since its not worth the extra dependency. */ getAllDisplayDimensions(width, height); @@ -514,8 +514,9 @@ static void destroyIMCallback(XIM /*xim*/, XPointer ptr, XPointer /*data*/) bool GHOST_SystemX11::openX11_IM() { - if (!m_display) + if (!m_display) { return false; + } /* set locale modifiers such as `@im=ibus` specified by XMODIFIERS. */ XSetLocaleModifiers(""); @@ -585,7 +586,7 @@ struct init_timestamp_data { Time timestamp; }; -static Bool init_timestamp_scanner(Display *, XEvent *event, XPointer arg) +static Bool init_timestamp_scanner(Display * /*display*/, XEvent *event, XPointer arg) { init_timestamp_data *data = reinterpret_cast<init_timestamp_data *>(arg); switch (event->type) { @@ -673,11 +674,12 @@ bool GHOST_SystemX11::processEvents(bool waitForEvent) GHOST_WindowX11 *window = findGhostWindow(xevent.xany.window); if (window && !window->getX11_XIC() && window->createX11_XIC()) { GHOST_PRINT("XIM input context created\n"); - if (xevent.type == KeyPress) + if (xevent.type == KeyPress) { /* we can assume the window has input focus * here, because key events are received only * when the window is focused. */ XSetICFocus(window->getX11_XIC()); + } } } } @@ -1321,10 +1323,12 @@ void GHOST_SystemX11::processEvent(XEvent *xe) #if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING) XIC xic = window->getX11_XIC(); if (xic) { - if (xe->type == FocusIn) + if (xe->type == FocusIn) { XSetICFocus(xic); - else + } + else { XUnsetICFocus(xic); + } } #endif @@ -2381,10 +2385,11 @@ class DialogData { /* Is the mouse inside the given button */ bool isInsideButton(XEvent &e, uint button_num) { - return ((e.xmotion.y > height - padding_y - button_height) && - (e.xmotion.y < height - padding_y) && - (e.xmotion.x > width - (padding_x + button_width) * button_num) && - (e.xmotion.x < width - padding_x - (padding_x + button_width) * (button_num - 1))); + return ( + (e.xmotion.y > (int)(height - padding_y - button_height)) && + (e.xmotion.y < (int)(height - padding_y)) && + (e.xmotion.x > (int)(width - (padding_x + button_width) * button_num)) && + (e.xmotion.x < (int)(width - padding_x - (padding_x + button_width) * (button_num - 1)))); } }; diff --git a/intern/ghost/intern/GHOST_TimerManager.cpp b/intern/ghost/intern/GHOST_TimerManager.cpp index 504cdbfb6c8..e54c2515029 100644 --- a/intern/ghost/intern/GHOST_TimerManager.cpp +++ b/intern/ghost/intern/GHOST_TimerManager.cpp @@ -71,10 +71,11 @@ uint64_t GHOST_TimerManager::nextFireTime() TTimerVector::iterator iter; for (iter = m_timers.begin(); iter != m_timers.end(); ++iter) { - uint64_t next = (*iter)->getNext(); + const uint64_t next = (*iter)->getNext(); - if (next < smallest) + if (next < smallest) { smallest = next; + } } return smallest; @@ -86,8 +87,9 @@ bool GHOST_TimerManager::fireTimers(uint64_t time) bool anyProcessed = false; for (iter = m_timers.begin(); iter != m_timers.end(); ++iter) { - if (fireTimer(time, *iter)) + if (fireTimer(time, *iter)) { anyProcessed = true; + } } return anyProcessed; @@ -113,9 +115,7 @@ bool GHOST_TimerManager::fireTimer(uint64_t time, GHOST_TimerTask *task) return true; } - else { - return false; - } + return false; } void GHOST_TimerManager::disposeTimers() diff --git a/intern/ghost/intern/GHOST_TimerManager.h b/intern/ghost/intern/GHOST_TimerManager.h index 090a84d1f14..4458a107190 100644 --- a/intern/ghost/intern/GHOST_TimerManager.h +++ b/intern/ghost/intern/GHOST_TimerManager.h @@ -87,7 +87,7 @@ class GHOST_TimerManager { */ void disposeTimers(); - typedef std::vector<GHOST_TimerTask *> TTimerVector; + using TTimerVector = std::vector<GHOST_TimerTask *>; /** The list with event consumers. */ TTimerVector m_timers; diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp index 2276e90387b..83c608435b0 100644 --- a/intern/ghost/intern/GHOST_WindowX11.cpp +++ b/intern/ghost/intern/GHOST_WindowX11.cpp @@ -147,16 +147,19 @@ static XVisualInfo *x11_visualinfo_from_glx(Display *display, /* take a frame buffer config that has alpha cap */ for (int i = 0; i < nbfbconfig; i++) { XVisualInfo *visual = (XVisualInfo *)glXGetVisualFromFBConfig(display, fbconfigs[i]); - if (!visual) + 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) + if (!pict_format) { continue; - if (pict_format->direct.alphaMask <= 0) + } + if (pict_format->direct.alphaMask <= 0) { continue; + } } *fbconfig = fbconfigs[i]; @@ -487,8 +490,9 @@ static Bool destroyICCallback(XIC /*xic*/, XPointer ptr, XPointer /*data*/) bool GHOST_WindowX11::createX11_XIC() { XIM xim = m_system->getX11_XIM(); - if (!xim) + if (!xim) { return false; + } XICCallback destroy; destroy.callback = (XICProc)destroyICCallback; @@ -536,17 +540,21 @@ void GHOST_WindowX11::refreshXInputDevices() XEventClass ev; DeviceMotionNotify(xtablet.Device, xtablet.MotionEvent, ev); - if (ev) + if (ev) { xevents.push_back(ev); + } DeviceButtonPress(xtablet.Device, xtablet.PressEvent, ev); - if (ev) + if (ev) { xevents.push_back(ev); + } ProximityIn(xtablet.Device, xtablet.ProxInEvent, ev); - if (ev) + if (ev) { xevents.push_back(ev); + } ProximityOut(xtablet.Device, xtablet.ProxOutEvent, ev); - if (ev) + if (ev) { xevents.push_back(ev); + } } XSelectExtensionEvent(m_display, m_window, xevents.data(), (int)xevents.size()); diff --git a/intern/ghost/test/gears/GHOST_Test.cpp b/intern/ghost/test/gears/GHOST_Test.cpp index 5a43543d163..f5ef2527d75 100644 --- a/intern/ghost/test/gears/GHOST_Test.cpp +++ b/intern/ghost/test/gears/GHOST_Test.cpp @@ -559,10 +559,12 @@ bool Application::processEvent(GHOST_IEvent *event) break; case GHOST_kKeyS: // toggle mono and stereo - if (stereo) + if (stereo) { stereo = false; - else + } + else { stereo = true; + } break; case GHOST_kKeyT: @@ -680,8 +682,9 @@ int main(int /*argc*/, char ** /*argv*/) if (lresult == ERROR_SUCCESS) printf("Successfully set value for key\n"); regkey.Close(); - if (lresult == ERROR_SUCCESS) + if (lresult == ERROR_SUCCESS) { printf("Successfully closed key\n"); + } // regkey.Write("2"); } #endif // WIN32 diff --git a/intern/ghost/test/multitest/MultiTest.c b/intern/ghost/test/multitest/MultiTest.c index 157e4f1b0f2..99b88dfb525 100644 --- a/intern/ghost/test/multitest/MultiTest.c +++ b/intern/ghost/test/multitest/MultiTest.c @@ -179,37 +179,44 @@ static void mainwindow_do_key(MainWindow *mw, GHOST_TKey key, int press) { switch (key) { case GHOST_kKeyC: - if (press) + if (press) { GHOST_SetCursorShape(mw->win, (GHOST_TStandardCursor)(rand() % (GHOST_kStandardCursorNumCursors))); + } break; case GHOST_kKeyLeftBracket: - if (press) + if (press) { GHOST_SetCursorVisibility(mw->win, 0); + } break; case GHOST_kKeyRightBracket: - if (press) + if (press) { GHOST_SetCursorVisibility(mw->win, 1); + } break; case GHOST_kKeyE: - if (press) + if (press) { multitestapp_toggle_extra_window(mw->app); + } break; case GHOST_kKeyQ: - if (press) + if (press) { multitestapp_exit(mw->app); + } break; case GHOST_kKeyT: - if (press) + if (press) { mainwindow_log(mw, "TextTest~|`hello`\"world\",<>/"); + } break; case GHOST_kKeyR: if (press) { int i; mainwindow_log(mw, "Invalidating window 10 times"); - for (i = 0; i < 10; i++) + for (i = 0; i < 10; i++) { GHOST_InvalidateWindow(mw->win); + } } break; case GHOST_kKeyF11: @@ -328,9 +335,7 @@ MainWindow *mainwindow_new(MultiTestApp *app) return mw; } - else { - return NULL; - } + return NULL; } void mainwindow_free(MainWindow *mw) diff --git a/intern/guardedalloc/MEM_guardedalloc.h b/intern/guardedalloc/MEM_guardedalloc.h index fca19fb9731..64987548a11 100644 --- a/intern/guardedalloc/MEM_guardedalloc.h +++ b/intern/guardedalloc/MEM_guardedalloc.h @@ -199,6 +199,15 @@ extern size_t (*MEM_get_peak_memory)(void) ATTR_WARN_UNUSED_RESULT; #ifndef NDEBUG extern const char *(*MEM_name_ptr)(void *vmemh); +/** + * Change the debugging name/string assigned to the memory allocated at \a vmemh. Only affects the + * guarded allocator. The name must be a static string, because only a pointer to it is stored! + * + * Handy when debugging leaking memory allocated by some often called, generic function with a + * unspecific name. A caller with more info can set a more specific name, and see which call to the + * generic function allocates the leaking memory. + */ +extern void (*MEM_name_ptr_set)(void *vmemh, const char *str) ATTR_NONNULL(); #endif /** diff --git a/intern/guardedalloc/intern/mallocn.c b/intern/guardedalloc/intern/mallocn.c index f7979168799..63f06ced31d 100644 --- a/intern/guardedalloc/intern/mallocn.c +++ b/intern/guardedalloc/intern/mallocn.c @@ -49,6 +49,7 @@ size_t (*MEM_get_peak_memory)(void) = MEM_lockfree_get_peak_memory; #ifndef NDEBUG const char *(*MEM_name_ptr)(void *vmemh) = MEM_lockfree_name_ptr; +void (*MEM_name_ptr_set)(void *vmemh, const char *str) = MEM_lockfree_name_ptr_set; #endif void *aligned_malloc(size_t size, size_t alignment) @@ -128,6 +129,7 @@ void MEM_use_lockfree_allocator(void) #ifndef NDEBUG MEM_name_ptr = MEM_lockfree_name_ptr; + MEM_name_ptr_set = MEM_lockfree_name_ptr_set; #endif } @@ -159,5 +161,6 @@ void MEM_use_guarded_allocator(void) #ifndef NDEBUG MEM_name_ptr = MEM_guarded_name_ptr; + MEM_name_ptr_set = MEM_guarded_name_ptr_set; #endif } diff --git a/intern/guardedalloc/intern/mallocn_guarded_impl.c b/intern/guardedalloc/intern/mallocn_guarded_impl.c index 8bf1680e6f8..cd4b99ecde8 100644 --- a/intern/guardedalloc/intern/mallocn_guarded_impl.c +++ b/intern/guardedalloc/intern/mallocn_guarded_impl.c @@ -1199,4 +1199,18 @@ const char *MEM_guarded_name_ptr(void *vmemh) return "MEM_guarded_name_ptr(NULL)"; } + +void MEM_guarded_name_ptr_set(void *vmemh, const char *str) +{ + if (!vmemh) { + return; + } + + MemHead *memh = vmemh; + memh--; + memh->name = str; + if (memh->prev) { + MEMNEXT(memh->prev)->nextname = str; + } +} #endif /* NDEBUG */ diff --git a/intern/guardedalloc/intern/mallocn_intern.h b/intern/guardedalloc/intern/mallocn_intern.h index f8b16ff6ddf..ce5683a04ae 100644 --- a/intern/guardedalloc/intern/mallocn_intern.h +++ b/intern/guardedalloc/intern/mallocn_intern.h @@ -131,6 +131,7 @@ void MEM_lockfree_reset_peak_memory(void); size_t MEM_lockfree_get_peak_memory(void) ATTR_WARN_UNUSED_RESULT; #ifndef NDEBUG const char *MEM_lockfree_name_ptr(void *vmemh); +void MEM_lockfree_name_ptr_set(void *vmemh, const char *str); #endif /* Prototypes for fully guarded allocator functions */ @@ -174,6 +175,7 @@ void MEM_guarded_reset_peak_memory(void); size_t MEM_guarded_get_peak_memory(void) ATTR_WARN_UNUSED_RESULT; #ifndef NDEBUG const char *MEM_guarded_name_ptr(void *vmemh); +void MEM_guarded_name_ptr_set(void *vmemh, const char *str); #endif #ifdef __cplusplus diff --git a/intern/guardedalloc/intern/mallocn_lockfree_impl.c b/intern/guardedalloc/intern/mallocn_lockfree_impl.c index 300e2000a14..b5ee539ff4d 100644 --- a/intern/guardedalloc/intern/mallocn_lockfree_impl.c +++ b/intern/guardedalloc/intern/mallocn_lockfree_impl.c @@ -426,4 +426,8 @@ const char *MEM_lockfree_name_ptr(void *vmemh) return "MEM_lockfree_name_ptr(NULL)"; } + +void MEM_lockfree_name_ptr_set(void *UNUSED(vmemh), const char *UNUSED(str)) +{ +} #endif /* NDEBUG */ diff --git a/intern/mantaflow/intern/MANTA_main.cpp b/intern/mantaflow/intern/MANTA_main.cpp index fc14c909f4d..f5f22dc700b 100644 --- a/intern/mantaflow/intern/MANTA_main.cpp +++ b/intern/mantaflow/intern/MANTA_main.cpp @@ -626,7 +626,7 @@ static void manta_python_main_module_restore(PyObject *main_mod) * access these variables, the same __main__ module has to be used every time. * * Unfortunately, we also depend on the fact that mantaflow dumps variables into this module using - * PyRun_SimpleString. So we can't easily create a separate module without changing mantaflow. + * #PyRun_String. So we can't easily create a separate module without changing mantaflow. */ static PyObject *manta_main_module = nullptr; @@ -1161,7 +1161,7 @@ string MANTA::parseScript(const string &setup_string, FluidModifierData *fmd) return res.str(); } -/* Dirty hack: Needed to format paths from python code that is run via PyRun_SimpleString */ +/** Dirty hack: Needed to format paths from python code that is run via #PyRun_String. */ static string escapePath(string const &s) { string result = ""; |