Page Menu
Home
Search
Configure Global Search
Log In
Files
F119806
auto_tile_size_release_06.py
Greg Zaal (gregzaal)
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Authored By
Greg Zaal (gregzaal)
Oct 26 2014, 8:56 PM
Size
12 KB
Subscribers
None
auto_tile_size_release_06.py
View Options
# BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# END GPL LICENSE BLOCK #####
bl_info
=
{
"name"
:
"Auto Tile Size"
,
"description"
:
"Estimate the render tile size that will render the fastest"
,
"author"
:
"Greg Zaal"
,
"version"
:
(
2
,
6
),
"blender"
:
(
2
,
72
,
0
),
"location"
:
"Render Settings > Performance"
,
"warning"
:
""
,
"wiki_url"
:
"http://wiki.blender.org/index.php?title=Extensions:2.6/Py/Scripts/Render/Auto_Tile_Size"
,
"tracker_url"
:
"https://projects.blender.org/tracker/index.php?func=detail&aid=36785&group_id=153&atid=467"
,
"category"
:
"Render"
}
import
bpy
from
bpy.app.handlers
import
persistent
from
math
import
ceil
,
floor
def
_update_tile_size
(
self
,
context
):
do_set_tile_size
(
context
)
class
AutoTileSizeSettings
(
bpy
.
types
.
PropertyGroup
):
gpu_choice
=
bpy
.
props
.
EnumProperty
(
name
=
"Target GPU Tile Size"
,
items
=
((
"16"
,
"16"
,
"16 x 16"
),
(
"32"
,
"32"
,
"32 x 32"
),
(
"64"
,
"64"
,
"64 x 64"
),
(
"128"
,
"128"
,
"128 x 128"
),
(
"256"
,
"256"
,
"256 x 256"
),
(
"512"
,
"512"
,
"512 x 512"
),
(
"1024"
,
"1024"
,
"1024 x 1024"
)),
default
=
'256'
,
description
=
"Square dimentions of tiles"
,
update
=
_update_tile_size
)
cpu_choice
=
bpy
.
props
.
EnumProperty
(
name
=
"Target CPU Tile Size"
,
items
=
((
"16"
,
"16"
,
"16 x 16"
),
(
"32"
,
"32"
,
"32 x 32"
),
(
"64"
,
"64"
,
"64 x 64"
),
(
"128"
,
"128"
,
"128 x 128"
),
(
"256"
,
"256"
,
"256 x 256"
),
(
"512"
,
"512"
,
"512 x 512"
),
(
"1024"
,
"1024"
,
"1024 x 1024"
)),
default
=
'32'
,
description
=
"Square dimentions of tiles"
,
update
=
_update_tile_size
)
bi_choice
=
bpy
.
props
.
EnumProperty
(
name
=
"Target CPU Tile Size"
,
items
=
((
"16"
,
"16"
,
"16 x 16"
),
(
"32"
,
"32"
,
"32 x 32"
),
(
"64"
,
"64"
,
"64 x 64"
),
(
"128"
,
"128"
,
"128 x 128"
),
(
"256"
,
"256"
,
"256 x 256"
),
(
"512"
,
"512"
,
"512 x 512"
),
(
"1024"
,
"1024"
,
"1024 x 1024"
)),
default
=
'64'
,
description
=
"Square dimentions of tiles"
,
update
=
_update_tile_size
)
optimal
=
bpy
.
props
.
EnumProperty
(
name
=
"Optimal Tiles"
,
default
=
"optimal"
,
description
=
"Match the target size exactly, or try to find a similar tile size for best performance"
,
items
=
((
"optimal"
,
"Optimal"
,
"All tiles will be the same size and roughly match the target (usually renders faster)"
),
(
"exact"
,
"Exact"
,
"Most tiles will match the target, but tiles around the edges may be rectangular (renders slower)"
)),
update
=
_update_tile_size
)
enable
=
bpy
.
props
.
BoolProperty
(
name
=
"Auto Tile Size"
,
default
=
True
,
description
=
"Calculate the best tile size based on factors of the render size and the chosen target"
,
update
=
_update_tile_size
)
advanced_ui
=
bpy
.
props
.
BoolProperty
(
name
=
"Advanced Settings"
,
default
=
False
,
description
=
"Show extra options for more control over the calculated tile size"
)
# Internally used props (not for GUI)
first_run
=
bpy
.
props
.
BoolProperty
(
default
=
True
)
threads_error
=
bpy
.
props
.
BoolProperty
()
prev_choice
=
bpy
.
props
.
StringProperty
(
default
=
'0'
)
prev_renderer
=
bpy
.
props
.
StringProperty
(
default
=
'prev_renderer'
)
prev_device
=
bpy
.
props
.
StringProperty
(
default
=
'prev_device'
)
prev_res
=
bpy
.
props
.
StringProperty
(
default
=
'prev_res'
)
prev_border
=
bpy
.
props
.
BoolProperty
(
default
=
False
)
prev_border_res
=
bpy
.
props
.
StringProperty
(
default
=
"prevborderres"
)
prev_actual_tile_size
=
bpy
.
props
.
StringProperty
(
default
=
'prevactual'
)
prev_threads
=
bpy
.
props
.
IntProperty
(
default
=
0
)
@persistent
def
on_scene_update
(
context
):
scene
=
bpy
.
context
.
scene
settings
=
scene
.
ats_settings
if
scene
.
render
.
engine
not
in
[
'CYCLES'
,
'BLENDER_RENDER'
]
or
not
settings
.
enable
:
return
False
# avoid any of these checks if ATS is disabled or scene uses unsupported renderer
renderer
=
scene
.
render
.
engine
device
=
scene
.
cycles
.
device
border
=
scene
.
render
.
use_border
threads
=
scene
.
render
.
threads
choice
=
0
if
(
device
==
'GPU'
and
bpy
.
context
.
user_preferences
.
system
.
compute_device_type
!=
'NONE'
)
and
scene
.
render
.
engine
==
'CYCLES'
:
choice
=
settings
.
gpu_choice
elif
(
device
==
'CPU'
or
bpy
.
context
.
user_preferences
.
system
.
compute_device_type
==
'NONE'
)
and
scene
.
render
.
engine
==
'CYCLES'
:
choice
=
settings
.
cpu_choice
elif
scene
.
render
.
engine
==
'BLENDER_RENDER'
:
choice
=
settings
.
bi_choice
res
=
str
(
get_actual_res
(
'x'
))
+
'x'
+
str
(
get_actual_res
(
'y'
))
actual_ts
=
str
(
scene
.
render
.
tile_x
)
+
'x'
+
str
(
scene
.
render
.
tile_y
)
border_res
=
(
str
(
scene
.
render
.
border_min_x
)
+
"x"
+
str
(
scene
.
render
.
border_min_y
))
+
'-'
+
(
str
(
scene
.
render
.
border_max_x
)
+
"x"
+
str
(
scene
.
render
.
border_max_y
))
# detect relevant changes in scene
change_triggers
=
[
renderer
!=
settings
.
prev_renderer
,
device
!=
settings
.
prev_device
,
border
!=
settings
.
prev_border
,
threads
!=
settings
.
prev_threads
,
choice
!=
settings
.
prev_choice
,
res
!=
settings
.
prev_res
,
border_res
!=
settings
.
prev_border_res
,
actual_ts
!=
settings
.
prev_actual_tile_size
]
if
any
(
change_triggers
):
settings
.
prev_renderer
=
renderer
settings
.
prev_device
=
device
settings
.
prev_border
=
border
settings
.
prev_threads
=
threads
settings
.
prev_choice
=
choice
settings
.
prev_border_res
=
border_res
do_set_tile_size
(
context
)
else
:
pass
return
True
def
get_actual_res
(
xy
):
rend
=
bpy
.
context
.
scene
.
render
rend_percent
=
rend
.
resolution_percentage
*
0.01
x
=
int
(
floor
(
rend
.
resolution_x
*
rend_percent
))
y
=
int
(
floor
(
rend
.
resolution_y
*
rend_percent
))
return
x
if
xy
==
'x'
else
y
def
do_set_tile_size
(
context
):
context
=
bpy
.
context
scene
=
context
.
scene
settings
=
scene
.
ats_settings
if
scene
.
render
.
engine
not
in
[
'CYCLES'
,
'BLENDER_RENDER'
]:
print
(
"Auto Tile Size is not supported for this renderer"
)
return
False
settings
.
first_run
=
False
device
=
scene
.
cycles
.
device
target
=
0
xres
=
get_actual_res
(
'x'
)
yres
=
get_actual_res
(
'y'
)
realxres
=
xres
realyres
=
yres
if
context
.
scene
.
render
.
use_border
:
xres
=
round
(
xres
*
(
context
.
scene
.
render
.
border_max_x
-
context
.
scene
.
render
.
border_min_x
))
yres
=
round
(
yres
*
(
context
.
scene
.
render
.
border_max_y
-
context
.
scene
.
render
.
border_min_y
))
if
(
device
==
'GPU'
and
context
.
user_preferences
.
system
.
compute_device_type
!=
'NONE'
)
and
scene
.
render
.
engine
==
'CYCLES'
:
target
=
int
(
settings
.
gpu_choice
)
elif
(
device
==
'CPU'
or
context
.
user_preferences
.
system
.
compute_device_type
==
'NONE'
)
and
scene
.
render
.
engine
==
'CYCLES'
:
target
=
int
(
settings
.
cpu_choice
)
elif
scene
.
render
.
engine
==
'BLENDER_RENDER'
:
target
=
int
(
settings
.
bi_choice
)
else
:
print
(
"Failed to get compute device"
)
return
False
settings
.
prev_choice
=
str
(
target
)
settings
.
prev_device
=
device
numtiles_x
=
ceil
(
xres
/
target
)
numtiles_y
=
ceil
(
yres
/
target
)
if
settings
.
optimal
==
"optimal"
:
tile_x
=
ceil
(
xres
/
numtiles_x
)
tile_y
=
ceil
(
yres
/
numtiles_y
)
print
(
"Tile size: "
+
str
(
tile_x
)
+
"x"
+
str
(
tile_y
)
+
" ("
+
str
(
ceil
(
xres
/
tile_x
))
+
"x"
+
str
(
ceil
(
yres
/
tile_y
))
+
" tiles)"
)
else
:
tile_x
=
target
tile_y
=
target
print
(
"Tile size: "
+
str
(
tile_x
)
+
"x"
+
str
(
tile_y
)
+
" ("
+
str
(
xres
/
tile_x
)
+
" x "
+
str
(
yres
/
tile_y
)
+
" tiles)"
)
# Detect if there are fewer tiles than available threads
if
((
ceil
(
numtiles_x
)
*
ceil
(
numtiles_y
))
<
scene
.
render
.
threads
)
and
not
((
device
==
'GPU'
and
context
.
user_preferences
.
system
.
compute_device_type
!=
'NONE'
)
and
scene
.
render
.
engine
==
'CYCLES'
):
settings
.
threads_error
=
True
else
:
settings
.
threads_error
=
False
scene
.
render
.
tile_x
=
tile_x
scene
.
render
.
tile_y
=
tile_y
settings
.
prev_res
=
str
(
realxres
)
+
'x'
+
str
(
realyres
)
settings
.
prev_actual_tile_size
=
str
(
scene
.
render
.
tile_x
)
+
'x'
+
str
(
scene
.
render
.
tile_y
)
return
True
class
SetTileSize
(
bpy
.
types
.
Operator
):
'The first render may not obey the tile-size set here'
bl_idname
=
'autotile.set'
bl_label
=
'Set'
def
execute
(
self
,
context
):
context
.
scene
.
ats_settings
.
first_run
=
False
if
do_set_tile_size
(
context
):
return
{
'FINISHED'
}
else
:
return
{
'CANCELLED'
}
'''
INFERFACE
'''
def
ui_layout
(
renderer
,
layout
,
context
):
scene
=
context
.
scene
settings
=
scene
.
ats_settings
col
=
layout
.
column
(
align
=
True
)
row
=
col
.
row
(
align
=
True
)
row
.
prop
(
settings
,
'enable'
,
toggle
=
True
)
row
.
prop
(
settings
,
'advanced_ui'
,
toggle
=
True
,
text
=
''
,
icon
=
'PREFERENCES'
)
if
settings
.
advanced_ui
:
col
.
label
(
"Target tile size:"
)
row
=
col
.
row
(
align
=
True
)
if
renderer
==
'CYCLES'
:
if
scene
.
cycles
.
device
==
'GPU'
and
context
.
user_preferences
.
system
.
compute_device_type
!=
'NONE'
and
scene
.
render
.
engine
==
'CYCLES'
:
row
.
prop
(
settings
,
'gpu_choice'
,
expand
=
True
)
elif
scene
.
cycles
.
device
==
'CPU'
or
context
.
user_preferences
.
system
.
compute_device_type
==
'NONE'
and
scene
.
render
.
engine
==
'CYCLES'
:
row
.
prop
(
settings
,
'cpu_choice'
,
expand
=
True
)
elif
renderer
==
'BLENDER_RENDER'
:
row
.
prop
(
settings
,
'bi_choice'
,
expand
=
True
)
row
=
col
.
row
(
align
=
True
)
row
.
prop
(
settings
,
'optimal'
,
text
=
'Consistent Tiles'
,
expand
=
True
)
if
settings
.
first_run
:
col
=
layout
.
column
(
align
=
True
)
col
.
operator
(
'autotile.set'
,
text
=
"First-render fix"
,
icon
=
'ERROR'
)
elif
settings
.
prev_device
!=
scene
.
cycles
.
device
:
col
=
layout
.
column
(
align
=
True
)
col
.
operator
(
'autotile.set'
,
text
=
"Device changed - fix"
,
icon
=
'ERROR'
)
if
(
scene
.
render
.
tile_x
/
scene
.
render
.
tile_y
>
2
)
or
(
scene
.
render
.
tile_x
/
scene
.
render
.
tile_y
<
0.5
):
# if not very square tile
col
.
label
(
text
=
"Warning: Tile size is not very square"
,
icon
=
'ERROR'
)
col
.
label
(
text
=
" Try a slightly different resolution"
)
col
.
label
(
text
=
" or choose
\"
Exact
\"
above"
)
if
settings
.
threads_error
:
col
.
label
(
text
=
"Warning: Fewer tiles than render threads"
,
icon
=
'ERROR'
)
def
menu_func_cycles
(
self
,
context
):
layout
=
self
.
layout
ui_layout
(
'CYCLES'
,
layout
,
context
)
def
menu_func_bi
(
self
,
context
):
layout
=
self
.
layout
ui_layout
(
'BLENDER_RENDER'
,
layout
,
context
)
'''
REGISTRATION
'''
def
register
():
bpy
.
types
.
CyclesRender_PT_performance
.
append
(
menu_func_cycles
)
# Note, the Cycles addon must be registered first, otherwise this panel doesn't exist
bpy
.
types
.
RENDER_PT_performance
.
append
(
menu_func_bi
)
bpy
.
app
.
handlers
.
scene_update_post
.
append
(
on_scene_update
)
bpy
.
utils
.
register_module
(
__name__
)
bpy
.
types
.
Scene
.
ats_settings
=
bpy
.
props
.
PointerProperty
(
type
=
AutoTileSizeSettings
)
def
unregister
():
del
bpy
.
types
.
Scene
.
ats_settings
bpy
.
types
.
CyclesRender_PT_performance
.
remove
(
menu_func_cycles
)
bpy
.
types
.
RENDER_PT_performance
.
remove
(
menu_func_bi
)
bpy
.
app
.
handlers
.
scene_update_post
.
remove
(
on_scene_update
)
bpy
.
utils
.
unregister_module
(
__name__
)
if
__name__
==
"__main__"
:
register
()
File Metadata
Details
Attached
Mime Type
text/x-python
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
4c/e3/7c97770894455768ad187189c9be
Attached To
T36785: Automatically calculate the best tile size for the fastest render
Event Timeline
Log In to Comment