From 0e8d708ff0316504bb6f495b42044c55ef4c0451 Mon Sep 17 00:00:00 2001 From: Nathan Vegdahl Date: Sun, 16 Oct 2016 14:55:00 -0700 Subject: [PATCH] Made samples per bucket configurable. --- psychoblend/__init__.py | 13 ++++++--- psychoblend/render.py | 2 +- psychoblend/ui.py | 59 ++++++++++++++++++++++------------------- src/main.rs | 10 ++++++- src/renderer.rs | 10 +++---- 5 files changed, 54 insertions(+), 40 deletions(-) diff --git a/psychoblend/__init__.py b/psychoblend/__init__.py index 45666c3..4fa63d8 100644 --- a/psychoblend/__init__.py +++ b/psychoblend/__init__.py @@ -40,6 +40,11 @@ class RenderPsychopathSettingsScene(PropertyGroup): min=1, max=65536, default=16 ) + max_samples_per_bucket = IntProperty( + name="Max Samples Per Bucket", description="How many samples to simultaneously calculate per thread; indirectly determines bucket size", + min=1, max=2**28, soft_max=2**16, default=4096 + ) + dicing_rate = FloatProperty( name="Dicing Rate", description="The target microgeometry width in pixels", min=0.0001, max=100.0, soft_min=0.125, soft_max=1.0, default=0.25 @@ -86,24 +91,24 @@ class PsychopathMaterial(bpy.types.PropertyGroup): items=[('Emit', 'Emit', ""), ('Lambert', 'Lambert', ""), ('GTR', 'GTR', "")], default="Lambert" ) - + color = FloatVectorProperty( name="Color", description="", subtype='COLOR', min=0.0, soft_min=0.0, soft_max = 1.0, default=[0.8,0.8,0.8] ) - + roughness = FloatProperty( name="Roughness", description="", min=-1.0, max=1.0, soft_min=0.0, soft_max=1.0, default=0.1 ) - + tail_shape = FloatProperty( name="Tail Shape", description="", min=0.0, max=8.0, soft_min=1.0, soft_max=3.0, default=2.0 ) - + fresnel = FloatProperty( name="Fresnel", description="", min=0.0, max=1.0, soft_min=0.0, soft_max=1.0, default=0.9 diff --git a/psychoblend/render.py b/psychoblend/render.py index 72f31b3..f70713f 100644 --- a/psychoblend/render.py +++ b/psychoblend/render.py @@ -49,7 +49,7 @@ class PsychopathRender(bpy.types.RenderEngine): return False # TODO: figure out command line options - args = ["-i", psy_filepath] + args = ["--spb", str(scene.psychopath.max_samples_per_bucket), "-i", psy_filepath] # Start Rendering! try: diff --git a/psychoblend/ui.py b/psychoblend/ui.py index 0b0c452..d96ca4e 100644 --- a/psychoblend/ui.py +++ b/psychoblend/ui.py @@ -46,6 +46,9 @@ class RENDER_PT_psychopath_render_settings(PsychopathPanel, bpy.types.Panel): col.prop(scene.psychopath, "shutter_start") col.prop(scene.psychopath, "shutter_end") + col.label(text="Performance") + col.prop(scene.psychopath, "max_samples_per_bucket") + class RENDER_PT_psychopath_export_settings(PsychopathPanel, bpy.types.Panel): bl_label = "Export Settings" @@ -66,14 +69,14 @@ class WORLD_PT_psychopath_background(PsychopathPanel, bpy.types.Panel): bl_space_type = 'PROPERTIES' bl_region_type = 'WINDOW' bl_context = "world" - + @classmethod def poll(cls, context): return context.world and PsychopathPanel.poll(context) - + def draw(self, context): layout = self.layout - + world = context.world layout.prop(world, "horizon_color", text="Color") @@ -131,22 +134,22 @@ class DATA_PT_psychopath_area_lamp(PsychopathPanel, bpy.types.Panel): bl_space_type = 'PROPERTIES' bl_region_type = 'WINDOW' bl_context = "data" - + @classmethod def poll(cls, context): lamp = context.lamp engine = context.scene.render.engine return (lamp and lamp.type == 'AREA') and (engine in cls.COMPAT_ENGINES) - + def draw(self, context): layout = self.layout - + lamp = context.lamp - + col = layout.column() col.row().prop(lamp, "shape", expand=True) sub = col.row(align=True) - + if lamp.shape == 'SQUARE': sub.prop(lamp, "size") elif lamp.shape == 'RECTANGLE': @@ -159,19 +162,19 @@ class DATA_PT_psychopath_mesh(PsychopathPanel, bpy.types.Panel): bl_space_type = 'PROPERTIES' bl_region_type = 'WINDOW' bl_context = "data" - + @classmethod def poll(cls, context): engine = context.scene.render.engine return context.mesh and (engine in cls.COMPAT_ENGINES) - + def draw(self, context): layout = self.layout - + mesh = context.mesh - + layout.row().prop(mesh.psychopath, "is_subdivision_surface") - + class MATERIAL_PT_psychopath_context_material(PsychopathPanel, bpy.types.Panel): bl_label = "" @@ -179,42 +182,42 @@ class MATERIAL_PT_psychopath_context_material(PsychopathPanel, bpy.types.Panel): bl_region_type = "WINDOW" bl_context = "material" bl_options = {'HIDE_HEADER'} - + @classmethod def poll(cls, context): return (context.material or context.object) and PsychopathPanel.poll(context) - + def draw(self, context): layout = self.layout - + mat = context.material ob = context.object slot = context.material_slot space = context.space_data - + if ob: row = layout.row() - + row.template_list("MATERIAL_UL_matslots", "", ob, "material_slots", ob, "active_material_index", rows=1) - + col = row.column(align=True) col.operator("object.material_slot_add", icon='ZOOMIN', text="") col.operator("object.material_slot_remove", icon='ZOOMOUT', text="") - + col.menu("MATERIAL_MT_specials", icon='DOWNARROW_HLT', text="") - + if ob.mode == 'EDIT': row = layout.row(align=True) row.operator("object.material_slot_assign", text="Assign") row.operator("object.material_slot_select", text="Select") row.operator("object.material_slot_deselect", text="Deselect") - + split = layout.split(percentage=0.65) - + if ob: split.template_ID(ob, "active_material", new="material.new") row = split.row() - + if slot: row.prop(slot, "link", text="") else: @@ -229,18 +232,18 @@ class MATERIAL_PT_psychopath_surface(PsychopathPanel, bpy.types.Panel): bl_space_type = "PROPERTIES" bl_region_type = "WINDOW" bl_context = "material" - + @classmethod def poll(cls, context): return context.material and PsychopathPanel.poll(context) - + def draw(self, context): layout = self.layout - + mat = context.material layout.prop(mat.psychopath, "surface_shader_type") layout.prop(mat.psychopath, "color") - + if mat.psychopath.surface_shader_type == 'GTR': layout.prop(mat.psychopath, "roughness") layout.prop(mat.psychopath, "tail_shape") diff --git a/src/main.rs b/src/main.rs index 06145d1..1e5e6aa 100644 --- a/src/main.rs +++ b/src/main.rs @@ -72,6 +72,7 @@ Usage: Options: -i , --input Input .psy file. -s , --spp Number of samples per pixel. + -b , --spb Maxmimum number of samples per bucket (determines bucket size). -t , --threads Number of threads to render with. Defaults to the number of logical cores on the system. --dev Show useful dev/debug info. @@ -83,6 +84,7 @@ Options: struct Args { flag_input: Option, flag_spp: Option, + flag_spb: Option, flag_threads: Option, flag_dev: bool, flag_version: bool, @@ -141,6 +143,12 @@ fn main() { r.spp = spp; } + let max_samples_per_bucket = if let Some(max_samples_per_bucket) = args.flag_spb { + max_samples_per_bucket as u32 + } else { + 4096 + }; + let thread_count = if let Some(threads) = args.flag_threads { threads as u32 } else { @@ -150,7 +158,7 @@ fn main() { println!("\tBuilt scene in {:.3}s", t.tick()); println!("Rendering scene with {} threads...", thread_count); - let mut image = r.render(thread_count); + let mut image = r.render(max_samples_per_bucket, thread_count); println!("\tRendered scene in {:.3}s", t.tick()); println!("Writing image to disk..."); diff --git a/src/renderer.rs b/src/renderer.rs index f66f3a9..d8a78c3 100644 --- a/src/renderer.rs +++ b/src/renderer.rs @@ -31,7 +31,7 @@ pub struct Renderer { } impl Renderer { - pub fn render(&self, thread_count: u32) -> Image { + pub fn render(&self, max_samples_per_bucket: u32, thread_count: u32) -> Image { let mut tpool = Pool::new(thread_count); let image = Image::new(self.resolution.0, self.resolution.1); @@ -174,12 +174,10 @@ impl Renderer { print!("0.00%"); let _ = io::stdout().flush(); - // Determine bucket size based on a target number of samples - // per bucket. - // TODO: make target samples per bucket configurable - let target_samples_per_bucket = 1usize << 12; + // 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 = target_samples_per_bucket as f64 / self.spp as f64; + 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 {