Skip to content
14 changes: 0 additions & 14 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,27 +41,13 @@ if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
"Debug" "Release" "MinSizeRel" "RelWithDebInfo")
endif()

if(NOT OUTPUT_WIDTH)
message(STATUS "Setting output width to 800 as none was specified.")
set(OUTPUT_WIDTH "800" CACHE
STRING "Image width in pixel" FORCE)
endif()

if(NOT OUTPUT_HEIGHT)
message(STATUS "Setting output height to 480 as none was specified.")
set(OUTPUT_HEIGHT "480" CACHE
STRING "Image height in pixel" FORCE)
endif()


set(SYCL_RT_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src)
set(SYCL_RT_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include)

add_executable(sycl-rt ${SYCL_RT_SRC_DIR}/main.cpp)

target_include_directories(sycl-rt PRIVATE ${SYCL_RT_INCLUDE_DIR})
target_compile_definitions(sycl-rt PRIVATE OUTPUT_WIDTH=${OUTPUT_WIDTH})
target_compile_definitions(sycl-rt PRIVATE OUTPUT_HEIGHT=${OUTPUT_HEIGHT})

# This is a SYCL program
if ("${SYCL_CXX_COMPILER}" STREQUAL "")
Expand Down
4 changes: 2 additions & 2 deletions include/box.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class box {
}

