Directly specify bucket size instead of inferring from sample count.

Since we aren't doing breadth-first ray tracing anymore, this makes
a lot more sense.
This commit is contained in:
Nathan Vegdahl 2022-08-02 19:41:23 -07:00
parent 72b8397e9d
commit 7c750dcded
5 changed files with 30 additions and 44 deletions

View File

@ -40,9 +40,9 @@ class RenderPsychopathSettingsScene(PropertyGroup):
min=1, max=65536, default=16 min=1, max=65536, default=16
) )
max_samples_per_bucket = IntProperty( bucket_size = IntProperty(
name="Max Samples Per Bucket", description="How many samples to simultaneously calculate per thread; indirectly determines bucket size", name="Bucket Size", description="The height and width of each render bucket in pixels.",
min=1, max=2**28, soft_max=2**16, default=4096 min=1, max=4096, soft_max=256, default=32
) )
dicing_rate = FloatProperty( dicing_rate = FloatProperty(

View File

@ -45,9 +45,9 @@ class PsychopathRender(bpy.types.RenderEngine):
if crop != None: if crop != None:
args += ["--crop", str(crop[0]), str(self.size_y - crop[3]), str(crop[2] - 1), str(self.size_y - crop[1] - 1)] args += ["--crop", str(crop[0]), str(self.size_y - crop[3]), str(crop[2] - 1), str(self.size_y - crop[1] - 1)]
if use_stdin: if use_stdin:
args += ["--spb", str(scene.psychopath.max_samples_per_bucket), "--serialized_output", "--use_stdin"] args += ["--bucket_size", str(scene.psychopath.bucket_size), "--serialized_output", "--use_stdin"]
else: else:
args += ["--spb", str(scene.psychopath.max_samples_per_bucket), "--serialized_output", "-i", psy_filepath] args += ["--bucket_size", str(scene.psychopath.bucket_size), "--serialized_output", "-i", psy_filepath]
# Start Rendering! # Start Rendering!
try: try:

View File

@ -47,7 +47,7 @@ class RENDER_PT_psychopath_render_settings(PsychopathPanel, bpy.types.Panel):
col.prop(scene.psychopath, "shutter_end") col.prop(scene.psychopath, "shutter_end")
col.label(text="Performance") col.label(text="Performance")
col.prop(scene.psychopath, "max_samples_per_bucket") col.prop(scene.psychopath, "bucket_size")
class RENDER_PT_psychopath_export_settings(PsychopathPanel, bpy.types.Panel): class RENDER_PT_psychopath_export_settings(PsychopathPanel, bpy.types.Panel):

View File

@ -89,11 +89,11 @@ fn main() {
}), }),
) )
.arg( .arg(
Arg::with_name("max_bucket_samples") Arg::with_name("bucket_size")
.short("b") .short("b")
.long("spb") .long("bucket_size")
.value_name("N") .value_name("N")
.help("Target number of samples per bucket (determines bucket size)") .help("Height and width of each render bucket in pixels.")
.takes_value(true) .takes_value(true)
.validator(|s| { .validator(|s| {
usize::from_str(&s) usize::from_str(&s)
@ -258,12 +258,11 @@ fn main() {
r.spp = usize::from_str(spp).unwrap(); r.spp = usize::from_str(spp).unwrap();
} }
let max_samples_per_bucket = let bucket_size = if let Some(bucket_size) = args.value_of("bucket_size") {
if let Some(max_samples_per_bucket) = args.value_of("max_bucket_samples") { u32::from_str(bucket_size).unwrap()
u32::from_str(max_samples_per_bucket).unwrap() } else {
} else { 32
4096 };
};
let thread_count = if let Some(threads) = args.value_of("threads") { let thread_count = if let Some(threads) = args.value_of("threads") {
u32::from_str(threads).unwrap() u32::from_str(threads).unwrap()
@ -279,7 +278,7 @@ fn main() {
println!("Rendering scene with {} threads...", thread_count); println!("Rendering scene with {} threads...", thread_count);
} }
let (mut image, rstats) = r.render( let (mut image, rstats) = r.render(
max_samples_per_bucket, bucket_size,
crop, crop,
thread_count, thread_count,
args.is_present("serialized_output"), args.is_present("serialized_output"),

View File

@ -59,7 +59,7 @@ impl RenderStats {
impl<'a> Renderer<'a> { impl<'a> Renderer<'a> {
pub fn render( pub fn render(
&self, &self,
max_samples_per_bucket: u32, bucket_size: u32,
crop: Option<(u32, u32, u32, u32)>, crop: Option<(u32, u32, u32, u32)>,
thread_count: u32, thread_count: u32,
do_blender_output: bool, do_blender_output: bool,
@ -82,13 +82,13 @@ impl<'a> Renderer<'a> {
// Calculate dimensions and coordinates of what we're rendering. This // Calculate dimensions and coordinates of what we're rendering. This
// accounts for cropping. // accounts for cropping.
let (width, height, start_x, start_y) = if let Some((x1, y1, x2, y2)) = crop { let (width, height, start_x, start_y) = if let Some((x1, y1, x2, y2)) = crop {
let x1 = min(x1 as usize, img_width - 1); let x1 = min(x1, img_width as u32 - 1);
let y1 = min(y1 as usize, img_height - 1); let y1 = min(y1, img_height as u32 - 1);
let x2 = min(x2 as usize, img_width - 1); let x2 = min(x2, img_width as u32 - 1);
let y2 = min(y2 as usize, img_height - 1); let y2 = min(y2, img_height as u32 - 1);
(x2 - x1 + 1, y2 - y1 + 1, x1, y1) (x2 - x1 + 1, y2 - y1 + 1, x1, y1)
} else { } else {
(img_width, img_height, 0, 0) (img_width as u32, img_height as u32, 0, 0)
}; };
// Render // Render
@ -105,7 +105,7 @@ impl<'a> Renderer<'a> {
jq, jq,
ajq, ajq,
img, img,
width * height, width as usize * height as usize,
pixrenref, pixrenref,
cstats, cstats,
do_blender_output, do_blender_output,
@ -117,23 +117,10 @@ impl<'a> Renderer<'a> {
print!("0.00%"); print!("0.00%");
let _ = io::stdout().flush(); let _ = io::stdout().flush();
// Determine bucket size based on the per-thread maximum number of samples to
// calculate at a time.
let (bucket_w, bucket_h) = {
let target_pixels_per_bucket = max_samples_per_bucket as f64 / self.spp as f64;
let target_bucket_dim = if target_pixels_per_bucket.sqrt() < 1.0 {
1usize
} else {
target_pixels_per_bucket.sqrt() as usize
};
(target_bucket_dim, target_bucket_dim)
};
// Populate job queue // Populate job queue
let bucket_n = { let bucket_n = {
let bucket_count_x = ((width / bucket_w) + 1) as u32; let bucket_count_x = (width / bucket_size) + 1;
let bucket_count_y = ((height / bucket_h) + 1) as u32; let bucket_count_y = (height / bucket_size) + 1;
let larger = cmp::max(bucket_count_x, bucket_count_y); let larger = cmp::max(bucket_count_x, bucket_count_y);
let pow2 = upper_power_of_two(larger); let pow2 = upper_power_of_two(larger);
pow2 * pow2 pow2 * pow2
@ -141,17 +128,17 @@ impl<'a> Renderer<'a> {
for hilbert_d in 0..bucket_n { for hilbert_d in 0..bucket_n {
let (bx, by) = hilbert::decode(hilbert_d); let (bx, by) = hilbert::decode(hilbert_d);
let x = bx as usize * bucket_w; let x = bx * bucket_size;
let y = by as usize * bucket_h; let y = by * bucket_size;
let w = if width >= x { let w = if width >= x {
min(bucket_w, width - x) min(bucket_size, width - x)
} else { } else {
bucket_w bucket_size
}; };
let h = if height >= y { let h = if height >= y {
min(bucket_h, height - y) min(bucket_size, height - y)
} else { } else {
bucket_h bucket_size
}; };
if x < width && y < height && w > 0 && h > 0 { if x < width && y < height && w > 0 && h > 0 {
job_queue.push(BucketJob { job_queue.push(BucketJob {