Skip to content

Commit

Permalink
Vectorize BSDFContext
Browse files Browse the repository at this point in the history
  • Loading branch information
Sebastien Speierer committed May 13, 2023
1 parent 3875f9a commit 2808967
Show file tree
Hide file tree
Showing 23 changed files with 458 additions and 415 deletions.
85 changes: 72 additions & 13 deletions include/mitsuba/render/bsdf.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,9 @@ MI_DECLARE_ENUM_OPERATORS(BSDFFlags)
* The \ref BSDFContext data structure encodes these preferences and is
* supplied to most \ref BSDF methods.
*/
struct MI_EXPORT_LIB BSDFContext {
template <typename Float, typename Spectrum> struct BSDFContext {
using Index = dr::uint32_array_t<Float>;

// =============================================================
//! @{ \name Fields
// =============================================================
Expand All @@ -141,18 +143,16 @@ struct MI_EXPORT_LIB BSDFContext {
* Bit mask for requested BSDF component types to be sampled/evaluated
* The default value (equal to \ref BSDFFlags::All) enables all components.
*/
uint32_t type_mask = (uint32_t) 0x1FFu;
Index type_mask = (Index) 0x1FFu;

/// Integer value of requested BSDF component index to be sampled/evaluated.
uint32_t component = (uint32_t) -1;
Index component = (Index) -1;

//! @}
// =============================================================

BSDFContext() = default;

BSDFContext(TransportMode mode, uint32_t type_mask = (uint32_t) 0x1FFu,
uint32_t component = (uint32_t) -1)
BSDFContext(TransportMode mode, Index type_mask = (Index) 0x1FFu,
Index component = (Index) -1)
: mode(mode), type_mask(type_mask), component(component) { }

/**
Expand All @@ -168,11 +168,13 @@ struct MI_EXPORT_LIB BSDFContext {
* Checks whether a given BSDF component type and BSDF component index are
* enabled in this context.
*/
bool is_enabled(BSDFFlags type_, uint32_t component_ = 0) const {
uint32_t type = (uint32_t) type_;
return (type_mask == (uint32_t) -1 || (type_mask & type) == type)
&& (component == (uint32_t) -1 || component == component_);
dr::mask_t<Float> is_enabled(Index type_, Index component_ = 0) const {
Index type = (Index) type_;
return (dr::eq(type_mask, (Index) -1) || dr::eq(type_mask & type, type))
&& (dr::eq(component, (Index) -1) || dr::eq(component, component_));
}

DRJIT_STRUCT(BSDFContext, mode, type_mask, component);
};

/// Data structure holding the result of BSDF sampling operations.
Expand Down Expand Up @@ -550,8 +552,65 @@ class MI_EXPORT_LIB BSDF : public Object {
extern MI_EXPORT_LIB std::ostream &operator<<(std::ostream &os,
const TransportMode &mode);

extern MI_EXPORT_LIB std::ostream &operator<<(std::ostream &os,
const BSDFContext& ctx);
template <typename Index>
std::string type_mask_to_string(Index type_mask) {
std::ostringstream oss;
oss << "{ ";

#define PROCESS(flag, name) \
if (has_flag(type_mask, flag)) { \
oss << #name << " "; \
type_mask = type_mask & ~flag; \
}
PROCESS(BSDFFlags::All, all)
PROCESS(BSDFFlags::Reflection, reflection)
PROCESS(BSDFFlags::Transmission, transmission)
PROCESS(BSDFFlags::Smooth, smooth)
PROCESS(BSDFFlags::Diffuse, diffuse)
PROCESS(BSDFFlags::Glossy, glossy)
PROCESS(BSDFFlags::Delta, delta)
PROCESS(BSDFFlags::Delta1D, delta_1d)
PROCESS(BSDFFlags::DiffuseReflection, diffuse_reflection)
PROCESS(BSDFFlags::DiffuseTransmission, diffuse_transmission)
PROCESS(BSDFFlags::GlossyReflection, glossy_reflection)
PROCESS(BSDFFlags::GlossyTransmission, glossy_transmission)
PROCESS(BSDFFlags::DeltaReflection, delta_reflection)
PROCESS(BSDFFlags::DeltaTransmission, delta_transmission)
PROCESS(BSDFFlags::Delta1DReflection, delta_1d_reflection)
PROCESS(BSDFFlags::Delta1DTransmission, delta_1d_transmission)
PROCESS(BSDFFlags::Null, null)
PROCESS(BSDFFlags::Anisotropic, anisotropic)
PROCESS(BSDFFlags::FrontSide, front_side)
PROCESS(BSDFFlags::BackSide, back_side)
PROCESS(BSDFFlags::SpatiallyVarying, spatially_varying)
PROCESS(BSDFFlags::NonSymmetric, non_symmetric)
#undef PROCESS

Assert(type_mask == 0);
oss << "}";
return oss.str();
}

template <typename Float, typename Spectrum>
std::ostream &operator<<(std::ostream &os, const BSDFContext<Float, Spectrum>& ctx) {
if constexpr (dr::is_jit_v<Float>) {
os << "BSDFContext[" << std::endl
<< " mode = " << ctx.mode << "," << std::endl
<< " type_mask = " << ctx.type_mask << "," << std::endl
<< " component = " << ctx.component;
} else {
os << "BSDFContext[" << std::endl
<< " mode = " << ctx.mode << "," << std::endl
<< " type_mask = " << type_mask_to_string(ctx.type_mask) << "," << std::endl
<< " component = ";
if (ctx.component == (uint32_t) -1)
os << "all";
else
os << ctx.component;
}
os << std::endl << "]";
return os;
}

template <typename Float, typename Spectrum>
std::ostream &operator<<(std::ostream &os, const BSDFSample3<Float, Spectrum>& bs) {
Expand Down
4 changes: 3 additions & 1 deletion include/mitsuba/render/fwd.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

NAMESPACE_BEGIN(mitsuba)

struct BSDFContext;
template <typename Float, typename Spectrum> class BSDF;
template <typename Float, typename Spectrum> class OptixDenoiser;
template <typename Float, typename Spectrum> class Emitter;
Expand Down Expand Up @@ -37,6 +36,7 @@ template <typename Float, typename Spectrum> class MeshAttribute;
template <typename Float, typename Spectrum> struct DirectionSample;
template <typename Float, typename Spectrum> struct PositionSample;
template <typename Float, typename Spectrum> struct BSDFSample3;
template <typename Float, typename Spectrum> struct BSDFContext;
template <typename Float, typename Spectrum> struct PhaseFunctionContext;
template <typename Float, typename Spectrum> struct Interaction;
template <typename Float, typename Spectrum> struct MediumInteraction;
Expand Down Expand Up @@ -64,6 +64,7 @@ template <typename Float_, typename Spectrum_> struct RenderAliases {
using PositionSample3f = PositionSample<Float, Spectrum>;
using DirectionSample3f = DirectionSample<Float, Spectrum>;
using BSDFSample3f = BSDFSample3<Float, Spectrum>;
using BSDFContext = mitsuba::BSDFContext<Float, Spectrum>;
using PhaseFunctionContext = mitsuba::PhaseFunctionContext<Float, Spectrum>;
using Interaction3f = Interaction<Float, Spectrum>;
using MediumInteraction3f = MediumInteraction<Float, Spectrum>;
Expand Down Expand Up @@ -155,6 +156,7 @@ template <typename Float_, typename Spectrum_> struct RenderAliases {
using MediumInteraction3f = typename RenderAliases::MediumInteraction3f; \
using PreliminaryIntersection3f = typename RenderAliases::PreliminaryIntersection3f; \
using BSDFSample3f = typename RenderAliases::BSDFSample3f; \
using BSDFContext = typename RenderAliases::BSDFContext; \
DRJIT_MAP(MI_IMPORT_TYPES_MACRO, __VA_ARGS__)

#define MI_IMPORT_OBJECT_TYPES() \
Expand Down
4 changes: 2 additions & 2 deletions src/bsdfs/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ add_plugin(dielectric dielectric.cpp)
add_plugin(diffuse diffuse.cpp)
add_plugin(mask mask.cpp)
add_plugin(measured measured.cpp)
add_plugin(measured_polarized measured_polarized.cpp)
add_plugin(normalmap normalmap.cpp)
add_plugin(null null.cpp)
add_plugin(plastic plastic.cpp)
add_plugin(pplastic pplastic.cpp)
add_plugin(roughconductor roughconductor.cpp)
add_plugin(roughdielectric roughdielectric.cpp)
add_plugin(roughplastic roughplastic.cpp)
Expand All @@ -18,8 +20,6 @@ add_plugin(twosided twosided.cpp)
add_plugin(polarizer polarizer.cpp)
add_plugin(retarder retarder.cpp)
add_plugin(circular circular.cpp)
add_plugin(measured_polarized measured_polarized.cpp)
add_plugin(pplastic pplastic.cpp)
add_plugin(principled principled.cpp)
add_plugin(principledthin principledthin.cpp)

Expand Down
121 changes: 77 additions & 44 deletions src/bsdfs/blendbsdf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,24 +115,27 @@ class BlendBSDF final : public BSDF<Float, Spectrum> {
Mask active) const override {
MI_MASKED_FUNCTION(ProfilerPhase::BSDFSample, active);

BSDFSample3f bs = dr::zeros<BSDFSample3f>();
Spectrum result(0.f);

Mask sample_all = dr::eq(ctx.component, (uint32_t) -1);

Float weight = eval_weight(si, active);
if (unlikely(ctx.component != (uint32_t) -1)) {
bool sample_first = ctx.component < m_nested_bsdf[0]->component_count();

if (dr::any_or<true>(!sample_all)) {
Mask sample_first = ctx.component < m_nested_bsdf[0]->component_count();
BSDFContext ctx2(ctx);
if (!sample_first)
ctx2.component -= (uint32_t) m_nested_bsdf[0]->component_count();
else
weight = 1.f - weight;
auto [bs, result] = m_nested_bsdf[sample_first ? 0 : 1]->sample(ctx2, si, sample1, sample2, active);
result *= weight;
return { bs, result };
dr::masked(ctx2.component, !sample_first) -= (uint32_t) m_nested_bsdf[0]->component_count();
dr::masked(weight, sample_first) = 1.f - weight;
auto [bs_, result_] = dr::select(sample_first,
m_nested_bsdf[0]->sample(ctx2, si, sample1, sample2, active),
m_nested_bsdf[1]->sample(ctx2, si, sample1, sample2, active));
dr::masked(bs, !sample_all) = bs_;
dr::masked(result, !sample_all) = result_ * weight;
}

BSDFSample3f bs = dr::zeros<BSDFSample3f>();
Spectrum result(0.f);

Mask m0 = active && sample1 > weight,
m1 = active && sample1 <= weight;
Mask m0 = active && sample1 > weight && sample_all,
m1 = active && sample1 <= weight && sample_all;

if (dr::any_or<true>(m0)) {
auto [bs0, result0] = m_nested_bsdf[0]->sample(
Expand All @@ -155,36 +158,57 @@ class BlendBSDF final : public BSDF<Float, Spectrum> {
const Vector3f &wo, Mask active) const override {
MI_MASKED_FUNCTION(ProfilerPhase::BSDFEvaluate, active);

Spectrum result(0.f);

Mask sample_all = dr::eq(ctx.component, (uint32_t) -1);
Float weight = eval_weight(si, active);
if (unlikely(ctx.component != (uint32_t) -1)) {
bool sample_first = ctx.component < m_nested_bsdf[0]->component_count();

if (dr::any_or<true>(!sample_all)) {
Mask sample_first = ctx.component < m_nested_bsdf[0]->component_count();
BSDFContext ctx2(ctx);
if (!sample_first)
ctx2.component -= (uint32_t) m_nested_bsdf[0]->component_count();
else
weight = 1.f - weight;
return weight * m_nested_bsdf[sample_first ? 0 : 1]->eval(ctx2, si, wo, active);
dr::masked(ctx2.component, !sample_first) -= (uint32_t) m_nested_bsdf[0]->component_count();
dr::masked(weight, sample_first) = 1.f - weight;
dr::masked(result, !sample_all) =
weight * dr::select(sample_first,
m_nested_bsdf[0]->eval(ctx2, si, wo, active),
m_nested_bsdf[1]->eval(ctx2, si, wo, active));
}

return m_nested_bsdf[0]->eval(ctx, si, wo, active) * (1 - weight) +
m_nested_bsdf[1]->eval(ctx, si, wo, active) * weight;
if (dr::any_or<true>(sample_all)) {
dr::masked(result, sample_all) =
m_nested_bsdf[0]->eval(ctx, si, wo, active) * (1 - weight) +
m_nested_bsdf[1]->eval(ctx, si, wo, active) * weight;
}

return result;
}

Float pdf(const BSDFContext &ctx, const SurfaceInteraction3f &si,
const Vector3f &wo, Mask active) const override {
MI_MASKED_FUNCTION(ProfilerPhase::BSDFEvaluate, active);

if (unlikely(ctx.component != (uint32_t) -1)) {
bool sample_first = ctx.component < m_nested_bsdf[0]->component_count();
Float result(0.f);

Mask sample_all = dr::eq(ctx.component, (uint32_t) -1);

if (dr::any_or<true>(!sample_all)) {
Mask sample_first = ctx.component < m_nested_bsdf[0]->component_count();
BSDFContext ctx2(ctx);
if (!sample_first)
ctx2.component -= (uint32_t) m_nested_bsdf[0]->component_count();
return m_nested_bsdf[sample_first ? 0 : 1]->pdf(ctx2, si, wo, active);
dr::masked(ctx2.component, !sample_first) -= (uint32_t) m_nested_bsdf[0]->component_count();
dr::masked(result, !sample_all) =
dr::select(sample_first,
m_nested_bsdf[0]->pdf(ctx2, si, wo, active),
m_nested_bsdf[1]->pdf(ctx2, si, wo, active));
}

Float weight = eval_weight(si, active);
return m_nested_bsdf[0]->pdf(ctx, si, wo, active) * (1 - weight) +
m_nested_bsdf[1]->pdf(ctx, si, wo, active) * weight;
if (dr::any_or<true>(sample_all)) {
Float weight = eval_weight(si, active);
dr::masked(result, sample_all) =
m_nested_bsdf[0]->pdf(ctx, si, wo, active) * (1 - weight) +
m_nested_bsdf[1]->pdf(ctx, si, wo, active) * weight;
}

return result;
}

std::pair<Spectrum, Float> eval_pdf(const BSDFContext &ctx,
Expand All @@ -193,24 +217,33 @@ class BlendBSDF final : public BSDF<Float, Spectrum> {
Mask active) const override {
MI_MASKED_FUNCTION(ProfilerPhase::BSDFEvaluate, active);

Spectrum val(0.f);
Float pdf(0.f);

Mask sample_all = dr::eq(ctx.component, (uint32_t) -1);
Float weight = eval_weight(si, active);
if (unlikely(ctx.component != (uint32_t) -1)) {
bool sample_first = ctx.component < m_nested_bsdf[0]->component_count();
BSDFContext ctx2(ctx);
if (!sample_first)
ctx2.component -= (uint32_t) m_nested_bsdf[0]->component_count();
else
weight = 1.f - weight;

auto [val, pdf] = m_nested_bsdf[sample_first ? 0 : 1]->eval_pdf(ctx2, si, wo, active);
return { weight * val, pdf };
if (dr::any_or<true>(!sample_all)) {
Mask sample_first = ctx.component < m_nested_bsdf[0]->component_count();
BSDFContext ctx2(ctx);
dr::masked(ctx2.component, !sample_first) -= (uint32_t) m_nested_bsdf[0]->component_count();
dr::masked(weight, sample_first) = 1.f - weight;
auto [val_, pdf_] =
dr::select(sample_first,
m_nested_bsdf[0]->eval_pdf(ctx2, si, wo, active),
m_nested_bsdf[1]->eval_pdf(ctx2, si, wo, active));
dr::masked(val, !sample_all) = weight * val_;
dr::masked(pdf, !sample_all) = pdf_;
}

auto [val_0, pdf_0] = m_nested_bsdf[0]->eval_pdf(ctx, si, wo, active);
auto [val_1, pdf_1] = m_nested_bsdf[1]->eval_pdf(ctx, si, wo, active);
if (dr::any_or<true>(sample_all)) {
auto [val_0, pdf_0] = m_nested_bsdf[0]->eval_pdf(ctx, si, wo, active);
auto [val_1, pdf_1] = m_nested_bsdf[1]->eval_pdf(ctx, si, wo, active);
dr::masked(val, sample_all) = val_0 * (1 - weight) + val_1 * weight;
dr::masked(pdf, sample_all) = pdf_0 * (1 - weight) + pdf_1 * weight;
}

return { val_0 * (1 - weight) + val_1 * weight,
pdf_0 * (1 - weight) + pdf_1 * weight };
return { val, pdf };
}

MI_INLINE Float eval_weight(const SurfaceInteraction3f &si, const Mask &active) const {
Expand Down
5 changes: 4 additions & 1 deletion src/bsdfs/conductor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,10 @@ class SmoothConductor final : public BSDF<Float, Spectrum> {

BSDFSample3f bs = dr::zeros<BSDFSample3f>();
Spectrum value(0.f);
if (unlikely(dr::none_or<false>(active) || !ctx.is_enabled(BSDFFlags::DeltaReflection)))

active &= ctx.is_enabled(+BSDFFlags::DeltaReflection);

if (unlikely(dr::none_or<false>(active)))
return { bs, value };

bs.sampled_component = 0;
Expand Down
Loading

0 comments on commit 2808967

Please sign in to comment.