/// Compute ray interaction with the box
bool hit(auto& ctx, const ray& r, real_t min, real_t max, hit_record& rec,
bool hit(const ray& r, real_t min, real_t max, hit_record& rec,
material_t& hit_material_type) const {
hit_record temp_rec;
material_t temp_material_type;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have the feeling that if we remove the std::monostate from the material it will always create a sphere here even when there is no intersection.

Expand All @@ -36,7 +36,7 @@ class box {
for (const auto& side : sides) {
if (dev_visit(
[&](auto&& arg) {
return arg.hit(ctx, r, min, closest_so_far, temp_rec,
return arg.hit(r, min, closest_so_far, temp_rec,
temp_material_type);
},
side)) {
Expand Down
4 changes: 3 additions & 1 deletion include/build_parameters.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@ constexpr bool use_sycl_compiler = USE_SYCL_COMPILER;
constexpr bool use_sycl_compiler = false;
#endif

constexpr int output_width = OUTPUT_WIDTH;
/*constexpr int output_width = OUTPUT_WIDTH;
constexpr int output_height = OUTPUT_HEIGHT;
constexpr int samples = SAMPLES;
constexpr int depth = DEPTH;//*/
} // namespace buildparams

#endif // BUILD_PARAMETERS_HPP
2 changes: 1 addition & 1 deletion include/camera.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ class camera {
return { origin + offset,
lower_left_corner + s * horizontal + t * vertical - origin -
offset,
rng.float_t(time0, time1) };
time0 };
}
};

Expand Down
11 changes: 5 additions & 6 deletions include/constant_medium.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,24 +25,22 @@ class constant_medium {
, neg_inv_density { -1 / d }
, phase_function { isotropic_material { a } } {}

bool hit(auto& ctx, const ray& r, real_t min, real_t max, hit_record& rec,
bool hit(const ray& r, real_t min, real_t max, hit_record& rec,
material_t& hit_material_type) const {
auto& rng = ctx.rng;
hit_material_type = phase_function;
material_t temp_material_type;
hit_record rec1, rec2;
if (!dev_visit(
[&](auto&& arg) {
return arg.hit(ctx, r, -infinity, infinity, rec1,
Comment thread
lforg37 marked this conversation as resolved.
return arg.hit(r, -infinity, infinity, rec1,
temp_material_type);
},
boundary)) {
return false;
}

if (!dev_visit(
[&](auto&& arg) {
return arg.hit(ctx, r, rec1.t + 0.0001f, infinity, rec2,
return arg.hit(r, rec1.t + 0.0001f, infinity, rec2,
temp_material_type);
},
boundary)) {
Expand All @@ -62,7 +60,8 @@ class constant_medium {
/// Distance between the two hitpoints affect of probability
/// of the ray hitting a smoke particle
const auto distance_inside_boundary = (rec2.t - rec1.t) * ray_length;
const auto hit_distance = neg_inv_density * sycl::log(rng.float_t());
auto rng = LocalPseudoRNG { toseed(r.direction()) };

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I realize you have removed the context passed everywhere and replaced basically the random generator with some local computation.
What was the rationale?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As getting a value from the RNG update its internal state, having a shared RNG creates a very long chain of read after write dependency that prevent the HLS compiler to parallelize the otherwise independent computation steps.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps we could have this context with some special HLS decorations to ignore some dependencies.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Otherwise, perhaps something like this pseudo HLS-SYCL code:

auto rng(auto local_seed = std::source_location::current()) {
  return [=] {
     static auto state = local_seed.line();
     #pragma HLS dependence variable=state inter false
     state = crunch(state);
     return mix(state);
  };
}

or

auto rng(auto local_seed = std::source_location::current()) {
  return [state = local_seed.line()] mutable {
     #pragma HLS dependence variable=state inter false
     state = crunch(state);
     return mix(state);
  };
}

Perhaps we need extension intel/llvm#3746 to have the big picture working.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@aisoard, @yu810226 any feedback?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Above is basically a good idea, if I understand the intention, to separate the state into multiple independent RNGs. I'm not sure what you're trying to achieve with the false dependence pragma, however.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stephenneuendorffer yes this is the idea to distribute the state here in a lazy way to even initialize the seed with something depending from the source location (here with the line number, we could also use the file name, etc.).
I has put probably too much here with the

#pragma HLS dependence variable=state inter false

as a way to have an II=1 without consuming too much latency at the price of a semantics change in the code and hoping we still have enough randomness...
But I agree this is a second order optimization if we are still in trouble...
Perhaps this code will not work with SYCL-HLS because it uses some function pointer. If so, we can try with a macro to avoid returning the lambda, or perhaps just have a macro which inline a random generator wherever we want one... Ahem... :-)

const auto hit_distance = neg_inv_density * sycl::log(rng.real());

/// With lower density, hit_distance has higher probabilty
/// of being greater than distance_inside_boundary
Expand Down
23 changes: 23 additions & 0 deletions include/hit_record.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#ifndef HIT_RECORD_HPP
#define HIT_RECORD_HPP

#include "rtweekend.hpp"

class hit_record {
public:
real_t t; //
point p; // hit point
vec normal; // normal at hit point
bool front_face; // to check if hit point is on the outer surface
/*local coordinates for rectangles
and mercator coordintes for spheres */
real_t u;
real_t v;

// To set if the hit point is on the front face
Comment on lines +10 to +17

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While you are here, add more Doxygen

Suggested change
point p; // hit point
vec normal; // normal at hit point
bool front_face; // to check if hit point is on the outer surface
/*local coordinates for rectangles
and mercator coordinates for spheres */
real_t u;
real_t v;
// To set if the hit point is on the front face
point p; ///< Hit point
vec normal; ///< Normal at hit point
bool front_face; ///< To check if hit point is on the outer surface
/// Local coordinates for rectangles and mercator coordinates for spheres
real_t u;
real_t v;
/// To set if the hit point is on the front face

void set_face_normal(const ray& r, const vec& outward_normal) {
front_face = dot(r.direction(), outward_normal) < 0;
normal = front_face ? outward_normal : vec {} - outward_normal;
}
};
#endif

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing end-of-line.
Yes, this is good to have this in its own file.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious... An IDE configuration bug?

25 changes: 5 additions & 20 deletions include/hitable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,10 @@
#define HITTABLE_H

#include "ray.hpp"
#include "rtweekend.hpp"
#include "vec.hpp"

class hit_record {
public:
float t; //
point p; // hit point
vec normal; // normal at hit point
bool front_face; // to check if hit point is on the outer surface
/*local coordinates for rectangles
and mercator coordintes for spheres */
float u;
float v;

// To set if the hit point is on the front face
void set_face_normal(const ray& r, const vec& outward_normal) {
front_face = dot(r.direction(), outward_normal) < 0;
normal = front_face ? outward_normal : vec {} - outward_normal;
}
};
#include "sphere.hpp"
#include "triangle.hpp"
#include "box.hpp"
#include "constant_medium.hpp"
Comment thread
lforg37 marked this conversation as resolved.
Outdated

using hittable_t = std::variant<sphere, triangle, constant_medium, box>;
#endif
58 changes: 28 additions & 30 deletions include/material.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

#include <iostream>

#include "hitable.hpp"
#include "hit_record.hpp"
#include "texture.hpp"
#include "vec.hpp"
#include "visit.hpp"
Expand All @@ -15,30 +15,31 @@ struct lambertian_material {
lambertian_material(const texture_t& a)
: albedo { a } {}

bool scatter(auto& ctx, const ray& r_in, const hit_record& rec,
color& attenuation, ray& scattered) const {
auto& rng = ctx.rng;
bool scatter(const ray& r_in, const hit_record& rec, color& attenuation,
ray& scattered) const {
auto rng = LocalPseudoRNG { toseed(rec.normal) };
vec scatter_direction = rec.normal + rng.unit_vec();
scattered = ray(rec.p, scatter_direction, r_in.time());
// Attenuation of the ray hitting the object is modified based on the color
// at hit point
attenuation *=
dev_visit([&](auto&& arg) { return arg.value(ctx, rec); }, albedo);
dev_visit([&](auto&& t) { return t.value(rec); },
albedo);
return true;
}
color emitted(auto&, const hit_record& rec) { return color(0, 0, 0); }
color emitted(const hit_record& rec) { return color(0.f, 0.f, 0.f); }
texture_t albedo;
};

struct metal_material {
metal_material() = default;
metal_material(const color& a, float f)
metal_material(const color& a, real_t f)
: albedo { a }
, fuzz { std::clamp(f, 0.0f, 1.0f) } {}

bool scatter(auto& ctx, const ray& r_in, const hit_record& rec,
bool scatter(const ray& r_in, const hit_record& rec,
color& attenuation, ray& scattered) const {
auto& rng = ctx.rng;
auto rng = LocalPseudoRNG { toseed(rec.normal) };
vec reflected = reflect(unit_vector(r_in.direction()), rec.normal);
scattered = ray(rec.p, reflected + fuzz * rng.in_unit_ball(), r_in.time());
// Attenuation of the ray hitting the object is modified based on the color
Expand All @@ -47,9 +48,9 @@ struct metal_material {
return (dot(scattered.direction(), rec.normal) > 0);
}

color emitted(auto&, const hit_record& rec) { return color(0, 0, 0); }
color emitted(const hit_record& rec) { return color(0, 0, 0); }
color albedo;
float fuzz;
real_t fuzz;
};

struct dielectric_material {
Expand All @@ -65,20 +66,19 @@ struct dielectric_material {
return r0 + (1 - r0) * sycl::pow((1 - cosine), 5.0f);
}

bool scatter(auto& ctx, const ray& r_in, const hit_record& rec,
bool scatter(const ray& r_in, const hit_record& rec,
color& attenuation, ray& scattered) const {
// Attenuation of the ray hitting the object is modified based on the color
// at hit point
auto& rng = ctx.rng;
auto rng = LocalPseudoRNG { toseed(rec.normal) };
attenuation *= albedo;
float refraction_ratio = rec.front_face ? (1.0f / ref_idx) : ref_idx;
real_t refraction_ratio = rec.front_face ? (1.0f / ref_idx) : ref_idx;
vec unit_direction = unit_vector(r_in.direction());
float cos_theta = sycl::fmin(-sycl::dot(unit_direction, rec.normal), 1.0f);
float sin_theta = sycl::sqrt(1.0f - cos_theta * cos_theta);
real_t cos_theta = sycl::fmin(-sycl::dot(unit_direction, rec.normal), 1.0f);
real_t sin_theta = sycl::sqrt(1.0f - cos_theta * cos_theta);
bool cannot_refract = refraction_ratio * sin_theta > 1.0f;
vec direction;
if (cannot_refract ||
reflectance(cos_theta, refraction_ratio) > rng.float_t())
if (cannot_refract || reflectance(cos_theta, refraction_ratio) > rng.real())
direction = reflect(unit_direction, rec.normal);
else
direction = refract(unit_direction, rec.normal, refraction_ratio);
Expand All @@ -87,7 +87,7 @@ struct dielectric_material {
return true;
}

color emitted(auto&, const hit_record& rec) { return color(0, 0, 0); }
color emitted(const hit_record& rec) { return color(0, 0, 0); }
// Refractive index of the glass
real_t ref_idx;
// Color of the glass
Expand All @@ -103,8 +103,8 @@ struct lightsource_material {

template <typename... T> bool scatter(T&...) const { return false; }

color emitted(auto& ctx, const hit_record& rec) {
return dev_visit([&](auto&& arg) { return arg.value(ctx, rec); }, emit);
color emitted(const hit_record& rec) {
return dev_visit([&](auto&& t) { return t.value(rec); }, emit);
}

texture_t emit;
Expand All @@ -116,22 +116,20 @@ struct isotropic_material {
isotropic_material(texture_t& a)
: albedo { a } {}

bool scatter(auto& ctx, const ray& r_in, const hit_record& rec,
color& attenuation, ray& scattered) const {
auto& rng = ctx.rng;
bool scatter(const ray& r_in, const hit_record& rec, color& attenuation,
ray& scattered) const {
LocalPseudoRNG rng(toseed(r_in.direction()));
scattered = ray(rec.p, rng.in_unit_ball(), r_in.time());
attenuation *=
dev_visit([&](auto&& arg) { return arg.value(ctx, rec); }, albedo);
attenuation *= dev_visit([&](auto&& t) { return t.value(rec); }, albedo);
return true;
}

color emitted(auto&, const hit_record& rec) { return color(0, 0, 0); }
color emitted(const hit_record& rec) { return color(0, 0, 0); }

texture_t albedo;
};

using material_t =
std::variant<lambertian_material, metal_material, dielectric_material,
lightsource_material, isotropic_material>;

std::variant<lambertian_material, metal_material,
dielectric_material, lightsource_material, isotropic_material>;
#endif
2 changes: 1 addition & 1 deletion include/ray.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class ray {

// returns point along the ray at distance t from ray's origin
// the ray P(t) = Origin + t*direction
point at(float t) const { return orig + t * dir; }
point at(real_t t) const { return orig + t * dir; }

public:
// To store the origin and direction of the ray
Expand Down
6 changes: 3 additions & 3 deletions include/rectangle.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class xy_rect {
, material_type { mat_type } {}

/// Compute ray interaction with rectangle
bool hit(auto&, const ray& r, real_t min, real_t max, hit_record& rec,
bool hit(const ray& r, real_t min, real_t max, hit_record& rec,
material_t& hit_material_type) const {
hit_material_type = material_type;

Expand Down Expand Up @@ -66,7 +66,7 @@ class xz_rect {
, material_type { mat_type } {}

/// Compute ray interaction with rectangle
bool hit(auto&, const ray& r, real_t min, real_t max, hit_record& rec,
bool hit(const ray& r, real_t min, real_t max, hit_record& rec,
material_t& hit_material_type) const {
hit_material_type = material_type;

Expand Down Expand Up @@ -104,7 +104,7 @@ class yz_rect {
, material_type { mat_type } {}

/// Compute ray interaction with rectangle
bool hit(auto&, const ray& r, real_t min, real_t max, hit_record& rec,
bool hit(const ray& r, real_t min, real_t max, hit_record& rec,
material_t& hit_material_type) const {
hit_material_type = material_type;

Expand Down
Loading