Compare commits
109 Commits
lineart-fn
...
geometry-n
Author | SHA1 | Date | |
---|---|---|---|
7030e3a016 | |||
936dfae3de | |||
399aed9a81 | |||
e7c1702ccb | |||
149078d580 | |||
47b1f9a4d3 | |||
8709d0cd5d | |||
46bfc3ec46 | |||
a29b9a73d2 | |||
39f21c2475 | |||
87036f5eeb | |||
9636e79c5a | |||
e1c04da36f | |||
45bac491eb | |||
837d630466 | |||
23eb05eba5 | |||
12951aecf6 | |||
46a037707b | |||
f2948faf97 | |||
d7aa481231 | |||
cd07fb6477 | |||
d0bdb2b48f | |||
35b0d177a2 | |||
441f8d98eb | |||
c21199a0ba | |||
26d4864ee6 | |||
da443d82ee | |||
330c14c26c | |||
34542eede5 | |||
2c73e16d1c | |||
dd886fcc6d | |||
6b44605cec | |||
2e76c3565d | |||
c3b5378978 | |||
645fa86b7d | |||
e43428eba3 | |||
52cb657e91 | |||
a80edb8865 | |||
b500099e5c | |||
c9c295ef25 | |||
d64dea8a7e | |||
476006ae64 | |||
51e72e4703 | |||
ba12548f24 | |||
a6f2da1caf | |||
91b44ebb52 | |||
0d203862ca | |||
371720cb6d | |||
be1a41878c | |||
53b2a1a0e3 | |||
d9cb1fa7dc | |||
e7516174c7 | |||
98c908d6f6 | |||
fcb7d2fcba | |||
d0b2ddefa3 | |||
bb04d1c2c8 | |||
839c796321 | |||
db731b0beb | |||
6cf3878765 | |||
1975dc96d1 | |||
fa83dbda06 | |||
d0b0cb5982 | |||
da3004a0f9 | |||
ec090a215b | |||
797331db86 | |||
652ee81662 | |||
b5bd676a51 | |||
b490e0838c | |||
7c77d769dd | |||
48316b7e08 | |||
ff34a3a612 | |||
583bc7a05d | |||
2a96dc80b0 | |||
2cdec6cbf4 | |||
f8604f18e8 | |||
4f0e6c3aa3 | |||
f3775ca2cf | |||
5e013d47a1 | |||
2f2bedafa1 | |||
b90aeb0a44 | |||
29e24974a6 | |||
c752884d0d | |||
797ff2f064 | |||
24d32a796a | |||
d1519df6a8 | |||
457e1f9d1f | |||
85165058ef | |||
54188678b4 | |||
073bf63a9d | |||
f91df2e3e3 | |||
c95b2cefab | |||
53f92279cb | |||
b3fc6ac07a | |||
968977d684 | |||
f49a499129 | |||
140828037b | |||
188e4d302c | |||
cc06b059c2 | |||
0c64850e43 | |||
d64e149a4f | |||
09846cdce8 | |||
a4ad4bc8d3 | |||
2622882d83 | |||
b4beba7f1c | |||
58cdb78ea0 | |||
25e95ccb1a | |||
9e91aea40a | |||
5f03931fc4 | |||
e1cef1b85d |
@@ -255,7 +255,6 @@ ForEachMacros:
|
||||
- SCULPT_VERTEX_DUPLICATES_AND_NEIGHBORS_ITER_BEGIN
|
||||
- SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN
|
||||
- SEQ_ALL_BEGIN
|
||||
- SEQ_ITERATOR_FOREACH
|
||||
- SURFACE_QUAD_ITER_BEGIN
|
||||
- foreach
|
||||
- ED_screen_areas_iter
|
||||
|
@@ -29,7 +29,7 @@ set(BLOSC_EXTRA_ARGS
|
||||
-DCMAKE_POSITION_INDEPENDENT_CODE=ON
|
||||
)
|
||||
|
||||
# Prevent blosc from including its own local copy of zlib in the object file
|
||||
# Prevent blosc from including it's own local copy of zlib in the object file
|
||||
# and cause linker errors with everybody else.
|
||||
set(BLOSC_EXTRA_ARGS ${BLOSC_EXTRA_ARGS}
|
||||
-DPREFER_EXTERNAL_ZLIB=ON
|
||||
|
@@ -43,7 +43,7 @@ set(JPEG_FILE libjpeg-turbo-${JPEG_VERSION}.tar.gz)
|
||||
set(BOOST_VERSION 1.73.0)
|
||||
set(BOOST_VERSION_NODOTS 1_73_0)
|
||||
set(BOOST_VERSION_NODOTS_SHORT 1_73)
|
||||
set(BOOST_URI https://boostorg.jfrog.io/artifactory/main/release/${BOOST_VERSION}/source/boost_${BOOST_VERSION_NODOTS}.tar.gz)
|
||||
set(BOOST_URI https://dl.bintray.com/boostorg/release/${BOOST_VERSION}/source/boost_${BOOST_VERSION_NODOTS}.tar.gz)
|
||||
set(BOOST_HASH 4036cd27ef7548b8d29c30ea10956196)
|
||||
set(BOOST_HASH_TYPE MD5)
|
||||
set(BOOST_FILE boost_${BOOST_VERSION_NODOTS}.tar.gz)
|
||||
@@ -297,10 +297,10 @@ set(OPENJPEG_HASH 63f5a4713ecafc86de51bfad89cc07bb788e9bba24ebbf0c4ca637621aadb6
|
||||
set(OPENJPEG_HASH_TYPE SHA256)
|
||||
set(OPENJPEG_FILE openjpeg-v${OPENJPEG_VERSION}.tar.gz)
|
||||
|
||||
set(FFMPEG_VERSION 4.4)
|
||||
set(FFMPEG_VERSION 4.2.3)
|
||||
set(FFMPEG_URI http://ffmpeg.org/releases/ffmpeg-${FFMPEG_VERSION}.tar.bz2)
|
||||
set(FFMPEG_HASH 42093549751b582cf0f338a21a3664f52e0a9fbe0d238d3c992005e493607d0e)
|
||||
set(FFMPEG_HASH_TYPE SHA256)
|
||||
set(FFMPEG_HASH 695fad11f3baf27784e24cb0e977b65a)
|
||||
set(FFMPEG_HASH_TYPE MD5)
|
||||
set(FFMPEG_FILE ffmpeg-${FFMPEG_VERSION}.tar.bz2)
|
||||
|
||||
set(FFTW_VERSION 3.3.8)
|
||||
|
@@ -37,7 +37,7 @@ if [ $USE_DEBUG_TRAP -ne 0 ]; then
|
||||
trap 'err_report $LINENO' ERR
|
||||
fi
|
||||
|
||||
# Noisy, show every line that runs with its line number.
|
||||
# Noisy, show every line that runs with it's line number.
|
||||
if [ $USE_DEBUG_LOG -ne 0 ]; then
|
||||
PS4='\e[0;33m$(printf %4d ${LINENO}):\e\033[0m '
|
||||
set -x
|
||||
@@ -563,9 +563,9 @@ OIDN_SKIP=false
|
||||
|
||||
ISPC_VERSION="1.14.1"
|
||||
|
||||
FFMPEG_VERSION="4.4"
|
||||
FFMPEG_VERSION_SHORT="4.4"
|
||||
FFMPEG_VERSION_MIN="4.4"
|
||||
FFMPEG_VERSION="4.2.3"
|
||||
FFMPEG_VERSION_SHORT="4.2"
|
||||
FFMPEG_VERSION_MIN="3.0"
|
||||
FFMPEG_VERSION_MAX="5.0"
|
||||
FFMPEG_FORCE_BUILD=false
|
||||
FFMPEG_FORCE_REBUILD=false
|
||||
|
@@ -20,7 +20,7 @@
|
||||
# ILMBASE_LIBRARIES - list of libraries to link against when using IlmBase.
|
||||
# ILMBASE_FOUND - True if IlmBase was found.
|
||||
|
||||
# Other standard issue macros
|
||||
# Other standarnd issue macros
|
||||
include(FindPackageHandleStandardArgs)
|
||||
include(FindPackageMessage)
|
||||
include(SelectLibraryConfigurations)
|
||||
|
@@ -22,7 +22,7 @@
|
||||
# These are defined by the FindIlmBase module.
|
||||
# OPENEXR_FOUND - True if OpenEXR was found.
|
||||
|
||||
# Other standard issue macros
|
||||
# Other standarnd issue macros
|
||||
include(SelectLibraryConfigurations)
|
||||
include(FindPackageHandleStandardArgs)
|
||||
include(FindPackageMessage)
|
||||
|
@@ -79,7 +79,7 @@ if(EXISTS ${SOURCE_DIR}/.git)
|
||||
ERROR_QUIET)
|
||||
if(NOT _git_below_check STREQUAL "")
|
||||
# If there're commits between HEAD and upstream this means
|
||||
# that we're reset-ed to older revision. Use its hash then.
|
||||
# that we're reset-ed to older revision. Use it's hash then.
|
||||
execute_process(COMMAND git rev-parse --short=12 HEAD
|
||||
WORKING_DIRECTORY ${SOURCE_DIR}
|
||||
OUTPUT_VARIABLE MY_WC_HASH
|
||||
|
@@ -56,6 +56,10 @@ set(WITH_TBB ON CACHE BOOL "" FORCE)
|
||||
set(WITH_USD ON CACHE BOOL "" FORCE)
|
||||
|
||||
set(WITH_MEM_JEMALLOC ON CACHE BOOL "" FORCE)
|
||||
set(WITH_CYCLES_CUDA_BINARIES ON CACHE BOOL "" FORCE)
|
||||
set(WITH_CYCLES_CUBIN_COMPILER OFF CACHE BOOL "" FORCE)
|
||||
set(CYCLES_CUDA_BINARIES_ARCH sm_30;sm_35;sm_37;sm_50;sm_52;sm_60;sm_61;sm_70;sm_75;sm_86;compute_75 CACHE STRING "" FORCE)
|
||||
set(WITH_CYCLES_DEVICE_OPTIX ON CACHE BOOL "" FORCE)
|
||||
|
||||
# platform dependent options
|
||||
if(APPLE)
|
||||
@@ -76,8 +80,4 @@ if(UNIX AND NOT APPLE)
|
||||
endif()
|
||||
if(NOT APPLE)
|
||||
set(WITH_XR_OPENXR ON CACHE BOOL "" FORCE)
|
||||
|
||||
set(WITH_CYCLES_DEVICE_OPTIX ON CACHE BOOL "" FORCE)
|
||||
set(WITH_CYCLES_CUDA_BINARIES ON CACHE BOOL "" FORCE)
|
||||
set(WITH_CYCLES_CUBIN_COMPILER OFF CACHE BOOL "" FORCE)
|
||||
endif()
|
||||
|
@@ -104,8 +104,8 @@ if(WIN32)
|
||||
set(CPACK_WIX_LIGHT_EXTRA_FLAGS -dcl:medium)
|
||||
endif()
|
||||
|
||||
set(CPACK_PACKAGE_EXECUTABLES "blender-launcher" "blender")
|
||||
set(CPACK_CREATE_DESKTOP_LINKS "blender-launcher" "blender")
|
||||
set(CPACK_PACKAGE_EXECUTABLES "blender" "blender")
|
||||
set(CPACK_CREATE_DESKTOP_LINKS "blender" "blender")
|
||||
|
||||
include(CPack)
|
||||
|
||||
|
@@ -20,6 +20,12 @@
|
||||
|
||||
# Libraries configuration for Apple.
|
||||
|
||||
if("${CMAKE_OSX_ARCHITECTURES}" STREQUAL "arm64")
|
||||
set(MACOSX_DEPLOYMENT_TARGET 11.00)
|
||||
else()
|
||||
set(MACOSX_DEPLOYMENT_TARGET 10.13)
|
||||
endif()
|
||||
|
||||
macro(find_package_wrapper)
|
||||
# do nothing, just satisfy the macro
|
||||
endmacro()
|
||||
|
@@ -168,15 +168,21 @@ endif()
|
||||
unset(OSX_SDKROOT)
|
||||
|
||||
|
||||
# 10.13 is our min. target, if you use higher sdk, weak linking happens
|
||||
if("${CMAKE_OSX_ARCHITECTURES}" STREQUAL "arm64")
|
||||
# M1 chips run Big Sur onwards.
|
||||
set(OSX_MIN_DEPLOYMENT_TARGET 11.00)
|
||||
else()
|
||||
# 10.13 is our min. target, if you use higher sdk, weak linking happens
|
||||
set(OSX_MIN_DEPLOYMENT_TARGET 10.13)
|
||||
endif()
|
||||
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "${OSX_MIN_DEPLOYMENT_TARGET}" CACHE STRING "" FORCE)
|
||||
if(CMAKE_OSX_DEPLOYMENT_TARGET)
|
||||
if(${CMAKE_OSX_DEPLOYMENT_TARGET} VERSION_LESS ${OSX_MIN_DEPLOYMENT_TARGET})
|
||||
message(STATUS "Setting deployment target to ${OSX_MIN_DEPLOYMENT_TARGET}, lower versions are not supported")
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "${OSX_MIN_DEPLOYMENT_TARGET}" CACHE STRING "" FORCE)
|
||||
endif()
|
||||
else()
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "${OSX_MIN_DEPLOYMENT_TARGET}" CACHE STRING "" FORCE)
|
||||
endif()
|
||||
|
||||
if(NOT ${CMAKE_GENERATOR} MATCHES "Xcode")
|
||||
# Force CMAKE_OSX_DEPLOYMENT_TARGET for makefiles, will not work else (CMake bug?)
|
||||
|
@@ -119,7 +119,7 @@ string(APPEND CMAKE_MODULE_LINKER_FLAGS " /SAFESEH:NO /ignore:4099")
|
||||
list(APPEND PLATFORM_LINKLIBS
|
||||
ws2_32 vfw32 winmm kernel32 user32 gdi32 comdlg32 Comctl32 version
|
||||
advapi32 shfolder shell32 ole32 oleaut32 uuid psapi Dbghelp Shlwapi
|
||||
pathcch Shcore
|
||||
pathcch
|
||||
)
|
||||
|
||||
if(WITH_INPUT_IME)
|
||||
@@ -144,8 +144,8 @@ add_definitions(-D_ALLOW_KEYWORD_MACROS)
|
||||
# that both /GR and /GR- are specified.
|
||||
remove_cc_flag("/GR")
|
||||
|
||||
# Make the Windows 8.1 API available for use.
|
||||
add_definitions(-D_WIN32_WINNT=0x603)
|
||||
# We want to support Windows 7 level ABI
|
||||
add_definitions(-D_WIN32_WINNT=0x601)
|
||||
include(build_files/cmake/platform/platform_win32_bundle_crt.cmake)
|
||||
remove_cc_flag("/MDd" "/MD" "/Zi")
|
||||
|
||||
|
@@ -85,7 +85,7 @@ def openBlendFile(filename):
|
||||
'''
|
||||
handle = open(filename, 'rb')
|
||||
magic = ReadString(handle, 7)
|
||||
if magic in {"BLENDER", "BULLETf"}:
|
||||
if magic in ("BLENDER", "BULLETf"):
|
||||
log.debug("normal blendfile detected")
|
||||
handle.seek(0, os.SEEK_SET)
|
||||
return handle
|
||||
@@ -137,7 +137,7 @@ class BlendFile:
|
||||
fileblock = BlendFileBlock(handle, self)
|
||||
found_dna_block = False
|
||||
while not found_dna_block:
|
||||
if fileblock.Header.Code in {"DNA1", "SDNA"}:
|
||||
if fileblock.Header.Code in ("DNA1", "SDNA"):
|
||||
self.Catalog = DNACatalog(self.Header, handle)
|
||||
found_dna_block = True
|
||||
else:
|
||||
|
@@ -4,9 +4,7 @@ Simple Render Engine
|
||||
"""
|
||||
|
||||
import bpy
|
||||
import array
|
||||
import gpu
|
||||
from gpu_extras.presets import draw_texture_2d
|
||||
import bgl
|
||||
|
||||
|
||||
class CustomRenderEngine(bpy.types.RenderEngine):
|
||||
@@ -102,7 +100,8 @@ class CustomRenderEngine(bpy.types.RenderEngine):
|
||||
dimensions = region.width, region.height
|
||||
|
||||
# Bind shader that converts from scene linear to display space,
|
||||
gpu.state.blend_set('ALPHA_PREMULT')
|
||||
bgl.glEnable(bgl.GL_BLEND)
|
||||
bgl.glBlendFunc(bgl.GL_ONE, bgl.GL_ONE_MINUS_SRC_ALPHA)
|
||||
self.bind_display_space_shader(scene)
|
||||
|
||||
if not self.draw_data or self.draw_data.dimensions != dimensions:
|
||||
@@ -111,7 +110,7 @@ class CustomRenderEngine(bpy.types.RenderEngine):
|
||||
self.draw_data.draw()
|
||||
|
||||
self.unbind_display_space_shader()
|
||||
gpu.state.blend_set('NONE')
|
||||
bgl.glDisable(bgl.GL_BLEND)
|
||||
|
||||
|
||||
class CustomDrawData:
|
||||
@@ -120,21 +119,68 @@ class CustomDrawData:
|
||||
self.dimensions = dimensions
|
||||
width, height = dimensions
|
||||
|
||||
pixels = width * height * array.array('f', [0.1, 0.2, 0.1, 1.0])
|
||||
pixels = gpu.types.Buffer('FLOAT', width * height * 4, pixels)
|
||||
pixels = [0.1, 0.2, 0.1, 1.0] * width * height
|
||||
pixels = bgl.Buffer(bgl.GL_FLOAT, width * height * 4, pixels)
|
||||
|
||||
# Generate texture
|
||||
self.texture = gpu.types.GPUTexture((width, height), format='RGBA16F', data=pixels)
|
||||
self.texture = bgl.Buffer(bgl.GL_INT, 1)
|
||||
bgl.glGenTextures(1, self.texture)
|
||||
bgl.glActiveTexture(bgl.GL_TEXTURE0)
|
||||
bgl.glBindTexture(bgl.GL_TEXTURE_2D, self.texture[0])
|
||||
bgl.glTexImage2D(bgl.GL_TEXTURE_2D, 0, bgl.GL_RGBA16F, width, height, 0, bgl.GL_RGBA, bgl.GL_FLOAT, pixels)
|
||||
bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MIN_FILTER, bgl.GL_LINEAR)
|
||||
bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MAG_FILTER, bgl.GL_LINEAR)
|
||||
bgl.glBindTexture(bgl.GL_TEXTURE_2D, 0)
|
||||
|
||||
# Note: This is just a didactic example.
|
||||
# In this case it would be more convenient to fill the texture with:
|
||||
# self.texture.clear('FLOAT', value=[0.1, 0.2, 0.1, 1.0])
|
||||
# Bind shader that converts from scene linear to display space,
|
||||
# use the scene's color management settings.
|
||||
shader_program = bgl.Buffer(bgl.GL_INT, 1)
|
||||
bgl.glGetIntegerv(bgl.GL_CURRENT_PROGRAM, shader_program)
|
||||
|
||||
# Generate vertex array
|
||||
self.vertex_array = bgl.Buffer(bgl.GL_INT, 1)
|
||||
bgl.glGenVertexArrays(1, self.vertex_array)
|
||||
bgl.glBindVertexArray(self.vertex_array[0])
|
||||
|
||||
texturecoord_location = bgl.glGetAttribLocation(shader_program[0], "texCoord")
|
||||
position_location = bgl.glGetAttribLocation(shader_program[0], "pos")
|
||||
|
||||
bgl.glEnableVertexAttribArray(texturecoord_location)
|
||||
bgl.glEnableVertexAttribArray(position_location)
|
||||
|
||||
# Generate geometry buffers for drawing textured quad
|
||||
position = [0.0, 0.0, width, 0.0, width, height, 0.0, height]
|
||||
position = bgl.Buffer(bgl.GL_FLOAT, len(position), position)
|
||||
texcoord = [0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0]
|
||||
texcoord = bgl.Buffer(bgl.GL_FLOAT, len(texcoord), texcoord)
|
||||
|
||||
self.vertex_buffer = bgl.Buffer(bgl.GL_INT, 2)
|
||||
|
||||
bgl.glGenBuffers(2, self.vertex_buffer)
|
||||
bgl.glBindBuffer(bgl.GL_ARRAY_BUFFER, self.vertex_buffer[0])
|
||||
bgl.glBufferData(bgl.GL_ARRAY_BUFFER, 32, position, bgl.GL_STATIC_DRAW)
|
||||
bgl.glVertexAttribPointer(position_location, 2, bgl.GL_FLOAT, bgl.GL_FALSE, 0, None)
|
||||
|
||||
bgl.glBindBuffer(bgl.GL_ARRAY_BUFFER, self.vertex_buffer[1])
|
||||
bgl.glBufferData(bgl.GL_ARRAY_BUFFER, 32, texcoord, bgl.GL_STATIC_DRAW)
|
||||
bgl.glVertexAttribPointer(texturecoord_location, 2, bgl.GL_FLOAT, bgl.GL_FALSE, 0, None)
|
||||
|
||||
bgl.glBindBuffer(bgl.GL_ARRAY_BUFFER, 0)
|
||||
bgl.glBindVertexArray(0)
|
||||
|
||||
def __del__(self):
|
||||
del self.texture
|
||||
bgl.glDeleteBuffers(2, self.vertex_buffer)
|
||||
bgl.glDeleteVertexArrays(1, self.vertex_array)
|
||||
bgl.glBindTexture(bgl.GL_TEXTURE_2D, 0)
|
||||
bgl.glDeleteTextures(1, self.texture)
|
||||
|
||||
def draw(self):
|
||||
draw_texture_2d(self.texture, (0, 0), self.texture.width, self.texture.height)
|
||||
bgl.glActiveTexture(bgl.GL_TEXTURE0)
|
||||
bgl.glBindTexture(bgl.GL_TEXTURE_2D, self.texture[0])
|
||||
bgl.glBindVertexArray(self.vertex_array[0])
|
||||
bgl.glDrawArrays(bgl.GL_TRIANGLE_FAN, 0, 4)
|
||||
bgl.glBindVertexArray(0)
|
||||
bgl.glBindTexture(bgl.GL_TEXTURE_2D, 0)
|
||||
|
||||
|
||||
# RenderEngines also need to tell UI Panels that they are compatible with.
|
||||
|
@@ -4,6 +4,7 @@ Mesh with Random Vertex Colors
|
||||
"""
|
||||
import bpy
|
||||
import gpu
|
||||
import bgl
|
||||
import numpy as np
|
||||
from random import random
|
||||
from gpu_extras.batch import batch_for_shader
|
||||
@@ -30,10 +31,9 @@ batch = batch_for_shader(
|
||||
|
||||
|
||||
def draw():
|
||||
gpu.state.depth_test_set('LESS_EQUAL')
|
||||
gpu.state.depth_mask_set(True)
|
||||
bgl.glEnable(bgl.GL_DEPTH_TEST)
|
||||
batch.draw(shader)
|
||||
gpu.state.depth_mask_set(False)
|
||||
bgl.glDisable(bgl.GL_DEPTH_TEST)
|
||||
|
||||
|
||||
bpy.types.SpaceView3D.draw_handler_add(draw, (), 'WINDOW', 'POST_VIEW')
|
||||
|
@@ -6,11 +6,11 @@ To use this example you have to provide an image that should be displayed.
|
||||
"""
|
||||
import bpy
|
||||
import gpu
|
||||
import bgl
|
||||
from gpu_extras.batch import batch_for_shader
|
||||
|
||||
IMAGE_NAME = "Untitled"
|
||||
image = bpy.data.images[IMAGE_NAME]
|
||||
texture = gpu.texture.from_image(image)
|
||||
|
||||
shader = gpu.shader.from_builtin('2D_IMAGE')
|
||||
batch = batch_for_shader(
|
||||
@@ -21,9 +21,16 @@ batch = batch_for_shader(
|
||||
},
|
||||
)
|
||||
|
||||
if image.gl_load():
|
||||
raise Exception()
|
||||
|
||||
|
||||
def draw():
|
||||
bgl.glActiveTexture(bgl.GL_TEXTURE0)
|
||||
bgl.glBindTexture(bgl.GL_TEXTURE_2D, image.bindcode)
|
||||
|
||||
shader.bind()
|
||||
shader.uniform_sampler("image", texture)
|
||||
shader.uniform_int("image", 0)
|
||||
batch.draw(shader)
|
||||
|
||||
|
||||
|
@@ -9,6 +9,7 @@ Generate a texture using Offscreen Rendering
|
||||
"""
|
||||
import bpy
|
||||
import gpu
|
||||
import bgl
|
||||
from mathutils import Matrix
|
||||
from gpu_extras.batch import batch_for_shader
|
||||
from gpu_extras.presets import draw_circle_2d
|
||||
@@ -19,8 +20,8 @@ from gpu_extras.presets import draw_circle_2d
|
||||
offscreen = gpu.types.GPUOffScreen(512, 512)
|
||||
|
||||
with offscreen.bind():
|
||||
fb = gpu.state.active_framebuffer_get()
|
||||
fb.clear(color=(0.0, 0.0, 0.0, 0.0))
|
||||
bgl.glClearColor(0.0, 0.0, 0.0, 0.0)
|
||||
bgl.glClear(bgl.GL_COLOR_BUFFER_BIT)
|
||||
with gpu.matrix.push_pop():
|
||||
# reset matrices -> use normalized device coordinates [-1, 1]
|
||||
gpu.matrix.load_matrix(Matrix.Identity(4))
|
||||
@@ -74,10 +75,13 @@ batch = batch_for_shader(
|
||||
|
||||
|
||||
def draw():
|
||||
bgl.glActiveTexture(bgl.GL_TEXTURE0)
|
||||
bgl.glBindTexture(bgl.GL_TEXTURE_2D, offscreen.color_texture)
|
||||
|
||||
shader.bind()
|
||||
shader.uniform_float("modelMatrix", Matrix.Translation((1, 2, 3)) @ Matrix.Scale(3, 4))
|
||||
shader.uniform_float("viewProjectionMatrix", bpy.context.region_data.perspective_matrix)
|
||||
shader.uniform_sampler("image", offscreen.texture_color)
|
||||
shader.uniform_float("image", 0)
|
||||
batch.draw(shader)
|
||||
|
||||
|
||||
|
@@ -7,10 +7,11 @@ If it already exists, it will override the existing one.
|
||||
|
||||
Currently almost all of the execution time is spent in the last line.
|
||||
In the future this will hopefully be solved by implementing the Python buffer protocol
|
||||
for :class:`gpu.types.Buffer` and :class:`bpy.types.Image.pixels` (aka ``bpy_prop_array``).
|
||||
for :class:`bgl.Buffer` and :class:`bpy.types.Image.pixels` (aka ``bpy_prop_array``).
|
||||
"""
|
||||
import bpy
|
||||
import gpu
|
||||
import bgl
|
||||
import random
|
||||
from mathutils import Matrix
|
||||
from gpu_extras.presets import draw_circle_2d
|
||||
@@ -24,8 +25,8 @@ RING_AMOUNT = 10
|
||||
offscreen = gpu.types.GPUOffScreen(WIDTH, HEIGHT)
|
||||
|
||||
with offscreen.bind():
|
||||
fb = gpu.state.active_framebuffer_get()
|
||||
fb.clear(color=(0.0, 0.0, 0.0, 0.0))
|
||||
bgl.glClearColor(0.0, 0.0, 0.0, 0.0)
|
||||
bgl.glClear(bgl.GL_COLOR_BUFFER_BIT)
|
||||
with gpu.matrix.push_pop():
|
||||
# reset matrices -> use normalized device coordinates [-1, 1]
|
||||
gpu.matrix.load_matrix(Matrix.Identity(4))
|
||||
@@ -36,7 +37,9 @@ with offscreen.bind():
|
||||
(random.uniform(-1, 1), random.uniform(-1, 1)),
|
||||
(1, 1, 1, 1), random.uniform(0.1, 1), 20)
|
||||
|
||||
buffer = fb.read_color(0, 0, WIDTH, HEIGHT, 4, 0, 'UBYTE')
|
||||
buffer = bgl.Buffer(bgl.GL_BYTE, WIDTH * HEIGHT * 4)
|
||||
bgl.glReadBuffer(bgl.GL_BACK)
|
||||
bgl.glReadPixels(0, 0, WIDTH, HEIGHT, bgl.GL_RGBA, bgl.GL_UNSIGNED_BYTE, buffer)
|
||||
|
||||
offscreen.free()
|
||||
|
||||
@@ -45,6 +48,4 @@ if not IMAGE_NAME in bpy.data.images:
|
||||
bpy.data.images.new(IMAGE_NAME, WIDTH, HEIGHT)
|
||||
image = bpy.data.images[IMAGE_NAME]
|
||||
image.scale(WIDTH, HEIGHT)
|
||||
|
||||
buffer.dimensions = WIDTH * HEIGHT * 4
|
||||
image.pixels = [v / 255 for v in buffer]
|
||||
|
@@ -7,6 +7,7 @@ You could also make this independent of a specific camera,
|
||||
but Blender does not expose good functions to create view and projection matrices yet.
|
||||
"""
|
||||
import bpy
|
||||
import bgl
|
||||
import gpu
|
||||
from gpu_extras.presets import draw_texture_2d
|
||||
|
||||
@@ -33,8 +34,8 @@ def draw():
|
||||
view_matrix,
|
||||
projection_matrix)
|
||||
|
||||
gpu.state.depth_mask_set(False)
|
||||
draw_texture_2d(offscreen.texture_color, (10, 10), WIDTH, HEIGHT)
|
||||
bgl.glDisable(bgl.GL_DEPTH_TEST)
|
||||
draw_texture_2d(offscreen.color_texture, (10, 10), WIDTH, HEIGHT)
|
||||
|
||||
|
||||
bpy.types.SpaceView3D.draw_handler_add(draw, (), 'WINDOW', 'POST_PIXEL')
|
||||
|
@@ -1,5 +0,0 @@
|
||||
# Compute local object transformation matrix:
|
||||
if obj.rotation_mode == 'QUATERNION':
|
||||
matrix = mathutils.Matrix.LocRotScale(obj.location, obj.rotation_quaternion, obj.scale)
|
||||
else:
|
||||
matrix = mathutils.Matrix.LocRotScale(obj.location, obj.rotation_euler, obj.scale)
|
@@ -14,14 +14,10 @@ mat_rot = mathutils.Matrix.Rotation(math.radians(45.0), 4, 'X')
|
||||
mat_out = mat_loc @ mat_rot @ mat_sca
|
||||
print(mat_out)
|
||||
|
||||
# extract components back out of the matrix as two vectors and a quaternion
|
||||
# extract components back out of the matrix
|
||||
loc, rot, sca = mat_out.decompose()
|
||||
print(loc, rot, sca)
|
||||
|
||||
# recombine extracted components
|
||||
mat_out2 = mathutils.Matrix.LocRotScale(loc, rot, sca)
|
||||
print(mat_out2)
|
||||
|
||||
# it can also be useful to access components of a matrix directly
|
||||
mat = mathutils.Matrix()
|
||||
mat[0][0], mat[1][0], mat[2][0] = 0.0, 1.0, 2.0
|
||||
|
@@ -545,13 +545,6 @@ def range_str(val):
|
||||
|
||||
|
||||
def example_extract_docstring(filepath):
|
||||
'''
|
||||
Return (text, line_no, line_no_has_content) where:
|
||||
- ``text`` is the doc-string text.
|
||||
- ``line_no`` is the line the doc-string text ends.
|
||||
- ``line_no_has_content`` when False, this file only contains a doc-string.
|
||||
There is no need to include the remainder.
|
||||
'''
|
||||
file = open(filepath, "r", encoding="utf-8")
|
||||
line = file.readline()
|
||||
line_no = 0
|
||||
@@ -560,7 +553,7 @@ def example_extract_docstring(filepath):
|
||||
line_no += 1
|
||||
else:
|
||||
file.close()
|
||||
return "", 0, True
|
||||
return "", 0, False
|
||||
|
||||
for line in file:
|
||||
line_no += 1
|
||||
@@ -954,7 +947,7 @@ def pymodule2sphinx(basepath, module_name, module, title, module_all_extra):
|
||||
# constant, not much fun we can do here except to list it.
|
||||
# TODO, figure out some way to document these!
|
||||
fw(".. data:: %s\n\n" % attribute)
|
||||
write_indented_lines(" ", fw, "Constant value %s" % repr(value), False)
|
||||
write_indented_lines(" ", fw, "constant value %s" % repr(value), False)
|
||||
fw("\n")
|
||||
else:
|
||||
BPY_LOGGER.debug("\tnot documenting %s.%s of %r type" % (module_name, attribute, value_type.__name__))
|
||||
@@ -1036,6 +1029,7 @@ def pymodule2sphinx(basepath, module_name, module, title, module_all_extra):
|
||||
context_type_map = {
|
||||
# context_member: (RNA type, is_collection)
|
||||
"active_annotation_layer": ("GPencilLayer", False),
|
||||
"active_base": ("ObjectBase", False),
|
||||
"active_bone": ("EditBone", False),
|
||||
"active_gpencil_frame": ("GreasePencilLayer", True),
|
||||
"active_gpencil_layer": ("GPencilLayer", True),
|
||||
@@ -1246,7 +1240,7 @@ def pyrna_enum2sphinx(prop, use_empty_descriptions=False):
|
||||
"%s.\n" % (
|
||||
identifier,
|
||||
# Account for multi-line enum descriptions, allowing this to be a block of text.
|
||||
indent(" -- ".join(escape_rst(val) for val in (name, description) if val) or "Undocumented", " "),
|
||||
indent(", ".join(escape_rst(val) for val in (name, description) if val) or "Undocumented", " "),
|
||||
)
|
||||
for identifier, name, description in prop.enum_items
|
||||
])
|
||||
@@ -1555,8 +1549,8 @@ def pyrna2sphinx(basepath):
|
||||
fw(".. hlist::\n")
|
||||
fw(" :columns: 2\n\n")
|
||||
|
||||
# Context does its own thing.
|
||||
# "active_object": ("Object", False),
|
||||
# context does its own thing
|
||||
# "active_base": ("ObjectBase", False),
|
||||
for ref_attr, (ref_type, ref_is_seq) in sorted(context_type_map.items()):
|
||||
if ref_type == struct_id:
|
||||
fw(" * :mod:`bpy.context.%s`\n" % ref_attr)
|
||||
|
@@ -1,8 +1,7 @@
|
||||
/* T76453: Prevent Long enum lists */
|
||||
.field-list > dd p {
|
||||
.field-list li {
|
||||
max-height: 245px;
|
||||
overflow-y: auto !important;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
/* Hide home icon in search area */
|
||||
@@ -12,15 +11,3 @@
|
||||
.wy-nav-content {
|
||||
max-width: 1000px !important;
|
||||
}
|
||||
|
||||
/* Fix long titles on mobile */
|
||||
h1, h2, h3, h4, h5, h6 {word-break: break-all}
|
||||
|
||||
/* Temp fix for https://github.com/readthedocs/sphinx_rtd_theme/pull/1109 */
|
||||
.hlist tr {
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
}
|
||||
|
||||
.hlist td {margin-right: auto}
|
||||
|
@@ -75,7 +75,6 @@ void FFMPEGWriter::encode()
|
||||
m_frame->nb_samples = m_input_samples;
|
||||
m_frame->format = m_codecCtx->sample_fmt;
|
||||
m_frame->channel_layout = m_codecCtx->channel_layout;
|
||||
m_frame->channels = m_specs.channels;
|
||||
|
||||
if(avcodec_fill_audio_frame(m_frame, m_specs.channels, m_codecCtx->sample_fmt, reinterpret_cast<data_t*>(data), m_input_buffer.getSize(), 0) < 0)
|
||||
AUD_THROW(FileException, "File couldn't be written, filling the audio frame failed with ffmpeg.");
|
||||
|
13
extern/mantaflow/preprocessed/fileio/iovdb.cpp
vendored
13
extern/mantaflow/preprocessed/fileio/iovdb.cpp
vendored
@@ -29,10 +29,10 @@
|
||||
|
||||
#if OPENVDB == 1
|
||||
# include "openvdb/openvdb.h"
|
||||
# include "openvdb/points/PointConversion.h"
|
||||
# include "openvdb/points/PointCount.h"
|
||||
# include "openvdb/tools/Clip.h"
|
||||
# include "openvdb/tools/Dense.h"
|
||||
# include <openvdb/points/PointConversion.h>
|
||||
# include <openvdb/points/PointCount.h>
|
||||
# include <openvdb/tools/Clip.h>
|
||||
# include <openvdb/tools/Dense.h>
|
||||
#endif
|
||||
|
||||
#define POSITION_NAME "P"
|
||||
@@ -519,7 +519,7 @@ int writeObjectsVDB(const string &filename,
|
||||
}
|
||||
}
|
||||
|
||||
// Write only if there is at least one grid, optionally write with compression.
|
||||
// Write only if the is at least one grid, optionally write with compression.
|
||||
if (gridsVDB.size()) {
|
||||
int vdb_flags = openvdb::io::COMPRESS_ACTIVE_MASK;
|
||||
switch (compression) {
|
||||
@@ -534,8 +534,7 @@ int writeObjectsVDB(const string &filename,
|
||||
}
|
||||
case COMPRESSION_BLOSC: {
|
||||
# if OPENVDB_BLOSC == 1
|
||||
// Cannot use |= here, causes segfault with blosc 1.5.0 (== recommended version)
|
||||
vdb_flags = openvdb::io::COMPRESS_BLOSC;
|
||||
vdb_flags |= openvdb::io::COMPRESS_BLOSC;
|
||||
# else
|
||||
debMsg("OpenVDB was built without Blosc support, using Zip compression instead", 1);
|
||||
vdb_flags |= openvdb::io::COMPRESS_ZIP;
|
||||
|
1
extern/mantaflow/preprocessed/fluidsolver.h
vendored
1
extern/mantaflow/preprocessed/fluidsolver.h
vendored
@@ -384,7 +384,6 @@ class FluidSolver : public PbClass {
|
||||
GridStorage<Real> mGrids4dReal;
|
||||
GridStorage<Vec3> mGrids4dVec;
|
||||
GridStorage<Vec4> mGrids4dVec4;
|
||||
|
||||
public:
|
||||
PbArgs _args;
|
||||
}
|
||||
|
2
extern/mantaflow/preprocessed/general.h
vendored
2
extern/mantaflow/preprocessed/general.h
vendored
@@ -42,7 +42,7 @@ inline void updateQtGui(bool full, int frame, float time, const std::string &cur
|
||||
# ifdef _DEBUG
|
||||
# define DEBUG 1
|
||||
# endif // _DEBUG
|
||||
#endif // DEBUG
|
||||
#endif // DEBUG
|
||||
|
||||
// Standard exception
|
||||
class Error : public std::exception {
|
||||
|
2
extern/mantaflow/preprocessed/gitinfo.h
vendored
2
extern/mantaflow/preprocessed/gitinfo.h
vendored
@@ -1,3 +1,3 @@
|
||||
|
||||
|
||||
#define MANTA_GIT_VERSION "commit 9c505cd22e289b98c9aa717efba8ef3201c7e458"
|
||||
#define MANTA_GIT_VERSION "commit 39b7a415721ecbf6643612a24e8eadd221aeb934"
|
||||
|
1
extern/mantaflow/preprocessed/grid.h
vendored
1
extern/mantaflow/preprocessed/grid.h
vendored
@@ -389,7 +389,6 @@ class GridBase : public PbClass {
|
||||
Real mDx;
|
||||
bool m3D; // precomputed Z shift: to ensure 2D compatibility, always use this instead of sx*sy !
|
||||
IndexInt mStrideZ;
|
||||
|
||||
public:
|
||||
PbArgs _args;
|
||||
}
|
||||
|
2
extern/mantaflow/preprocessed/grid4d.h
vendored
2
extern/mantaflow/preprocessed/grid4d.h
vendored
@@ -326,7 +326,6 @@ class Grid4dBase : public PbClass {
|
||||
// precomputed Z,T shift: to ensure 2D compatibility, always use this instead of sx*sy !
|
||||
IndexInt mStrideZ;
|
||||
IndexInt mStrideT;
|
||||
|
||||
public:
|
||||
PbArgs _args;
|
||||
}
|
||||
@@ -951,7 +950,6 @@ template<class T> class Grid4d : public Grid4dBase {
|
||||
|
||||
protected:
|
||||
T *mData;
|
||||
|
||||
public:
|
||||
PbArgs _args;
|
||||
}
|
||||
|
1
extern/mantaflow/preprocessed/levelset.h
vendored
1
extern/mantaflow/preprocessed/levelset.h
vendored
@@ -266,7 +266,6 @@ class LevelsetGrid : public Grid<Real> {
|
||||
}
|
||||
|
||||
static Real invalidTimeValue();
|
||||
|
||||
public:
|
||||
PbArgs _args;
|
||||
}
|
||||
|
3
extern/mantaflow/preprocessed/mesh.h
vendored
3
extern/mantaflow/preprocessed/mesh.h
vendored
@@ -796,7 +796,6 @@ class Mesh : public PbClass {
|
||||
std::vector<MeshDataImpl<int> *>
|
||||
mMdataInt; //! indicate that mdata of this mesh is copied, and needs to be freed
|
||||
bool mFreeMdata;
|
||||
|
||||
public:
|
||||
PbArgs _args;
|
||||
}
|
||||
@@ -882,7 +881,6 @@ class MeshDataBase : public PbClass {
|
||||
|
||||
protected:
|
||||
Mesh *mMesh;
|
||||
|
||||
public:
|
||||
PbArgs _args;
|
||||
}
|
||||
@@ -1647,7 +1645,6 @@ template<class T> class MeshDataImpl : public MeshDataBase {
|
||||
//! optionally , we might have an associated grid from which to grab new data
|
||||
Grid<T> *mpGridSource; //! unfortunately , we need to distinguish mac vs regular vec3
|
||||
bool mGridSourceMAC;
|
||||
|
||||
public:
|
||||
PbArgs _args;
|
||||
}
|
||||
|
1
extern/mantaflow/preprocessed/movingobs.h
vendored
1
extern/mantaflow/preprocessed/movingobs.h
vendored
@@ -154,7 +154,6 @@ class MovingObstacle : public PbClass {
|
||||
int mEmptyType;
|
||||
int mID;
|
||||
static int sIDcnt;
|
||||
|
||||
public:
|
||||
PbArgs _args;
|
||||
}
|
||||
|
1
extern/mantaflow/preprocessed/noisefield.h
vendored
1
extern/mantaflow/preprocessed/noisefield.h
vendored
@@ -236,7 +236,6 @@ class WaveletNoiseField : public PbClass {
|
||||
static int randomSeed;
|
||||
// global reference count for noise tile
|
||||
static std::atomic<int> mNoiseReferenceCount;
|
||||
|
||||
public:
|
||||
PbArgs _args;
|
||||
}
|
||||
|
6
extern/mantaflow/preprocessed/particle.h
vendored
6
extern/mantaflow/preprocessed/particle.h
vendored
@@ -205,7 +205,6 @@ class ParticleBase : public PbClass {
|
||||
//! custom seed for particle systems, used by plugins
|
||||
int mSeed; //! fix global random seed storage, used mainly by functions in this class
|
||||
static int globalSeed;
|
||||
|
||||
public:
|
||||
PbArgs _args;
|
||||
}
|
||||
@@ -629,7 +628,6 @@ template<class S> class ParticleSystem : public ParticleBase {
|
||||
std::vector<S> mData;
|
||||
//! reduce storage , called by doCompress
|
||||
virtual void compress();
|
||||
|
||||
public:
|
||||
PbArgs _args;
|
||||
}
|
||||
@@ -920,7 +918,6 @@ class ParticleIndexSystem : public ParticleSystem<ParticleIndexData> {
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
PbArgs _args;
|
||||
}
|
||||
@@ -985,7 +982,6 @@ template<class DATA, class CON> class ConnectedParticleSystem : public ParticleS
|
||||
protected:
|
||||
std::vector<CON> mSegments;
|
||||
virtual void compress();
|
||||
|
||||
public:
|
||||
PbArgs _args;
|
||||
}
|
||||
@@ -1075,7 +1071,6 @@ class ParticleDataBase : public PbClass {
|
||||
|
||||
protected:
|
||||
ParticleBase *mpParticleSys;
|
||||
|
||||
public:
|
||||
PbArgs _args;
|
||||
}
|
||||
@@ -1848,7 +1843,6 @@ template<class T> class ParticleDataImpl : public ParticleDataBase {
|
||||
//! optionally , we might have an associated grid from which to grab new data
|
||||
Grid<T> *mpGridSource; //! unfortunately , we need to distinguish mac vs regular vec3
|
||||
bool mGridSourceMAC;
|
||||
|
||||
public:
|
||||
PbArgs _args;
|
||||
}
|
||||
|
@@ -234,10 +234,10 @@ void subdivideMesh(
|
||||
normalize(ne2);
|
||||
|
||||
// Real thisArea = sqrMag(cross(-e2,e0));
|
||||
// small angle approximation says sin(x) = arcsin(x) = x,
|
||||
// arccos(x) = pi/2 - arcsin(x),
|
||||
// cos(x) = dot(A,B),
|
||||
// so angle is approximately 1 - dot(A,B).
|
||||
// small angle approximation says sin(x) = arcsin(x) = x,
|
||||
// arccos(x) = pi/2 - arcsin(x),
|
||||
// cos(x) = dot(A,B),
|
||||
// so angle is approximately 1 - dot(A,B).
|
||||
Real angle[3];
|
||||
angle[0] = 1.0 - dot(ne0, -ne2);
|
||||
angle[1] = 1.0 - dot(ne1, -ne0);
|
||||
|
@@ -2287,10 +2287,9 @@ struct knFlipComputePotentialTrappedAir : public KernelBase {
|
||||
const Vec3 &vj = scaleFromManta * v.getCentered(x, y, z);
|
||||
const Vec3 xij = xi - xj;
|
||||
const Vec3 vij = vi - vj;
|
||||
Real h = !pot.is3D() ?
|
||||
1.414 * radius :
|
||||
1.732 * radius; // estimate sqrt(2)*radius resp. sqrt(3)*radius for h, due
|
||||
// to squared resp. cubic neighbor area
|
||||
Real h = !pot.is3D() ? 1.414 * radius :
|
||||
1.732 * radius; // estimate sqrt(2)*radius resp. sqrt(3)*radius
|
||||
// for h, due to squared resp. cubic neighbor area
|
||||
vdiff += norm(vij) * (1 - dot(getNormalized(vij), getNormalized(xij))) *
|
||||
(1 - norm(xij) / h);
|
||||
}
|
||||
|
6
extern/mantaflow/preprocessed/shapes.h
vendored
6
extern/mantaflow/preprocessed/shapes.h
vendored
@@ -269,7 +269,6 @@ class Shape : public PbClass {
|
||||
|
||||
protected:
|
||||
GridType mType;
|
||||
|
||||
public:
|
||||
PbArgs _args;
|
||||
}
|
||||
@@ -320,7 +319,6 @@ class NullShape : public Shape {
|
||||
{
|
||||
gridSetConst<Real>(phi, 1000.0f);
|
||||
}
|
||||
|
||||
public:
|
||||
PbArgs _args;
|
||||
}
|
||||
@@ -396,7 +394,6 @@ class Box : public Shape {
|
||||
|
||||
protected:
|
||||
Vec3 mP0, mP1;
|
||||
|
||||
public:
|
||||
PbArgs _args;
|
||||
}
|
||||
@@ -458,7 +455,6 @@ class Sphere : public Shape {
|
||||
protected:
|
||||
Vec3 mCenter, mScale;
|
||||
Real mRadius;
|
||||
|
||||
public:
|
||||
PbArgs _args;
|
||||
}
|
||||
@@ -583,7 +579,6 @@ class Cylinder : public Shape {
|
||||
protected:
|
||||
Vec3 mCenter, mZDir;
|
||||
Real mRadius, mZ;
|
||||
|
||||
public:
|
||||
PbArgs _args;
|
||||
}
|
||||
@@ -660,7 +655,6 @@ class Slope : public Shape {
|
||||
Real mAnglexy, mAngleyz;
|
||||
Real mOrigin;
|
||||
Vec3 mGs;
|
||||
|
||||
public:
|
||||
PbArgs _args;
|
||||
}
|
||||
|
@@ -199,7 +199,6 @@ class TurbulenceParticleSystem : public ParticleSystem<TurbulenceParticleData> {
|
||||
|
||||
private:
|
||||
WaveletNoiseField &noise;
|
||||
|
||||
public:
|
||||
PbArgs _args;
|
||||
}
|
||||
|
1
extern/mantaflow/preprocessed/vortexpart.h
vendored
1
extern/mantaflow/preprocessed/vortexpart.h
vendored
@@ -127,7 +127,6 @@ class VortexParticleSystem : public ParticleSystem<VortexParticleData> {
|
||||
}
|
||||
|
||||
virtual ParticleBase *clone();
|
||||
|
||||
public:
|
||||
PbArgs _args;
|
||||
}
|
||||
|
1
extern/mantaflow/preprocessed/vortexsheet.h
vendored
1
extern/mantaflow/preprocessed/vortexsheet.h
vendored
@@ -240,7 +240,6 @@ class VortexSheetMesh : public Mesh {
|
||||
VorticityChannel mVorticity;
|
||||
TexCoord3Channel mTex1, mTex2;
|
||||
TurbulenceChannel mTurb;
|
||||
|
||||
public:
|
||||
PbArgs _args;
|
||||
}
|
||||
|
2
extern/smaa_areatex/smaa_areatex.cpp
vendored
2
extern/smaa_areatex/smaa_areatex.cpp
vendored
@@ -1088,8 +1088,6 @@ static int generate_file(AreaOrtho *ortho, AreaDiag *diag, const char *path, boo
|
||||
return 1;
|
||||
}
|
||||
|
||||
// fprintf(stderr, "Generating %s\n", path);
|
||||
|
||||
if (tga)
|
||||
write_tga(ortho, diag, fp, subsampling);
|
||||
else if (raw)
|
||||
|
@@ -118,7 +118,6 @@ typedef struct CLG_LogType {
|
||||
typedef struct CLG_LogRef {
|
||||
const char *identifier;
|
||||
CLG_LogType *type;
|
||||
struct CLG_LogRef *next;
|
||||
} CLG_LogRef;
|
||||
|
||||
void CLG_log_str(CLG_LogType *lg,
|
||||
|
@@ -81,8 +81,6 @@ typedef struct CLG_IDFilter {
|
||||
typedef struct CLogContext {
|
||||
/** Single linked list of types. */
|
||||
CLG_LogType *types;
|
||||
/** Single linked list of references. */
|
||||
CLG_LogRef *refs;
|
||||
#ifdef WITH_CLOG_PTHREADS
|
||||
pthread_mutex_t types_lock;
|
||||
#endif
|
||||
@@ -322,9 +320,7 @@ static bool clg_ctx_filter_check(CLogContext *ctx, const char *identifier)
|
||||
if (flt->match[0] == '*' && flt->match[len - 1] == '*') {
|
||||
char *match = MEM_callocN(sizeof(char) * len - 1, __func__);
|
||||
memcpy(match, flt->match + 1, len - 2);
|
||||
const bool success = (strstr(identifier, match) != NULL);
|
||||
MEM_freeN(match);
|
||||
if (success) {
|
||||
if (strstr(identifier, match) != NULL) {
|
||||
return (bool)i;
|
||||
}
|
||||
}
|
||||
@@ -677,12 +673,6 @@ static void CLG_ctx_free(CLogContext *ctx)
|
||||
MEM_freeN(item);
|
||||
}
|
||||
|
||||
while (ctx->refs != NULL) {
|
||||
CLG_LogRef *item = ctx->refs;
|
||||
ctx->refs = item->next;
|
||||
item->type = NULL;
|
||||
}
|
||||
|
||||
for (uint i = 0; i < 2; i++) {
|
||||
while (ctx->filters[i] != NULL) {
|
||||
CLG_IDFilter *item = ctx->filters[i];
|
||||
@@ -779,10 +769,6 @@ void CLG_logref_init(CLG_LogRef *clg_ref)
|
||||
pthread_mutex_lock(&g_ctx->types_lock);
|
||||
#endif
|
||||
if (clg_ref->type == NULL) {
|
||||
/* Add to the refs list so we can NULL the pointers to 'type' when CLG_exit() is called. */
|
||||
clg_ref->next = g_ctx->refs;
|
||||
g_ctx->refs = clg_ref;
|
||||
|
||||
CLG_LogType *clg_ty = clg_ctx_type_find_by_name(g_ctx, clg_ref->identifier);
|
||||
if (clg_ty == NULL) {
|
||||
clg_ty = clg_ctx_type_register(g_ctx, clg_ref->identifier);
|
||||
|
@@ -71,16 +71,6 @@ if(WITH_CYCLES_STANDALONE)
|
||||
target_link_libraries(cycles ${LIBRARIES})
|
||||
cycles_target_link_libraries(cycles)
|
||||
|
||||
if(APPLE)
|
||||
if(WITH_OPENCOLORIO)
|
||||
set_property(TARGET cycles APPEND_STRING PROPERTY LINK_FLAGS " -framework IOKit")
|
||||
endif()
|
||||
if(WITH_OPENIMAGEDENOISE AND "${CMAKE_OSX_ARCHITECTURES}" STREQUAL "arm64")
|
||||
# OpenImageDenoise uses BNNS from the Accelerate framework.
|
||||
set_property(TARGET cycles APPEND_STRING PROPERTY LINK_FLAGS " -framework Accelerate")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
set_target_properties(cycles PROPERTIES INSTALL_RPATH $ORIGIN/lib)
|
||||
endif()
|
||||
|
@@ -19,16 +19,16 @@ from __future__ import annotations
|
||||
|
||||
|
||||
def _is_using_buggy_driver():
|
||||
import gpu
|
||||
import bgl
|
||||
# We need to be conservative here because in multi-GPU systems display card
|
||||
# might be quite old, but others one might be just good.
|
||||
#
|
||||
# So We shouldn't disable possible good dedicated cards just because display
|
||||
# card seems weak. And instead we only blacklist configurations which are
|
||||
# proven to cause problems.
|
||||
if gpu.platform.vendor_get() == "ATI Technologies Inc.":
|
||||
if bgl.glGetString(bgl.GL_VENDOR) == "ATI Technologies Inc.":
|
||||
import re
|
||||
version = gpu.platform.version_get()
|
||||
version = bgl.glGetString(bgl.GL_VERSION)
|
||||
if version.endswith("Compatibility Profile Context"):
|
||||
# Old HD 4xxx and 5xxx series drivers did not have driver version
|
||||
# in the version string, but those cards do not quite work and
|
||||
|
@@ -552,9 +552,7 @@ class CYCLES_RENDER_PT_light_paths_fast_gi(CyclesButtonsPanel, Panel):
|
||||
|
||||
if world:
|
||||
light = world.light_settings
|
||||
col = layout.column(align=True)
|
||||
col.prop(light, "ao_factor", text="AO Factor")
|
||||
col.prop(light, "distance", text="AO Distance")
|
||||
layout.prop(light, "distance", text="AO Distance")
|
||||
|
||||
|
||||
class CYCLES_RENDER_PT_motion_blur(CyclesButtonsPanel, Panel):
|
||||
@@ -725,7 +723,7 @@ class CYCLES_RENDER_PT_performance_tiles(CyclesButtonsPanel, Panel):
|
||||
col.prop(cscene, "tile_order", text="Order")
|
||||
|
||||
sub = col.column()
|
||||
sub.active = not rd.use_save_buffers and not cscene.use_adaptive_sampling
|
||||
sub.active = not rd.use_save_buffers
|
||||
sub.prop(cscene, "use_progressive_refine")
|
||||
|
||||
|
||||
|
@@ -83,8 +83,6 @@ struct BlenderCamera {
|
||||
BoundBox2D pano_viewplane;
|
||||
BoundBox2D viewport_camera_border;
|
||||
|
||||
float passepartout_alpha;
|
||||
|
||||
Transform matrix;
|
||||
|
||||
float offscreen_dicing_scale;
|
||||
@@ -127,7 +125,6 @@ static void blender_camera_init(BlenderCamera *bcam, BL::RenderSettings &b_rende
|
||||
bcam->pano_viewplane.top = 1.0f;
|
||||
bcam->viewport_camera_border.right = 1.0f;
|
||||
bcam->viewport_camera_border.top = 1.0f;
|
||||
bcam->passepartout_alpha = 0.5f;
|
||||
bcam->offscreen_dicing_scale = 1.0f;
|
||||
bcam->matrix = transform_identity();
|
||||
|
||||
@@ -215,8 +212,6 @@ static void blender_camera_from_object(BlenderCamera *bcam,
|
||||
|
||||
bcam->lens = b_camera.lens();
|
||||
|
||||
bcam->passepartout_alpha = b_camera.show_passepartout() ? b_camera.passepartout_alpha() : 0.0f;
|
||||
|
||||
if (b_camera.dof().use_dof()) {
|
||||
/* allow f/stop number to change aperture_size but still
|
||||
* give manual control over aperture radius */
|
||||
@@ -839,19 +834,15 @@ static void blender_camera_border(BlenderCamera *bcam,
|
||||
full_border,
|
||||
&bcam->viewport_camera_border);
|
||||
|
||||
if (b_render.use_border()) {
|
||||
bcam->border.left = b_render.border_min_x();
|
||||
bcam->border.right = b_render.border_max_x();
|
||||
bcam->border.bottom = b_render.border_min_y();
|
||||
bcam->border.top = b_render.border_max_y();
|
||||
}
|
||||
else if (bcam->passepartout_alpha == 1.0f) {
|
||||
bcam->border = full_border;
|
||||
}
|
||||
else {
|
||||
if (!b_render.use_border()) {
|
||||
return;
|
||||
}
|
||||
|
||||
bcam->border.left = b_render.border_min_x();
|
||||
bcam->border.right = b_render.border_max_x();
|
||||
bcam->border.bottom = b_render.border_min_y();
|
||||
bcam->border.top = b_render.border_max_y();
|
||||
|
||||
/* Determine viewport subset matching camera border. */
|
||||
blender_camera_border_subset(b_engine,
|
||||
b_render,
|
||||
@@ -894,7 +885,8 @@ void BlenderSync::sync_view(BL::SpaceView3D &b_v3d,
|
||||
}
|
||||
}
|
||||
|
||||
BufferParams BlenderSync::get_buffer_params(BL::SpaceView3D &b_v3d,
|
||||
BufferParams BlenderSync::get_buffer_params(BL::RenderSettings &b_render,
|
||||
BL::SpaceView3D &b_v3d,
|
||||
BL::RegionView3D &b_rv3d,
|
||||
Camera *cam,
|
||||
int width,
|
||||
@@ -910,8 +902,7 @@ BufferParams BlenderSync::get_buffer_params(BL::SpaceView3D &b_v3d,
|
||||
if (b_v3d && b_rv3d && b_rv3d.view_perspective() != BL::RegionView3D::view_perspective_CAMERA)
|
||||
use_border = b_v3d.use_render_border();
|
||||
else
|
||||
/* the camera can always have a passepartout */
|
||||
use_border = true;
|
||||
use_border = b_render.use_border();
|
||||
|
||||
if (use_border) {
|
||||
/* border render */
|
||||
|
@@ -96,49 +96,7 @@ bool BlenderSync::object_is_light(BL::Object &b_ob)
|
||||
return (b_ob_data && b_ob_data.is_a(&RNA_Light));
|
||||
}
|
||||
|
||||
void BlenderSync::sync_object_motion_init(BL::Object &b_parent, BL::Object &b_ob, Object *object)
|
||||
{
|
||||
/* Initialize motion blur for object, detecting if it's enabled and creating motion
|
||||
* steps array if so. */
|
||||
array<Transform> motion;
|
||||
object->set_motion(motion);
|
||||
|
||||
Scene::MotionType need_motion = scene->need_motion();
|
||||
if (need_motion == Scene::MOTION_NONE || !object->get_geometry()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Geometry *geom = object->get_geometry();
|
||||
geom->set_use_motion_blur(false);
|
||||
geom->set_motion_steps(0);
|
||||
|
||||
uint motion_steps;
|
||||
|
||||
if (need_motion == Scene::MOTION_BLUR) {
|
||||
motion_steps = object_motion_steps(b_parent, b_ob, Object::MAX_MOTION_STEPS);
|
||||
geom->set_motion_steps(motion_steps);
|
||||
if (motion_steps && object_use_deform_motion(b_parent, b_ob)) {
|
||||
geom->set_use_motion_blur(true);
|
||||
}
|
||||
}
|
||||
else {
|
||||
motion_steps = 3;
|
||||
geom->set_motion_steps(motion_steps);
|
||||
}
|
||||
|
||||
motion.resize(motion_steps, transform_empty());
|
||||
|
||||
if (motion_steps) {
|
||||
motion[motion_steps / 2] = object->get_tfm();
|
||||
|
||||
/* update motion socket before trying to access object->motion_time */
|
||||
object->set_motion(motion);
|
||||
|
||||
for (size_t step = 0; step < motion_steps; step++) {
|
||||
motion_times.insert(object->motion_time(step));
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Object */
|
||||
|
||||
Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
|
||||
BL::ViewLayer &b_view_layer,
|
||||
@@ -261,8 +219,10 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
|
||||
}
|
||||
|
||||
/* test if we need to sync */
|
||||
bool object_updated = object_map.add_or_update(&object, b_ob, b_parent, key) ||
|
||||
(tfm != object->get_tfm());
|
||||
bool object_updated = false;
|
||||
|
||||
if (object_map.add_or_update(&object, b_ob, b_parent, key))
|
||||
object_updated = true;
|
||||
|
||||
/* mesh sync */
|
||||
/* b_ob is owned by the iterator and will go out of scope at the end of the block.
|
||||
@@ -311,11 +271,49 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
|
||||
* transform comparison should not be needed, but duplis don't work perfect
|
||||
* in the depsgraph and may not signal changes, so this is a workaround */
|
||||
if (object->is_modified() || object_updated ||
|
||||
(object->get_geometry() && object->get_geometry()->is_modified())) {
|
||||
(object->get_geometry() && object->get_geometry()->is_modified()) ||
|
||||
tfm != object->get_tfm()) {
|
||||
object->name = b_ob.name().c_str();
|
||||
object->set_pass_id(b_ob.pass_index());
|
||||
object->set_color(get_float3(b_ob.color()));
|
||||
object->set_tfm(tfm);
|
||||
array<Transform> motion;
|
||||
object->set_motion(motion);
|
||||
|
||||
/* motion blur */
|
||||
Scene::MotionType need_motion = scene->need_motion();
|
||||
if (need_motion != Scene::MOTION_NONE && object->get_geometry()) {
|
||||
Geometry *geom = object->get_geometry();
|
||||
geom->set_use_motion_blur(false);
|
||||
geom->set_motion_steps(0);
|
||||
|
||||
uint motion_steps;
|
||||
|
||||
if (need_motion == Scene::MOTION_BLUR) {
|
||||
motion_steps = object_motion_steps(b_parent, b_ob, Object::MAX_MOTION_STEPS);
|
||||
geom->set_motion_steps(motion_steps);
|
||||
if (motion_steps && object_use_deform_motion(b_parent, b_ob)) {
|
||||
geom->set_use_motion_blur(true);
|
||||
}
|
||||
}
|
||||
else {
|
||||
motion_steps = 3;
|
||||
geom->set_motion_steps(motion_steps);
|
||||
}
|
||||
|
||||
motion.resize(motion_steps, transform_empty());
|
||||
|
||||
if (motion_steps) {
|
||||
motion[motion_steps / 2] = tfm;
|
||||
|
||||
/* update motion socket before trying to access object->motion_time */
|
||||
object->set_motion(motion);
|
||||
|
||||
for (size_t step = 0; step < motion_steps; step++) {
|
||||
motion_times.insert(object->motion_time(step));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* dupli texture coordinates and random_id */
|
||||
if (is_instance) {
|
||||
@@ -333,8 +331,6 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
|
||||
object->tag_update(scene);
|
||||
}
|
||||
|
||||
sync_object_motion_init(b_parent, b_ob, object);
|
||||
|
||||
if (is_instance) {
|
||||
/* Sync possible particle data. */
|
||||
sync_dupli_particle(b_parent, b_instance, object);
|
||||
@@ -564,12 +560,10 @@ void BlenderSync::sync_objects(BL::Depsgraph &b_depsgraph,
|
||||
if (!cancel && !motion) {
|
||||
sync_background_light(b_v3d, use_portal);
|
||||
|
||||
/* Handle removed data and modified pointers, as this may free memory, delete Nodes in the
|
||||
* right order to ensure that dependent data is freed after their users. Objects should be
|
||||
* freed before particle systems and geometries. */
|
||||
/* handle removed data and modified pointers */
|
||||
light_map.post_sync();
|
||||
object_map.post_sync();
|
||||
geometry_map.post_sync();
|
||||
object_map.post_sync();
|
||||
particle_system_map.post_sync();
|
||||
}
|
||||
|
||||
@@ -617,7 +611,7 @@ void BlenderSync::sync_motion(BL::RenderSettings &b_render,
|
||||
if (b_cam) {
|
||||
sync_camera_motion(b_render, b_cam, width, height, 0.0f);
|
||||
}
|
||||
sync_objects(b_depsgraph, b_v3d);
|
||||
sync_objects(b_depsgraph, b_v3d, 0.0f);
|
||||
}
|
||||
|
||||
/* Insert motion times from camera. Motion times from other objects
|
||||
|
@@ -35,7 +35,6 @@
|
||||
#include "util/util_path.h"
|
||||
#include "util/util_string.h"
|
||||
#include "util/util_task.h"
|
||||
#include "util/util_tbb.h"
|
||||
#include "util/util_types.h"
|
||||
|
||||
#ifdef WITH_OSL
|
||||
@@ -289,11 +288,9 @@ static PyObject *render_func(PyObject * /*self*/, PyObject *args)
|
||||
RNA_pointer_create(NULL, &RNA_Depsgraph, (ID *)PyLong_AsVoidPtr(pydepsgraph), &depsgraphptr);
|
||||
BL::Depsgraph b_depsgraph(depsgraphptr);
|
||||
|
||||
/* Allow Blender to execute other Python scripts, and isolate TBB tasks so we
|
||||
* don't get deadlocks with Blender threads accessing shared data like images. */
|
||||
python_thread_state_save(&session->python_thread_state);
|
||||
|
||||
tbb::this_task_arena::isolate([&] { session->render(b_depsgraph); });
|
||||
session->render(b_depsgraph);
|
||||
|
||||
python_thread_state_restore(&session->python_thread_state);
|
||||
|
||||
@@ -330,8 +327,7 @@ static PyObject *bake_func(PyObject * /*self*/, PyObject *args)
|
||||
|
||||
python_thread_state_save(&session->python_thread_state);
|
||||
|
||||
tbb::this_task_arena::isolate(
|
||||
[&] { session->bake(b_depsgraph, b_object, pass_type, pass_filter, width, height); });
|
||||
session->bake(b_depsgraph, b_object, pass_type, pass_filter, width, height);
|
||||
|
||||
python_thread_state_restore(&session->python_thread_state);
|
||||
|
||||
@@ -377,7 +373,7 @@ static PyObject *reset_func(PyObject * /*self*/, PyObject *args)
|
||||
|
||||
python_thread_state_save(&session->python_thread_state);
|
||||
|
||||
tbb::this_task_arena::isolate([&] { session->reset_session(b_data, b_depsgraph); });
|
||||
session->reset_session(b_data, b_depsgraph);
|
||||
|
||||
python_thread_state_restore(&session->python_thread_state);
|
||||
|
||||
@@ -399,7 +395,7 @@ static PyObject *sync_func(PyObject * /*self*/, PyObject *args)
|
||||
|
||||
python_thread_state_save(&session->python_thread_state);
|
||||
|
||||
tbb::this_task_arena::isolate([&] { session->synchronize(b_depsgraph); });
|
||||
session->synchronize(b_depsgraph);
|
||||
|
||||
python_thread_state_restore(&session->python_thread_state);
|
||||
|
||||
|
@@ -155,7 +155,7 @@ void BlenderSession::create_session()
|
||||
|
||||
/* set buffer parameters */
|
||||
BufferParams buffer_params = BlenderSync::get_buffer_params(
|
||||
b_v3d, b_rv3d, scene->camera, width, height, session_params.denoising.use);
|
||||
b_render, b_v3d, b_rv3d, scene->camera, width, height, session_params.denoising.use);
|
||||
session->reset(buffer_params, session_params.samples);
|
||||
|
||||
b_engine.use_highlight_tiles(session_params.progressive_refine == false);
|
||||
@@ -237,12 +237,10 @@ void BlenderSession::reset_session(BL::BlendData &b_data, BL::Depsgraph &b_depsg
|
||||
sync->sync_recalc(b_depsgraph, b_v3d);
|
||||
}
|
||||
|
||||
BL::Object b_camera_override(b_engine.camera_override());
|
||||
sync->sync_camera(b_render, b_camera_override, width, height, "");
|
||||
|
||||
BL::SpaceView3D b_null_space_view3d(PointerRNA_NULL);
|
||||
BL::RegionView3D b_null_region_view3d(PointerRNA_NULL);
|
||||
BufferParams buffer_params = BlenderSync::get_buffer_params(b_null_space_view3d,
|
||||
BufferParams buffer_params = BlenderSync::get_buffer_params(b_render,
|
||||
b_null_space_view3d,
|
||||
b_null_region_view3d,
|
||||
scene->camera,
|
||||
width,
|
||||
@@ -485,7 +483,7 @@ void BlenderSession::render(BL::Depsgraph &b_depsgraph_)
|
||||
SessionParams session_params = BlenderSync::get_session_params(
|
||||
b_engine, b_userpref, b_scene, background, b_view_layer);
|
||||
BufferParams buffer_params = BlenderSync::get_buffer_params(
|
||||
b_v3d, b_rv3d, scene->camera, width, height, session_params.denoising.use);
|
||||
b_render, b_v3d, b_rv3d, scene->camera, width, height, session_params.denoising.use);
|
||||
|
||||
/* temporary render result to find needed passes and views */
|
||||
BL::RenderResult b_rr = begin_render_result(
|
||||
@@ -809,7 +807,7 @@ void BlenderSession::synchronize(BL::Depsgraph &b_depsgraph_)
|
||||
|
||||
/* get buffer parameters */
|
||||
BufferParams buffer_params = BlenderSync::get_buffer_params(
|
||||
b_v3d, b_rv3d, scene->camera, width, height, session_params.denoising.use);
|
||||
b_render, b_v3d, b_rv3d, scene->camera, width, height, session_params.denoising.use);
|
||||
|
||||
if (!buffer_params.denoising_data_pass) {
|
||||
session_params.denoising.use = false;
|
||||
@@ -888,7 +886,7 @@ bool BlenderSession::draw(int w, int h)
|
||||
SessionParams session_params = BlenderSync::get_session_params(
|
||||
b_engine, b_userpref, b_scene, background);
|
||||
BufferParams buffer_params = BlenderSync::get_buffer_params(
|
||||
b_v3d, b_rv3d, scene->camera, width, height, session_params.denoising.use);
|
||||
b_render, b_v3d, b_rv3d, scene->camera, width, height, session_params.denoising.use);
|
||||
bool session_pause = BlenderSync::get_session_pause(b_scene, background);
|
||||
|
||||
if (session_pause == false) {
|
||||
@@ -906,7 +904,7 @@ bool BlenderSession::draw(int w, int h)
|
||||
|
||||
/* draw */
|
||||
BufferParams buffer_params = BlenderSync::get_buffer_params(
|
||||
b_v3d, b_rv3d, scene->camera, width, height, session->params.denoising.use);
|
||||
b_render, b_v3d, b_rv3d, scene->camera, width, height, session->params.denoising.use);
|
||||
DeviceDrawParams draw_params;
|
||||
|
||||
if (session->params.display_buffer_linear) {
|
||||
|
@@ -1373,7 +1373,7 @@ void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d,
|
||||
BlenderViewportParameters new_viewport_parameters(b_v3d);
|
||||
|
||||
if (world_recalc || update_all || b_world.ptr.data != world_map ||
|
||||
viewport_parameters.shader_modified(new_viewport_parameters)) {
|
||||
viewport_parameters.modified(new_viewport_parameters)) {
|
||||
Shader *shader = scene->default_background;
|
||||
ShaderGraph *graph = new ShaderGraph();
|
||||
|
||||
@@ -1501,8 +1501,8 @@ void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d,
|
||||
background->set_transparent_roughness_threshold(0.0f);
|
||||
}
|
||||
|
||||
background->set_use_shader(view_layer.use_background_shader ||
|
||||
viewport_parameters.use_custom_shader());
|
||||
background->set_use_shader(view_layer.use_background_shader |
|
||||
viewport_parameters.custom_viewport_parameters());
|
||||
background->set_use_ao(background->get_use_ao() && view_layer.use_background_ao);
|
||||
|
||||
background->tag_update(scene);
|
||||
@@ -1553,9 +1553,13 @@ void BlenderSync::sync_lights(BL::Depsgraph &b_depsgraph, bool update_all)
|
||||
void BlenderSync::sync_shaders(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d)
|
||||
{
|
||||
/* for auto refresh images */
|
||||
ImageManager *image_manager = scene->image_manager;
|
||||
const int frame = b_scene.frame_current();
|
||||
const bool auto_refresh_update = image_manager->set_animation_frame_update(frame);
|
||||
bool auto_refresh_update = false;
|
||||
|
||||
if (preview) {
|
||||
ImageManager *image_manager = scene->image_manager;
|
||||
int frame = b_scene.frame_current();
|
||||
auto_refresh_update = image_manager->set_animation_frame_update(frame);
|
||||
}
|
||||
|
||||
shader_map.pre_sync();
|
||||
|
||||
|
@@ -69,8 +69,7 @@ BlenderSync::BlenderSync(BL::RenderEngine &b_engine,
|
||||
experimental(false),
|
||||
dicing_rate(1.0f),
|
||||
max_subdivisions(12),
|
||||
progress(progress),
|
||||
has_updates_(true)
|
||||
progress(progress)
|
||||
{
|
||||
PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
|
||||
dicing_rate = preview ? RNA_float_get(&cscene, "preview_dicing_rate") :
|
||||
@@ -85,9 +84,7 @@ BlenderSync::~BlenderSync()
|
||||
void BlenderSync::reset(BL::BlendData &b_data, BL::Scene &b_scene)
|
||||
{
|
||||
/* Update data and scene pointers in case they change in session reset,
|
||||
* for example after undo.
|
||||
* Note that we do not modify the `has_updates_` flag here because the sync
|
||||
* reset is also used during viewport navigation. */
|
||||
* for example after undo. */
|
||||
this->b_data = b_data;
|
||||
this->b_scene = b_scene;
|
||||
}
|
||||
@@ -120,8 +117,6 @@ void BlenderSync::sync_recalc(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d
|
||||
}
|
||||
|
||||
if (dicing_prop_changed) {
|
||||
has_updates_ = true;
|
||||
|
||||
for (const pair<const GeometryKey, Geometry *> &iter : geometry_map.key_to_scene_data()) {
|
||||
Geometry *geom = iter.second;
|
||||
if (geom->is_mesh()) {
|
||||
@@ -138,12 +133,6 @@ void BlenderSync::sync_recalc(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d
|
||||
|
||||
/* Iterate over all IDs in this depsgraph. */
|
||||
for (BL::DepsgraphUpdate &b_update : b_depsgraph.updates) {
|
||||
/* TODO(sergey): Can do more selective filter here. For example, ignore changes made to
|
||||
* screen datablock. Note that sync_data() needs to be called after object deletion, and
|
||||
* currently this is ensured by the scene ID tagged for update, which sets the `has_updates_`
|
||||
* flag. */
|
||||
has_updates_ = true;
|
||||
|
||||
BL::ID b_id(b_update.id());
|
||||
|
||||
/* Material */
|
||||
@@ -224,13 +213,9 @@ void BlenderSync::sync_recalc(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d
|
||||
|
||||
if (b_v3d) {
|
||||
BlenderViewportParameters new_viewport_parameters(b_v3d);
|
||||
|
||||
if (viewport_parameters.shader_modified(new_viewport_parameters)) {
|
||||
if (viewport_parameters.modified(new_viewport_parameters)) {
|
||||
world_recalc = true;
|
||||
has_updates_ = true;
|
||||
}
|
||||
|
||||
has_updates_ |= viewport_parameters.modified(new_viewport_parameters);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -242,15 +227,11 @@ void BlenderSync::sync_data(BL::RenderSettings &b_render,
|
||||
int height,
|
||||
void **python_thread_state)
|
||||
{
|
||||
if (!has_updates_) {
|
||||
return;
|
||||
}
|
||||
|
||||
scoped_timer timer;
|
||||
|
||||
BL::ViewLayer b_view_layer = b_depsgraph.view_layer_eval();
|
||||
|
||||
sync_view_layer(b_view_layer);
|
||||
sync_view_layer(b_v3d, b_view_layer);
|
||||
sync_integrator();
|
||||
sync_film(b_v3d);
|
||||
sync_shaders(b_depsgraph, b_v3d);
|
||||
@@ -273,8 +254,6 @@ void BlenderSync::sync_data(BL::RenderSettings &b_render,
|
||||
free_data_after_sync(b_depsgraph);
|
||||
|
||||
VLOG(1) << "Total time spent synchronizing data: " << timer.get_time();
|
||||
|
||||
has_updates_ = false;
|
||||
}
|
||||
|
||||
/* Integrator */
|
||||
@@ -445,7 +424,7 @@ void BlenderSync::sync_film(BL::SpaceView3D &b_v3d)
|
||||
|
||||
/* Render Layer */
|
||||
|
||||
void BlenderSync::sync_view_layer(BL::ViewLayer &b_view_layer)
|
||||
void BlenderSync::sync_view_layer(BL::SpaceView3D & /*b_v3d*/, BL::ViewLayer &b_view_layer)
|
||||
{
|
||||
view_layer.name = b_view_layer.name();
|
||||
|
||||
@@ -760,18 +739,12 @@ void BlenderSync::free_data_after_sync(BL::Depsgraph &b_depsgraph)
|
||||
* caches to be releases from blender side in order to reduce peak memory
|
||||
* footprint during synchronization process.
|
||||
*/
|
||||
|
||||
const bool is_interface_locked = b_engine.render() && b_engine.render().use_lock_interface();
|
||||
const bool is_persistent_data = b_engine.render() && b_engine.render().use_persistent_data();
|
||||
const bool can_free_caches =
|
||||
(BlenderSession::headless || is_interface_locked) &&
|
||||
/* Baking re-uses the depsgraph multiple times, clearing crashes
|
||||
* reading un-evaluated mesh data which isn't aligned with the
|
||||
* geometry we're baking, see T71012. */
|
||||
!scene->bake_manager->get_baking() &&
|
||||
/* Persistent data must main caches for performance and correctness. */
|
||||
!is_persistent_data;
|
||||
|
||||
const bool can_free_caches = (BlenderSession::headless || is_interface_locked) &&
|
||||
/* Baking re-uses the depsgraph multiple times, clearing crashes
|
||||
* reading un-evaluated mesh data which isn't aligned with the
|
||||
* geometry we're baking, see T71012. */
|
||||
!scene->bake_manager->get_baking();
|
||||
if (!can_free_caches) {
|
||||
return;
|
||||
}
|
||||
@@ -896,9 +869,6 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine &b_engine,
|
||||
/* Clamp samples. */
|
||||
params.samples = min(params.samples, Integrator::MAX_SAMPLES);
|
||||
|
||||
/* Adaptive sampling. */
|
||||
params.adaptive_sampling = RNA_boolean_get(&cscene, "use_adaptive_sampling");
|
||||
|
||||
/* tiles */
|
||||
const bool is_cpu = (params.device.type == DEVICE_CPU);
|
||||
if (!is_cpu && !background) {
|
||||
@@ -951,7 +921,7 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine &b_engine,
|
||||
BL::RenderSettings b_r = b_scene.render();
|
||||
params.progressive_refine = b_engine.is_preview() ||
|
||||
get_boolean(cscene, "use_progressive_refine");
|
||||
if (b_r.use_save_buffers() || params.adaptive_sampling)
|
||||
if (b_r.use_save_buffers())
|
||||
params.progressive_refine = false;
|
||||
|
||||
if (background) {
|
||||
@@ -987,6 +957,8 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine &b_engine,
|
||||
params.use_profiling = params.device.has_profiling && !b_engine.is_preview() && background &&
|
||||
BlenderSession::print_render_stats;
|
||||
|
||||
params.adaptive_sampling = RNA_boolean_get(&cscene, "use_adaptive_sampling");
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
|
@@ -73,7 +73,7 @@ class BlenderSync {
|
||||
int width,
|
||||
int height,
|
||||
void **python_thread_state);
|
||||
void sync_view_layer(BL::ViewLayer &b_view_layer);
|
||||
void sync_view_layer(BL::SpaceView3D &b_v3d, BL::ViewLayer &b_view_layer);
|
||||
vector<Pass> sync_render_passes(BL::Scene &b_scene,
|
||||
BL::RenderLayer &b_render_layer,
|
||||
BL::ViewLayer &b_view_layer,
|
||||
@@ -104,7 +104,8 @@ class BlenderSync {
|
||||
bool background,
|
||||
BL::ViewLayer b_view_layer = BL::ViewLayer(PointerRNA_NULL));
|
||||
static bool get_session_pause(BL::Scene &b_scene, bool background);
|
||||
static BufferParams get_buffer_params(BL::SpaceView3D &b_v3d,
|
||||
static BufferParams get_buffer_params(BL::RenderSettings &b_render,
|
||||
BL::SpaceView3D &b_v3d,
|
||||
BL::RegionView3D &b_rv3d,
|
||||
Camera *cam,
|
||||
int width,
|
||||
@@ -149,7 +150,6 @@ class BlenderSync {
|
||||
BlenderObjectCulling &culling,
|
||||
bool *use_portal,
|
||||
TaskPool *geom_task_pool);
|
||||
void sync_object_motion_init(BL::Object &b_parent, BL::Object &b_ob, Object *object);
|
||||
|
||||
bool sync_object_attributes(BL::DepsgraphObjectInstance &b_instance, Object *object);
|
||||
|
||||
@@ -263,12 +263,6 @@ class BlenderSync {
|
||||
} view_layer;
|
||||
|
||||
Progress &progress;
|
||||
|
||||
protected:
|
||||
/* Indicates that `sync_recalc()` detected changes in the scene.
|
||||
* If this flag is false then the data is considered to be up-to-date and will not be
|
||||
* synchronized at all. */
|
||||
bool has_updates_ = true;
|
||||
};
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
@@ -13,7 +13,6 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "blender_viewport.h"
|
||||
|
||||
#include "blender_util.h"
|
||||
@@ -26,39 +25,29 @@ BlenderViewportParameters::BlenderViewportParameters()
|
||||
studiolight_rotate_z(0.0f),
|
||||
studiolight_intensity(1.0f),
|
||||
studiolight_background_alpha(1.0f),
|
||||
display_pass(PASS_COMBINED)
|
||||
studiolight_path(ustring())
|
||||
{
|
||||
}
|
||||
|
||||
BlenderViewportParameters::BlenderViewportParameters(BL::SpaceView3D &b_v3d)
|
||||
: BlenderViewportParameters()
|
||||
{
|
||||
if (!b_v3d) {
|
||||
return;
|
||||
}
|
||||
|
||||
BL::View3DShading shading = b_v3d.shading();
|
||||
PointerRNA cshading = RNA_pointer_get(&shading.ptr, "cycles");
|
||||
|
||||
/* We only copy the shading parameters if we are in look dev mode. otherwise
|
||||
/* We only copy the parameters if we are in look dev mode. otherwise
|
||||
* defaults are being used. These defaults mimic normal render settings */
|
||||
if (shading.type() == BL::View3DShading::type_RENDERED) {
|
||||
use_scene_world = shading.use_scene_world_render();
|
||||
use_scene_lights = shading.use_scene_lights_render();
|
||||
|
||||
if (b_v3d && b_v3d.shading().type() == BL::View3DShading::type_RENDERED) {
|
||||
use_scene_world = b_v3d.shading().use_scene_world_render();
|
||||
use_scene_lights = b_v3d.shading().use_scene_lights_render();
|
||||
if (!use_scene_world) {
|
||||
studiolight_rotate_z = shading.studiolight_rotate_z();
|
||||
studiolight_intensity = shading.studiolight_intensity();
|
||||
studiolight_background_alpha = shading.studiolight_background_alpha();
|
||||
studiolight_path = shading.selected_studio_light().path();
|
||||
studiolight_rotate_z = b_v3d.shading().studiolight_rotate_z();
|
||||
studiolight_intensity = b_v3d.shading().studiolight_intensity();
|
||||
studiolight_background_alpha = b_v3d.shading().studiolight_background_alpha();
|
||||
studiolight_path = b_v3d.shading().selected_studio_light().path();
|
||||
}
|
||||
}
|
||||
|
||||
/* Film. */
|
||||
display_pass = (PassType)get_enum(cshading, "render_pass", -1, -1);
|
||||
}
|
||||
|
||||
bool BlenderViewportParameters::shader_modified(const BlenderViewportParameters &other) const
|
||||
/* Check if two instances are different. */
|
||||
const bool BlenderViewportParameters::modified(const BlenderViewportParameters &other) const
|
||||
{
|
||||
return use_scene_world != other.use_scene_world || use_scene_lights != other.use_scene_lights ||
|
||||
studiolight_rotate_z != other.studiolight_rotate_z ||
|
||||
@@ -67,26 +56,26 @@ bool BlenderViewportParameters::shader_modified(const BlenderViewportParameters
|
||||
studiolight_path != other.studiolight_path;
|
||||
}
|
||||
|
||||
bool BlenderViewportParameters::film_modified(const BlenderViewportParameters &other) const
|
||||
{
|
||||
return display_pass != other.display_pass;
|
||||
}
|
||||
|
||||
bool BlenderViewportParameters::modified(const BlenderViewportParameters &other) const
|
||||
{
|
||||
return shader_modified(other) || film_modified(other);
|
||||
}
|
||||
|
||||
bool BlenderViewportParameters::use_custom_shader() const
|
||||
const bool BlenderViewportParameters::custom_viewport_parameters() const
|
||||
{
|
||||
return !(use_scene_world && use_scene_lights);
|
||||
}
|
||||
|
||||
PassType BlenderViewportParameters::get_viewport_display_render_pass(BL::SpaceView3D &b_v3d)
|
||||
{
|
||||
PassType display_pass = PASS_NONE;
|
||||
if (b_v3d) {
|
||||
BL::View3DShading b_view3dshading = b_v3d.shading();
|
||||
PointerRNA cshading = RNA_pointer_get(&b_view3dshading.ptr, "cycles");
|
||||
display_pass = (PassType)get_enum(cshading, "render_pass", -1, -1);
|
||||
}
|
||||
return display_pass;
|
||||
}
|
||||
|
||||
PassType update_viewport_display_passes(BL::SpaceView3D &b_v3d, vector<Pass> &passes)
|
||||
{
|
||||
if (b_v3d) {
|
||||
const BlenderViewportParameters viewport_parameters(b_v3d);
|
||||
const PassType display_pass = viewport_parameters.display_pass;
|
||||
PassType display_pass = BlenderViewportParameters::get_viewport_display_render_pass(b_v3d);
|
||||
|
||||
passes.clear();
|
||||
Pass::add(display_pass, passes);
|
||||
|
@@ -18,18 +18,17 @@
|
||||
#define __BLENDER_VIEWPORT_H__
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_blender_cpp.h"
|
||||
#include "RNA_types.h"
|
||||
|
||||
#include "render/film.h"
|
||||
#include "util/util_param.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
class BlenderViewportParameters {
|
||||
public:
|
||||
/* Shader. */
|
||||
private:
|
||||
bool use_scene_world;
|
||||
bool use_scene_lights;
|
||||
float studiolight_rotate_z;
|
||||
@@ -37,24 +36,17 @@ class BlenderViewportParameters {
|
||||
float studiolight_background_alpha;
|
||||
ustring studiolight_path;
|
||||
|
||||
/* Film. */
|
||||
PassType display_pass;
|
||||
|
||||
BlenderViewportParameters();
|
||||
explicit BlenderViewportParameters(BL::SpaceView3D &b_v3d);
|
||||
BlenderViewportParameters(BL::SpaceView3D &b_v3d);
|
||||
|
||||
/* Check whether any of shading related settings are different from the given parameters. */
|
||||
bool shader_modified(const BlenderViewportParameters &other) const;
|
||||
const bool modified(const BlenderViewportParameters &other) const;
|
||||
const bool custom_viewport_parameters() const;
|
||||
friend class BlenderSync;
|
||||
|
||||
/* Check whether any of film related settings are different from the given parameters. */
|
||||
bool film_modified(const BlenderViewportParameters &other) const;
|
||||
|
||||
/* Check whether any of settings are different from the given parameters. */
|
||||
bool modified(const BlenderViewportParameters &other) const;
|
||||
|
||||
/* Returns truth when a custom shader defined by the viewport is to be used instead of the
|
||||
* regular background shader or scene light. */
|
||||
bool use_custom_shader() const;
|
||||
public:
|
||||
/* Retrieve the render pass that needs to be displayed on the given `SpaceView3D`
|
||||
* When the `b_v3d` parameter is not given `PASS_NONE` will be returned. */
|
||||
static PassType get_viewport_display_render_pass(BL::SpaceView3D &b_v3d);
|
||||
};
|
||||
|
||||
PassType update_viewport_display_passes(BL::SpaceView3D &b_v3d, vector<Pass> &passes);
|
||||
|
@@ -17,8 +17,6 @@
|
||||
|
||||
#ifdef WITH_OPTIX
|
||||
|
||||
# include "device/device.h"
|
||||
|
||||
# include "bvh/bvh_optix.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
@@ -28,7 +26,6 @@ BVHOptiX::BVHOptiX(const BVHParams ¶ms_,
|
||||
const vector<Object *> &objects_,
|
||||
Device *device)
|
||||
: BVH(params_, geometry_, objects_),
|
||||
device(device),
|
||||
traversable_handle(0),
|
||||
as_data(device, params_.top_level ? "optix tlas" : "optix blas", false),
|
||||
motion_transform_data(device, "optix motion transform", false)
|
||||
@@ -37,9 +34,7 @@ BVHOptiX::BVHOptiX(const BVHParams ¶ms_,
|
||||
|
||||
BVHOptiX::~BVHOptiX()
|
||||
{
|
||||
// Acceleration structure memory is delayed freed on device, since deleting the
|
||||
// BVH may happen while still being used for rendering.
|
||||
device->release_optix_bvh(this);
|
||||
// Acceleration structure memory is freed via the 'as_data' destructor
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
@@ -28,7 +28,6 @@ CCL_NAMESPACE_BEGIN
|
||||
|
||||
class BVHOptiX : public BVH {
|
||||
public:
|
||||
Device *device;
|
||||
uint64_t traversable_handle;
|
||||
device_only_memory<char> as_data;
|
||||
device_only_memory<char> motion_transform_data;
|
||||
|
@@ -61,6 +61,7 @@ enum DeviceTypeMask {
|
||||
};
|
||||
|
||||
enum DeviceKernelStatus {
|
||||
DEVICE_KERNEL_WAITING_FOR_FEATURE_KERNEL = 0,
|
||||
DEVICE_KERNEL_FEATURE_KERNEL_AVAILABLE,
|
||||
DEVICE_KERNEL_USING_FEATURE_KERNEL,
|
||||
DEVICE_KERNEL_FEATURE_KERNEL_INVALID,
|
||||
@@ -426,9 +427,6 @@ class Device {
|
||||
/* acceleration structure building */
|
||||
virtual void build_bvh(BVH *bvh, Progress &progress, bool refit);
|
||||
|
||||
/* OptiX specific destructor. */
|
||||
virtual void release_optix_bvh(BVH * /*bvh*/){};
|
||||
|
||||
#ifdef WITH_NETWORK
|
||||
/* networking */
|
||||
void server_run();
|
||||
|
@@ -35,54 +35,10 @@ device_memory::device_memory(Device *device, const char *name, MemoryType type)
|
||||
device_pointer(0),
|
||||
host_pointer(0),
|
||||
shared_pointer(0),
|
||||
shared_counter(0),
|
||||
original_device_ptr(0),
|
||||
original_device_size(0),
|
||||
original_device(0),
|
||||
need_realloc_(false),
|
||||
modified(false)
|
||||
shared_counter(0)
|
||||
{
|
||||
}
|
||||
|
||||
device_memory::device_memory(device_memory &&other) noexcept
|
||||
: data_type(other.data_type),
|
||||
data_elements(other.data_elements),
|
||||
data_size(other.data_size),
|
||||
device_size(other.device_size),
|
||||
data_width(other.data_width),
|
||||
data_height(other.data_height),
|
||||
data_depth(other.data_depth),
|
||||
type(other.type),
|
||||
name(other.name),
|
||||
device(other.device),
|
||||
device_pointer(other.device_pointer),
|
||||
host_pointer(other.host_pointer),
|
||||
shared_pointer(other.shared_pointer),
|
||||
shared_counter(other.shared_counter),
|
||||
original_device_ptr(other.original_device_ptr),
|
||||
original_device_size(other.original_device_size),
|
||||
original_device(other.original_device),
|
||||
need_realloc_(other.need_realloc_),
|
||||
modified(other.modified)
|
||||
{
|
||||
other.data_elements = 0;
|
||||
other.data_size = 0;
|
||||
other.device_size = 0;
|
||||
other.data_width = 0;
|
||||
other.data_height = 0;
|
||||
other.data_depth = 0;
|
||||
other.device = 0;
|
||||
other.device_pointer = 0;
|
||||
other.host_pointer = 0;
|
||||
other.shared_pointer = 0;
|
||||
other.shared_counter = 0;
|
||||
other.original_device_ptr = 0;
|
||||
other.original_device_size = 0;
|
||||
other.original_device = 0;
|
||||
other.need_realloc_ = false;
|
||||
other.modified = false;
|
||||
}
|
||||
|
||||
device_memory::~device_memory()
|
||||
{
|
||||
assert(shared_pointer == 0);
|
||||
|
@@ -238,7 +238,6 @@ class device_memory {
|
||||
|
||||
/* Only create through subclasses. */
|
||||
device_memory(Device *device, const char *name, MemoryType type);
|
||||
device_memory(device_memory &&other) noexcept;
|
||||
|
||||
/* No copying allowed. */
|
||||
device_memory(const device_memory &) = delete;
|
||||
@@ -278,10 +277,6 @@ template<typename T> class device_only_memory : public device_memory {
|
||||
data_elements = max(device_type_traits<T>::num_elements, 1);
|
||||
}
|
||||
|
||||
device_only_memory(device_only_memory &&other) noexcept : device_memory(std::move(other))
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~device_only_memory()
|
||||
{
|
||||
free();
|
||||
|
@@ -232,6 +232,10 @@ class MultiDevice : public Device {
|
||||
foreach (SubDevice &sub, devices) {
|
||||
DeviceKernelStatus subresult = sub.device->get_active_kernel_switch_state();
|
||||
switch (subresult) {
|
||||
case DEVICE_KERNEL_WAITING_FOR_FEATURE_KERNEL:
|
||||
result = subresult;
|
||||
break;
|
||||
|
||||
case DEVICE_KERNEL_FEATURE_KERNEL_INVALID:
|
||||
case DEVICE_KERNEL_FEATURE_KERNEL_AVAILABLE:
|
||||
return subresult;
|
||||
|
@@ -193,9 +193,6 @@ class OptiXDevice : public CUDADevice {
|
||||
device_only_memory<unsigned char> denoiser_state;
|
||||
int denoiser_input_passes = 0;
|
||||
|
||||
vector<device_only_memory<char>> delayed_free_bvh_memory;
|
||||
thread_mutex delayed_free_bvh_mutex;
|
||||
|
||||
public:
|
||||
OptiXDevice(DeviceInfo &info_, Stats &stats_, Profiler &profiler_, bool background_)
|
||||
: CUDADevice(info_, stats_, profiler_, background_),
|
||||
@@ -261,8 +258,6 @@ class OptiXDevice : public CUDADevice {
|
||||
// Make CUDA context current
|
||||
const CUDAContextScope scope(cuContext);
|
||||
|
||||
free_bvh_memory_delayed();
|
||||
|
||||
sbt_data.free();
|
||||
texture_info.free();
|
||||
launch_params.free();
|
||||
@@ -726,11 +721,7 @@ class OptiXDevice : public CUDADevice {
|
||||
}
|
||||
}
|
||||
else if (task.type == DeviceTask::SHADER) {
|
||||
// CUDA kernels are used when doing baking
|
||||
if (optix_module == NULL)
|
||||
CUDADevice::shader(task);
|
||||
else
|
||||
launch_shader_eval(task, thread_index);
|
||||
launch_shader_eval(task, thread_index);
|
||||
}
|
||||
else if (task.type == DeviceTask::DENOISE_BUFFER) {
|
||||
// Set up a single tile that covers the whole task and denoise it
|
||||
@@ -1306,8 +1297,6 @@ class OptiXDevice : public CUDADevice {
|
||||
return;
|
||||
}
|
||||
|
||||
free_bvh_memory_delayed();
|
||||
|
||||
BVHOptiX *const bvh_optix = static_cast<BVHOptiX *>(bvh);
|
||||
|
||||
progress.set_substatus("Building OptiX acceleration structure");
|
||||
@@ -1778,24 +1767,6 @@ class OptiXDevice : public CUDADevice {
|
||||
}
|
||||
}
|
||||
|
||||
void release_optix_bvh(BVH *bvh) override
|
||||
{
|
||||
thread_scoped_lock lock(delayed_free_bvh_mutex);
|
||||
/* Do delayed free of BVH memory, since geometry holding BVH might be deleted
|
||||
* while GPU is still rendering. */
|
||||
BVHOptiX *const bvh_optix = static_cast<BVHOptiX *>(bvh);
|
||||
|
||||
delayed_free_bvh_memory.emplace_back(std::move(bvh_optix->as_data));
|
||||
delayed_free_bvh_memory.emplace_back(std::move(bvh_optix->motion_transform_data));
|
||||
bvh_optix->traversable_handle = 0;
|
||||
}
|
||||
|
||||
void free_bvh_memory_delayed()
|
||||
{
|
||||
thread_scoped_lock lock(delayed_free_bvh_mutex);
|
||||
delayed_free_bvh_memory.free_memory();
|
||||
}
|
||||
|
||||
void const_copy_to(const char *name, void *host, size_t size) override
|
||||
{
|
||||
// Set constant memory for CUDA module
|
||||
|
@@ -269,6 +269,7 @@ class OpenCLDevice : public Device {
|
||||
cl_device_id cdDevice;
|
||||
cl_int ciErr;
|
||||
int device_num;
|
||||
bool use_preview_kernels;
|
||||
|
||||
class OpenCLProgram {
|
||||
public:
|
||||
@@ -368,7 +369,8 @@ class OpenCLDevice : public Device {
|
||||
/* Load the kernels and put the created kernels in the given
|
||||
* `programs` parameter. */
|
||||
void load_kernels(vector<OpenCLProgram *> &programs,
|
||||
const DeviceRequestedFeatures &requested_features);
|
||||
const DeviceRequestedFeatures &requested_features,
|
||||
bool is_preview = false);
|
||||
};
|
||||
|
||||
DeviceSplitKernel *split_kernel;
|
||||
@@ -380,6 +382,7 @@ class OpenCLDevice : public Device {
|
||||
OpenCLProgram denoising_program;
|
||||
|
||||
OpenCLSplitPrograms kernel_programs;
|
||||
OpenCLSplitPrograms preview_programs;
|
||||
|
||||
typedef map<string, device_vector<uchar> *> ConstMemMap;
|
||||
typedef map<string, device_ptr> MemMap;
|
||||
@@ -409,6 +412,7 @@ class OpenCLDevice : public Device {
|
||||
string device_md5_hash(string kernel_custom_build_options = "");
|
||||
bool load_kernels(const DeviceRequestedFeatures &requested_features);
|
||||
void load_required_kernels(const DeviceRequestedFeatures &requested_features);
|
||||
void load_preview_kernels();
|
||||
|
||||
bool wait_for_availability(const DeviceRequestedFeatures &requested_features);
|
||||
DeviceKernelStatus get_active_kernel_switch_state();
|
||||
@@ -418,7 +422,8 @@ class OpenCLDevice : public Device {
|
||||
/* Get the program file name to compile (*.cl) for the given kernel */
|
||||
const string get_opencl_program_filename(const string &kernel_name);
|
||||
string get_build_options(const DeviceRequestedFeatures &requested_features,
|
||||
const string &opencl_program_name);
|
||||
const string &opencl_program_name,
|
||||
bool preview_kernel = false);
|
||||
/* Enable the default features to reduce recompilation events */
|
||||
void enable_default_features(DeviceRequestedFeatures &features);
|
||||
|
||||
|
@@ -107,7 +107,8 @@ void OpenCLDevice::enable_default_features(DeviceRequestedFeatures &features)
|
||||
}
|
||||
|
||||
string OpenCLDevice::get_build_options(const DeviceRequestedFeatures &requested_features,
|
||||
const string &opencl_program_name)
|
||||
const string &opencl_program_name,
|
||||
bool preview_kernel)
|
||||
{
|
||||
/* first check for non-split kernel programs */
|
||||
if (opencl_program_name == "base" || opencl_program_name == "denoising") {
|
||||
@@ -184,7 +185,13 @@ string OpenCLDevice::get_build_options(const DeviceRequestedFeatures &requested_
|
||||
enable_default_features(nofeatures);
|
||||
|
||||
/* Add program specific optimized compile directives */
|
||||
if (opencl_program_name == "split_do_volume" && !requested_features.use_volume) {
|
||||
if (preview_kernel) {
|
||||
DeviceRequestedFeatures preview_features;
|
||||
preview_features.use_hair = true;
|
||||
build_options += "-D__KERNEL_AO_PREVIEW__ ";
|
||||
build_options += preview_features.get_build_options();
|
||||
}
|
||||
else if (opencl_program_name == "split_do_volume" && !requested_features.use_volume) {
|
||||
build_options += nofeatures.get_build_options();
|
||||
}
|
||||
else {
|
||||
@@ -231,7 +238,9 @@ OpenCLDevice::OpenCLSplitPrograms::~OpenCLSplitPrograms()
|
||||
}
|
||||
|
||||
void OpenCLDevice::OpenCLSplitPrograms::load_kernels(
|
||||
vector<OpenCLProgram *> &programs, const DeviceRequestedFeatures &requested_features)
|
||||
vector<OpenCLProgram *> &programs,
|
||||
const DeviceRequestedFeatures &requested_features,
|
||||
bool is_preview)
|
||||
{
|
||||
if (!requested_features.use_baking) {
|
||||
# define ADD_SPLIT_KERNEL_BUNDLE_PROGRAM(kernel_name) \
|
||||
@@ -242,7 +251,7 @@ void OpenCLDevice::OpenCLSplitPrograms::load_kernels(
|
||||
device, \
|
||||
program_name_##kernel_name, \
|
||||
"kernel_" #kernel_name ".cl", \
|
||||
device->get_build_options(requested_features, program_name_##kernel_name)); \
|
||||
device->get_build_options(requested_features, program_name_##kernel_name, is_preview)); \
|
||||
program_##kernel_name.add_kernel(ustring("path_trace_" #kernel_name)); \
|
||||
programs.push_back(&program_##kernel_name);
|
||||
|
||||
@@ -250,7 +259,7 @@ void OpenCLDevice::OpenCLSplitPrograms::load_kernels(
|
||||
ADD_SPLIT_KERNEL_PROGRAM(subsurface_scatter);
|
||||
ADD_SPLIT_KERNEL_PROGRAM(direct_lighting);
|
||||
ADD_SPLIT_KERNEL_PROGRAM(indirect_background);
|
||||
if (requested_features.use_volume) {
|
||||
if (requested_features.use_volume || is_preview) {
|
||||
ADD_SPLIT_KERNEL_PROGRAM(do_volume);
|
||||
}
|
||||
ADD_SPLIT_KERNEL_PROGRAM(shader_eval);
|
||||
@@ -265,7 +274,7 @@ void OpenCLDevice::OpenCLSplitPrograms::load_kernels(
|
||||
device,
|
||||
"split_bundle",
|
||||
"kernel_split_bundle.cl",
|
||||
device->get_build_options(requested_features, "split_bundle"));
|
||||
device->get_build_options(requested_features, "split_bundle", is_preview));
|
||||
|
||||
ADD_SPLIT_KERNEL_BUNDLE_PROGRAM(data_init);
|
||||
ADD_SPLIT_KERNEL_BUNDLE_PROGRAM(state_buffer_size);
|
||||
@@ -394,7 +403,7 @@ class OpenCLSplitKernel : public DeviceSplitKernel {
|
||||
device,
|
||||
program_name,
|
||||
device->get_opencl_program_filename(kernel_name),
|
||||
device->get_build_options(requested_features, program_name));
|
||||
device->get_build_options(requested_features, program_name, device->use_preview_kernels));
|
||||
|
||||
kernel->program.add_kernel(ustring("path_trace_" + kernel_name));
|
||||
kernel->program.load();
|
||||
@@ -560,11 +569,6 @@ class OpenCLSplitKernel : public DeviceSplitKernel {
|
||||
size_t num_elements = max_elements_for_max_buffer_size(kg, data, max_buffer_size);
|
||||
int2 global_size = make_int2(max(round_down((int)sqrt(num_elements), 64), 64),
|
||||
(int)sqrt(num_elements));
|
||||
|
||||
if (device->info.description.find("Intel") != string::npos) {
|
||||
global_size = make_int2(min(512, global_size.x), min(512, global_size.y));
|
||||
}
|
||||
|
||||
VLOG(1) << "Global size: " << global_size << ".";
|
||||
return global_size;
|
||||
}
|
||||
@@ -608,6 +612,7 @@ OpenCLDevice::OpenCLDevice(DeviceInfo &info, Stats &stats, Profiler &profiler, b
|
||||
: Device(info, stats, profiler, background),
|
||||
load_kernel_num_compiling(0),
|
||||
kernel_programs(this),
|
||||
preview_programs(this),
|
||||
memory_manager(this),
|
||||
texture_info(this, "__texture_info", MEM_GLOBAL)
|
||||
{
|
||||
@@ -617,6 +622,7 @@ OpenCLDevice::OpenCLDevice(DeviceInfo &info, Stats &stats, Profiler &profiler, b
|
||||
cqCommandQueue = NULL;
|
||||
device_initialized = false;
|
||||
textures_need_update = true;
|
||||
use_preview_kernels = !background;
|
||||
|
||||
vector<OpenCLPlatformDevice> usable_devices;
|
||||
OpenCLInfo::get_usable_devices(&usable_devices);
|
||||
@@ -672,6 +678,9 @@ OpenCLDevice::OpenCLDevice(DeviceInfo &info, Stats &stats, Profiler &profiler, b
|
||||
device_initialized = true;
|
||||
|
||||
split_kernel = new OpenCLSplitKernel(this);
|
||||
if (use_preview_kernels) {
|
||||
load_preview_kernels();
|
||||
}
|
||||
}
|
||||
|
||||
OpenCLDevice::~OpenCLDevice()
|
||||
@@ -762,7 +771,7 @@ bool OpenCLDevice::load_kernels(const DeviceRequestedFeatures &requested_feature
|
||||
load_required_kernels(requested_features);
|
||||
|
||||
vector<OpenCLProgram *> programs;
|
||||
kernel_programs.load_kernels(programs, requested_features);
|
||||
kernel_programs.load_kernels(programs, requested_features, false);
|
||||
|
||||
if (!requested_features.use_baking && requested_features.use_denoising) {
|
||||
denoising_program = OpenCLProgram(
|
||||
@@ -840,6 +849,19 @@ void OpenCLDevice::load_required_kernels(const DeviceRequestedFeatures &requeste
|
||||
}
|
||||
}
|
||||
|
||||
void OpenCLDevice::load_preview_kernels()
|
||||
{
|
||||
DeviceRequestedFeatures no_features;
|
||||
vector<OpenCLProgram *> programs;
|
||||
preview_programs.load_kernels(programs, no_features, true);
|
||||
|
||||
foreach (OpenCLProgram *program, programs) {
|
||||
if (!program->load()) {
|
||||
load_required_kernel_task_pool.push(function_bind(&OpenCLProgram::compile, program));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool OpenCLDevice::wait_for_availability(const DeviceRequestedFeatures &requested_features)
|
||||
{
|
||||
if (requested_features.use_baking) {
|
||||
@@ -847,18 +869,59 @@ bool OpenCLDevice::wait_for_availability(const DeviceRequestedFeatures &requeste
|
||||
return true;
|
||||
}
|
||||
|
||||
load_kernel_task_pool.wait_work();
|
||||
if (background) {
|
||||
load_kernel_task_pool.wait_work();
|
||||
use_preview_kernels = false;
|
||||
}
|
||||
else {
|
||||
/* We use a device setting to determine to load preview kernels or not
|
||||
* Better to check on device level than per kernel as mixing preview and
|
||||
* non-preview kernels does not work due to different data types */
|
||||
if (use_preview_kernels) {
|
||||
use_preview_kernels = load_kernel_num_compiling.load() > 0;
|
||||
}
|
||||
}
|
||||
return split_kernel->load_kernels(requested_features);
|
||||
}
|
||||
|
||||
OpenCLDevice::OpenCLSplitPrograms *OpenCLDevice::get_split_programs()
|
||||
{
|
||||
return &kernel_programs;
|
||||
return use_preview_kernels ? &preview_programs : &kernel_programs;
|
||||
}
|
||||
|
||||
DeviceKernelStatus OpenCLDevice::get_active_kernel_switch_state()
|
||||
{
|
||||
return DEVICE_KERNEL_USING_FEATURE_KERNEL;
|
||||
/* Do not switch kernels for background renderings
|
||||
* We do foreground rendering but use the preview kernels
|
||||
* Check for the optimized kernels
|
||||
*
|
||||
* This works also the other way around, where we are using
|
||||
* optimized kernels but new ones are being compiled due
|
||||
* to other features that are needed */
|
||||
if (background) {
|
||||
/* The if-statements below would find the same result,
|
||||
* But as the `finished` method uses a mutex we added
|
||||
* this as an early exit */
|
||||
return DEVICE_KERNEL_USING_FEATURE_KERNEL;
|
||||
}
|
||||
|
||||
bool other_kernels_finished = load_kernel_num_compiling.load() == 0;
|
||||
if (use_preview_kernels) {
|
||||
if (other_kernels_finished) {
|
||||
return DEVICE_KERNEL_FEATURE_KERNEL_AVAILABLE;
|
||||
}
|
||||
else {
|
||||
return DEVICE_KERNEL_WAITING_FOR_FEATURE_KERNEL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (other_kernels_finished) {
|
||||
return DEVICE_KERNEL_USING_FEATURE_KERNEL;
|
||||
}
|
||||
else {
|
||||
return DEVICE_KERNEL_FEATURE_KERNEL_INVALID;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OpenCLDevice::mem_alloc(device_memory &mem)
|
||||
|
@@ -367,17 +367,9 @@ void Node::copy_value(const SocketType &socket, const Node &other, const SocketT
|
||||
case SocketType::TRANSFORM_ARRAY:
|
||||
copy_array<Transform>(this, socket, &other, other_socket);
|
||||
break;
|
||||
case SocketType::NODE_ARRAY: {
|
||||
case SocketType::NODE_ARRAY:
|
||||
copy_array<void *>(this, socket, &other, other_socket);
|
||||
|
||||
array<Node *> &node_array = get_socket_value<array<Node *>>(this, socket);
|
||||
|
||||
for (Node *node : node_array) {
|
||||
node->reference();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
@@ -387,14 +379,6 @@ void Node::copy_value(const SocketType &socket, const Node &other, const SocketT
|
||||
const void *src = ((char *)&other) + other_socket.struct_offset;
|
||||
void *dst = ((char *)this) + socket.struct_offset;
|
||||
memcpy(dst, src, socket.size());
|
||||
|
||||
if (socket.type == SocketType::NODE) {
|
||||
Node *node = get_socket_value<Node *>(this, socket);
|
||||
|
||||
if (node) {
|
||||
node->reference();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -789,26 +773,6 @@ void Node::set_owner(const NodeOwner *owner_)
|
||||
owner = owner_;
|
||||
}
|
||||
|
||||
void Node::dereference_all_used_nodes()
|
||||
{
|
||||
foreach (const SocketType &socket, type->inputs) {
|
||||
if (socket.type == SocketType::NODE) {
|
||||
Node *node = get_socket_value<Node *>(this, socket);
|
||||
|
||||
if (node) {
|
||||
node->dereference();
|
||||
}
|
||||
}
|
||||
else if (socket.type == SocketType::NODE_ARRAY) {
|
||||
const array<Node *> &nodes = get_socket_value<array<Node *>>(this, socket);
|
||||
|
||||
for (Node *node : nodes) {
|
||||
node->dereference();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Node::socket_is_modified(const SocketType &input) const
|
||||
{
|
||||
return (socket_modified & input.modified_flag_bit) != 0;
|
||||
@@ -839,25 +803,6 @@ template<typename T> void Node::set_if_different(const SocketType &input, T valu
|
||||
socket_modified |= input.modified_flag_bit;
|
||||
}
|
||||
|
||||
void Node::set_if_different(const SocketType &input, Node *value)
|
||||
{
|
||||
if (get_socket_value<Node *>(this, input) == value) {
|
||||
return;
|
||||
}
|
||||
|
||||
Node *old_node = get_socket_value<Node *>(this, input);
|
||||
if (old_node) {
|
||||
old_node->dereference();
|
||||
}
|
||||
|
||||
if (value) {
|
||||
value->reference();
|
||||
}
|
||||
|
||||
get_socket_value<Node *>(this, input) = value;
|
||||
socket_modified |= input.modified_flag_bit;
|
||||
}
|
||||
|
||||
template<typename T> void Node::set_if_different(const SocketType &input, array<T> &value)
|
||||
{
|
||||
if (!socket_is_modified(input)) {
|
||||
@@ -870,27 +815,6 @@ template<typename T> void Node::set_if_different(const SocketType &input, array<
|
||||
socket_modified |= input.modified_flag_bit;
|
||||
}
|
||||
|
||||
void Node::set_if_different(const SocketType &input, array<Node *> &value)
|
||||
{
|
||||
if (!socket_is_modified(input)) {
|
||||
if (get_socket_value<array<Node *>>(this, input) == value) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
array<Node *> &old_nodes = get_socket_value<array<Node *>>(this, input);
|
||||
for (Node *old_node : old_nodes) {
|
||||
old_node->dereference();
|
||||
}
|
||||
|
||||
for (Node *new_node : value) {
|
||||
new_node->reference();
|
||||
}
|
||||
|
||||
get_socket_value<array<Node *>>(this, input).steal_data(value);
|
||||
socket_modified |= input.modified_flag_bit;
|
||||
}
|
||||
|
||||
void Node::print_modified_sockets() const
|
||||
{
|
||||
printf("Node : %s\n", name.c_str());
|
||||
|
@@ -177,32 +177,8 @@ struct Node {
|
||||
const NodeOwner *get_owner() const;
|
||||
void set_owner(const NodeOwner *owner_);
|
||||
|
||||
int reference_count() const
|
||||
{
|
||||
return ref_count;
|
||||
}
|
||||
|
||||
void reference()
|
||||
{
|
||||
ref_count += 1;
|
||||
}
|
||||
|
||||
void dereference()
|
||||
{
|
||||
ref_count -= 1;
|
||||
}
|
||||
|
||||
/* Set the reference count to zero. This should only be called when we know for sure that the
|
||||
* Node is not used by anyone else. For now, this is only the case when "deleting" shaders, as
|
||||
* they are never actually deleted. */
|
||||
void clear_reference_count()
|
||||
{
|
||||
ref_count = 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
const NodeOwner *owner;
|
||||
int ref_count{0};
|
||||
|
||||
template<typename T> static T &get_socket_value(const Node *node, const SocketType &socket)
|
||||
{
|
||||
@@ -213,19 +189,7 @@ struct Node {
|
||||
|
||||
template<typename T> void set_if_different(const SocketType &input, T value);
|
||||
|
||||
/* Explicit overload for Node sockets so we can handle reference counting. The old Node is
|
||||
* dereferenced, and the new one is referenced. */
|
||||
void set_if_different(const SocketType &input, Node *value);
|
||||
|
||||
template<typename T> void set_if_different(const SocketType &input, array<T> &value);
|
||||
|
||||
/* Explicit overload for Node sockets so we can handle reference counting. The old Nodes are
|
||||
* dereferenced, and the new ones are referenced. */
|
||||
void set_if_different(const SocketType &input, array<Node *> &value);
|
||||
|
||||
/* Call this function in derived classes' destructors to ensure that used Nodes are dereferenced
|
||||
* properly. */
|
||||
void dereference_all_used_nodes();
|
||||
};
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
@@ -148,17 +148,16 @@ struct NodeType {
|
||||
#define NODE_DECLARE \
|
||||
static const NodeType *get_node_type(); \
|
||||
template<typename T> static const NodeType *register_type(); \
|
||||
static Node *create(const NodeType *type); \
|
||||
static const NodeType *node_type;
|
||||
static Node *create(const NodeType *type);
|
||||
|
||||
#define NODE_DEFINE(structname) \
|
||||
const NodeType *structname::node_type = structname::register_type<structname>(); \
|
||||
Node *structname::create(const NodeType *) \
|
||||
{ \
|
||||
return new structname(); \
|
||||
} \
|
||||
const NodeType *structname::get_node_type() \
|
||||
{ \
|
||||
static const NodeType *node_type = register_type<structname>(); \
|
||||
return node_type; \
|
||||
} \
|
||||
template<typename T> const NodeType *structname::register_type()
|
||||
@@ -170,8 +169,6 @@ struct NodeType {
|
||||
#define NODE_ABSTRACT_DEFINE(structname) \
|
||||
const NodeType *structname::get_node_base_type() \
|
||||
{ \
|
||||
/* Base types constructed in this getter to ensure correct initialization \
|
||||
* order. Regular types are not so they are auto-registered for XML parsing. */ \
|
||||
static const NodeType *node_base_type = register_base_type<structname>(); \
|
||||
return node_base_type; \
|
||||
} \
|
||||
|
@@ -57,24 +57,14 @@ ccl_device ccl_addr_space void *closure_alloc_extra(ShaderData *sd, int size)
|
||||
|
||||
ccl_device_inline ShaderClosure *bsdf_alloc(ShaderData *sd, int size, float3 weight)
|
||||
{
|
||||
kernel_assert(isfinite3_safe(weight));
|
||||
ShaderClosure *sc = closure_alloc(sd, size, CLOSURE_NONE_ID, weight);
|
||||
|
||||
const float sample_weight = fabsf(average(weight));
|
||||
if (sc == NULL)
|
||||
return NULL;
|
||||
|
||||
/* Use comparison this way to help dealing with non-finite weight: if the average is not finite
|
||||
* we will not allocate new closure. */
|
||||
if (sample_weight >= CLOSURE_WEIGHT_CUTOFF) {
|
||||
ShaderClosure *sc = closure_alloc(sd, size, CLOSURE_NONE_ID, weight);
|
||||
if (sc == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sc->sample_weight = sample_weight;
|
||||
|
||||
return sc;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
float sample_weight = fabsf(average(weight));
|
||||
sc->sample_weight = sample_weight;
|
||||
return (sample_weight >= CLOSURE_WEIGHT_CUTOFF) ? sc : NULL;
|
||||
}
|
||||
|
||||
#ifdef __OSL__
|
||||
@@ -83,27 +73,17 @@ ccl_device_inline ShaderClosure *bsdf_alloc_osl(ShaderData *sd,
|
||||
float3 weight,
|
||||
void *data)
|
||||
{
|
||||
kernel_assert(isfinite3_safe(weight));
|
||||
ShaderClosure *sc = closure_alloc(sd, size, CLOSURE_NONE_ID, weight);
|
||||
|
||||
const float sample_weight = fabsf(average(weight));
|
||||
if (!sc)
|
||||
return NULL;
|
||||
|
||||
/* Use comparison this way to help dealing with non-finite weight: if the average is not finite
|
||||
* we will not allocate new closure. */
|
||||
if (sample_weight >= CLOSURE_WEIGHT_CUTOFF) {
|
||||
ShaderClosure *sc = closure_alloc(sd, size, CLOSURE_NONE_ID, weight);
|
||||
if (!sc) {
|
||||
return NULL;
|
||||
}
|
||||
memcpy((void *)sc, data, size);
|
||||
|
||||
memcpy((void *)sc, data, size);
|
||||
|
||||
sc->weight = weight;
|
||||
sc->sample_weight = sample_weight;
|
||||
|
||||
return sc;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
float sample_weight = fabsf(average(weight));
|
||||
sc->weight = weight;
|
||||
sc->sample_weight = sample_weight;
|
||||
return (sample_weight >= CLOSURE_WEIGHT_CUTOFF) ? sc : NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@@ -200,12 +200,12 @@ ccl_device bool light_spread_clamp_area_light(const float3 P,
|
||||
* uv coordinates. */
|
||||
const float new_center_u = 0.5f * (min_u + max_u);
|
||||
const float new_center_v = 0.5f * (min_v + max_v);
|
||||
const float new_len_u = max_u - min_u;
|
||||
const float new_len_v = max_v - min_v;
|
||||
const float new_len_u = 0.5f * (max_u - min_u);
|
||||
const float new_len_v = 0.5f * (max_v - min_v);
|
||||
|
||||
*lightP = *lightP + new_center_u * u + new_center_v * v;
|
||||
*axisu = u * new_len_u;
|
||||
*axisv = v * new_len_v;
|
||||
*axisu = u * new_len_u * 2.0f;
|
||||
*axisv = v * new_len_v * 2.0f;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@@ -195,108 +195,31 @@ ccl_device float2 regular_polygon_sample(float corners, float rotation, float u,
|
||||
|
||||
ccl_device float3 ensure_valid_reflection(float3 Ng, float3 I, float3 N)
|
||||
{
|
||||
float3 R = 2 * dot(N, I) * N - I;
|
||||
float3 R;
|
||||
float NI = dot(N, I);
|
||||
float NgR, threshold;
|
||||
|
||||
/* Reflection rays may always be at least as shallow as the incoming ray. */
|
||||
float threshold = min(0.9f * dot(Ng, I), 0.01f);
|
||||
if (dot(Ng, R) >= threshold) {
|
||||
return N;
|
||||
}
|
||||
/* Check if the incident ray is coming from behind normal N. */
|
||||
if (NI > 0) {
|
||||
/* Normal reflection */
|
||||
R = (2 * NI) * N - I;
|
||||
NgR = dot(Ng, R);
|
||||
|
||||
/* Form coordinate system with Ng as the Z axis and N inside the X-Z-plane.
|
||||
* The X axis is found by normalizing the component of N that's orthogonal to Ng.
|
||||
* The Y axis isn't actually needed.
|
||||
*/
|
||||
float NdotNg = dot(N, Ng);
|
||||
float3 X = normalize(N - NdotNg * Ng);
|
||||
|
||||
/* Keep math expressions. */
|
||||
/* clang-format off */
|
||||
/* Calculate N.z and N.x in the local coordinate system.
|
||||
*
|
||||
* The goal of this computation is to find a N' that is rotated towards Ng just enough
|
||||
* to lift R' above the threshold (here called t), therefore dot(R', Ng) = t.
|
||||
*
|
||||
* According to the standard reflection equation,
|
||||
* this means that we want dot(2*dot(N', I)*N' - I, Ng) = t.
|
||||
*
|
||||
* Since the Z axis of our local coordinate system is Ng, dot(x, Ng) is just x.z, so we get
|
||||
* 2*dot(N', I)*N'.z - I.z = t.
|
||||
*
|
||||
* The rotation is simple to express in the coordinate system we formed -
|
||||
* since N lies in the X-Z-plane, we know that N' will also lie in the X-Z-plane,
|
||||
* so N'.y = 0 and therefore dot(N', I) = N'.x*I.x + N'.z*I.z .
|
||||
*
|
||||
* Furthermore, we want N' to be normalized, so N'.x = sqrt(1 - N'.z^2).
|
||||
*
|
||||
* With these simplifications,
|
||||
* we get the final equation 2*(sqrt(1 - N'.z^2)*I.x + N'.z*I.z)*N'.z - I.z = t.
|
||||
*
|
||||
* The only unknown here is N'.z, so we can solve for that.
|
||||
*
|
||||
* The equation has four solutions in general:
|
||||
*
|
||||
* N'.z = +-sqrt(0.5*(+-sqrt(I.x^2*(I.x^2 + I.z^2 - t^2)) + t*I.z + I.x^2 + I.z^2)/(I.x^2 + I.z^2))
|
||||
* We can simplify this expression a bit by grouping terms:
|
||||
*
|
||||
* a = I.x^2 + I.z^2
|
||||
* b = sqrt(I.x^2 * (a - t^2))
|
||||
* c = I.z*t + a
|
||||
* N'.z = +-sqrt(0.5*(+-b + c)/a)
|
||||
*
|
||||
* Two solutions can immediately be discarded because they're negative so N' would lie in the
|
||||
* lower hemisphere.
|
||||
*/
|
||||
/* clang-format on */
|
||||
|
||||
float Ix = dot(I, X), Iz = dot(I, Ng);
|
||||
float Ix2 = sqr(Ix), Iz2 = sqr(Iz);
|
||||
float a = Ix2 + Iz2;
|
||||
|
||||
float b = safe_sqrtf(Ix2 * (a - sqr(threshold)));
|
||||
float c = Iz * threshold + a;
|
||||
|
||||
/* Evaluate both solutions.
|
||||
* In many cases one can be immediately discarded (if N'.z would be imaginary or larger than
|
||||
* one), so check for that first. If no option is viable (might happen in extreme cases like N
|
||||
* being in the wrong hemisphere), give up and return Ng. */
|
||||
float fac = 0.5f / a;
|
||||
float N1_z2 = fac * (b + c), N2_z2 = fac * (-b + c);
|
||||
bool valid1 = (N1_z2 > 1e-5f) && (N1_z2 <= (1.0f + 1e-5f));
|
||||
bool valid2 = (N2_z2 > 1e-5f) && (N2_z2 <= (1.0f + 1e-5f));
|
||||
|
||||
float2 N_new;
|
||||
if (valid1 && valid2) {
|
||||
/* If both are possible, do the expensive reflection-based check. */
|
||||
float2 N1 = make_float2(safe_sqrtf(1.0f - N1_z2), safe_sqrtf(N1_z2));
|
||||
float2 N2 = make_float2(safe_sqrtf(1.0f - N2_z2), safe_sqrtf(N2_z2));
|
||||
|
||||
float R1 = 2 * (N1.x * Ix + N1.y * Iz) * N1.y - Iz;
|
||||
float R2 = 2 * (N2.x * Ix + N2.y * Iz) * N2.y - Iz;
|
||||
|
||||
valid1 = (R1 >= 1e-5f);
|
||||
valid2 = (R2 >= 1e-5f);
|
||||
if (valid1 && valid2) {
|
||||
/* If both solutions are valid, return the one with the shallower reflection since it will be
|
||||
* closer to the input (if the original reflection wasn't shallow, we would not be in this
|
||||
* part of the function). */
|
||||
N_new = (R1 < R2) ? N1 : N2;
|
||||
/* Reflection rays may always be at least as shallow as the incoming ray. */
|
||||
threshold = min(0.9f * dot(Ng, I), 0.01f);
|
||||
if (NgR >= threshold) {
|
||||
return N;
|
||||
}
|
||||
else {
|
||||
/* If only one reflection is valid (= positive), pick that one. */
|
||||
N_new = (R1 > R2) ? N1 : N2;
|
||||
}
|
||||
}
|
||||
else if (valid1 || valid2) {
|
||||
/* Only one solution passes the N'.z criterium, so pick that one. */
|
||||
float Nz2 = valid1 ? N1_z2 : N2_z2;
|
||||
N_new = make_float2(safe_sqrtf(1.0f - Nz2), safe_sqrtf(Nz2));
|
||||
}
|
||||
else {
|
||||
return Ng;
|
||||
/* Bad incident */
|
||||
R = -I;
|
||||
NgR = dot(Ng, R);
|
||||
threshold = 0.01f;
|
||||
}
|
||||
|
||||
return N_new.x * X + N_new.y * Ng;
|
||||
R = R + Ng * (threshold - NgR); /* Lift the reflection above the threshold. */
|
||||
return normalize(I * len(R) + R * len(I)); /* Find a bisector. */
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
@@ -25,9 +25,8 @@ CCL_NAMESPACE_BEGIN
|
||||
ccl_device_inline float3
|
||||
subsurface_scatter_eval(ShaderData *sd, const ShaderClosure *sc, float disk_r, float r, bool all)
|
||||
{
|
||||
/* This is the Veach one-sample model with balance heuristic, some pdf
|
||||
* factors drop out when using balance heuristic weighting. For branched
|
||||
* path tracing (all) we sample all closure and don't use MIS. */
|
||||
/* this is the veach one-sample model with balance heuristic, some pdf
|
||||
* factors drop out when using balance heuristic weighting */
|
||||
float3 eval_sum = zero_float3();
|
||||
float pdf_sum = 0.0f;
|
||||
float sample_weight_inv = 0.0f;
|
||||
@@ -66,30 +65,6 @@ subsurface_scatter_eval(ShaderData *sd, const ShaderClosure *sc, float disk_r, f
|
||||
return (pdf_sum > 0.0f) ? eval_sum / pdf_sum : zero_float3();
|
||||
}
|
||||
|
||||
ccl_device_inline float3 subsurface_scatter_walk_eval(ShaderData *sd,
|
||||
const ShaderClosure *sc,
|
||||
float3 throughput,
|
||||
bool all)
|
||||
{
|
||||
/* This is the Veach one-sample model with balance heuristic, some pdf
|
||||
* factors drop out when using balance heuristic weighting. For branched
|
||||
* path tracing (all) we sample all closure and don't use MIS. */
|
||||
if (!all) {
|
||||
float bssrdf_weight = 0.0f;
|
||||
float weight = sc->sample_weight;
|
||||
|
||||
for (int i = 0; i < sd->num_closure; i++) {
|
||||
sc = &sd->closure[i];
|
||||
|
||||
if (CLOSURE_IS_BSSRDF(sc->type)) {
|
||||
bssrdf_weight += sc->sample_weight;
|
||||
}
|
||||
}
|
||||
throughput *= bssrdf_weight / weight;
|
||||
}
|
||||
return throughput;
|
||||
}
|
||||
|
||||
/* replace closures with a single diffuse bsdf closure after scatter step */
|
||||
ccl_device void subsurface_scatter_setup_diffuse_bsdf(
|
||||
KernelGlobals *kg, ShaderData *sd, ClosureType type, float roughness, float3 weight, float3 N)
|
||||
@@ -462,8 +437,7 @@ ccl_device_noinline
|
||||
ccl_addr_space PathState *state,
|
||||
const ShaderClosure *sc,
|
||||
const float bssrdf_u,
|
||||
const float bssrdf_v,
|
||||
bool all)
|
||||
const float bssrdf_v)
|
||||
{
|
||||
/* Sample diffuse surface scatter into the object. */
|
||||
float3 D;
|
||||
@@ -632,10 +606,10 @@ ccl_device_noinline
|
||||
t = ray->t;
|
||||
}
|
||||
else if (bounce == 0) {
|
||||
/* Restore original position if nothing was hit after the first bounce,
|
||||
* without the ray_offset() that was added to avoid self-intersection.
|
||||
* Otherwise if that offset is relatively large compared to the scattering
|
||||
* radius, we never go back up high enough to exit the surface. */
|
||||
/* Restore original position if nothing was hit after the first bounce.
|
||||
* Otherwise if the ray_offset() to avoid self-intersection is relatively
|
||||
* large compared to the scattering radius, we go never backup high enough
|
||||
* to exit the surface. */
|
||||
ray->P = sd->P;
|
||||
}
|
||||
|
||||
@@ -695,7 +669,7 @@ ccl_device_noinline
|
||||
/* TODO: gain back performance lost from merging with disk BSSRDF. We
|
||||
* only need to return on hit so this indirect ray push/pop overhead
|
||||
* is not actually needed, but it does keep the code simpler. */
|
||||
ss_isect->weight[0] = subsurface_scatter_walk_eval(sd, sc, throughput, all);
|
||||
ss_isect->weight[0] = throughput;
|
||||
#ifdef __SPLIT_KERNEL__
|
||||
ss_isect->ray = *ray;
|
||||
#endif
|
||||
@@ -717,7 +691,7 @@ ccl_device_inline int subsurface_scatter_multi_intersect(KernelGlobals *kg,
|
||||
return subsurface_scatter_disk(kg, ss_isect, sd, sc, lcg_state, bssrdf_u, bssrdf_v, all);
|
||||
}
|
||||
else {
|
||||
return subsurface_random_walk(kg, ss_isect, sd, state, sc, bssrdf_u, bssrdf_v, all);
|
||||
return subsurface_random_walk(kg, ss_isect, sd, state, sc, bssrdf_u, bssrdf_v);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -99,23 +99,27 @@ CCL_NAMESPACE_BEGIN
|
||||
#define __AO__
|
||||
#define __PASSES__
|
||||
#define __HAIR__
|
||||
#define __SVM__
|
||||
#define __EMISSION__
|
||||
#define __HOLDOUT__
|
||||
#define __MULTI_CLOSURE__
|
||||
#define __TRANSPARENT_SHADOWS__
|
||||
#define __BACKGROUND_MIS__
|
||||
#define __LAMP_MIS__
|
||||
#define __CAMERA_MOTION__
|
||||
#define __OBJECT_MOTION__
|
||||
#define __BAKING__
|
||||
#define __PRINCIPLED__
|
||||
#define __SUBSURFACE__
|
||||
#define __VOLUME__
|
||||
#define __VOLUME_SCATTER__
|
||||
#define __CMJ__
|
||||
#define __SHADOW_RECORD_ALL__
|
||||
#define __BRANCHED_PATH__
|
||||
|
||||
/* Without these we get an AO render, used by OpenCL preview kernel. */
|
||||
#ifndef __KERNEL_AO_PREVIEW__
|
||||
# define __SVM__
|
||||
# define __EMISSION__
|
||||
# define __HOLDOUT__
|
||||
# define __MULTI_CLOSURE__
|
||||
# define __TRANSPARENT_SHADOWS__
|
||||
# define __BACKGROUND_MIS__
|
||||
# define __LAMP_MIS__
|
||||
# define __CAMERA_MOTION__
|
||||
# define __OBJECT_MOTION__
|
||||
# define __BAKING__
|
||||
# define __PRINCIPLED__
|
||||
# define __SUBSURFACE__
|
||||
# define __VOLUME__
|
||||
# define __VOLUME_SCATTER__
|
||||
# define __CMJ__
|
||||
# define __SHADOW_RECORD_ALL__
|
||||
# define __BRANCHED_PATH__
|
||||
#endif
|
||||
|
||||
/* Device specific features */
|
||||
#ifdef __KERNEL_CPU__
|
||||
|
@@ -25,7 +25,7 @@
|
||||
* coordinates to act as a seed since the noise functions don't have seed values.
|
||||
* A seed value is needed for generating distortion textures and color outputs.
|
||||
* The offset's components are in the range [100, 200], not too high to cause
|
||||
* bad precision and not too small to be noticeable. We use float seed because
|
||||
* bad precision and not to small to be noticeable. We use float seed because
|
||||
* OSL only support float hashes.
|
||||
*/
|
||||
|
||||
|
@@ -84,67 +84,30 @@ closure color principled_hair(normal N,
|
||||
closure color henyey_greenstein(float g) BUILTIN;
|
||||
closure color absorption() BUILTIN;
|
||||
|
||||
normal ensure_valid_reflection(normal Ng, vector I, normal N)
|
||||
normal ensure_valid_reflection(normal Ng, normal I, normal N)
|
||||
{
|
||||
/* The implementation here mirrors the one in kernel_montecarlo.h,
|
||||
* check there for an explanation of the algorithm. */
|
||||
vector R;
|
||||
float NI = dot(N, I);
|
||||
float NgR, threshold;
|
||||
|
||||
float sqr(float x)
|
||||
{
|
||||
return x * x;
|
||||
}
|
||||
|
||||
vector R = 2 * dot(N, I) * N - I;
|
||||
|
||||
float threshold = min(0.9 * dot(Ng, I), 0.01);
|
||||
if (dot(Ng, R) >= threshold) {
|
||||
return N;
|
||||
}
|
||||
|
||||
float NdotNg = dot(N, Ng);
|
||||
vector X = normalize(N - NdotNg * Ng);
|
||||
|
||||
float Ix = dot(I, X), Iz = dot(I, Ng);
|
||||
float Ix2 = sqr(Ix), Iz2 = sqr(Iz);
|
||||
float a = Ix2 + Iz2;
|
||||
|
||||
float b = sqrt(Ix2 * (a - sqr(threshold)));
|
||||
float c = Iz * threshold + a;
|
||||
|
||||
float fac = 0.5 / a;
|
||||
float N1_z2 = fac * (b + c), N2_z2 = fac * (-b + c);
|
||||
int valid1 = (N1_z2 > 1e-5) && (N1_z2 <= (1.0 + 1e-5));
|
||||
int valid2 = (N2_z2 > 1e-5) && (N2_z2 <= (1.0 + 1e-5));
|
||||
|
||||
float N_new_x, N_new_z;
|
||||
if (valid1 && valid2) {
|
||||
float N1_x = sqrt(1.0 - N1_z2), N1_z = sqrt(N1_z2);
|
||||
float N2_x = sqrt(1.0 - N2_z2), N2_z = sqrt(N2_z2);
|
||||
|
||||
float R1 = 2 * (N1_x * Ix + N1_z * Iz) * N1_z - Iz;
|
||||
float R2 = 2 * (N2_x * Ix + N2_z * Iz) * N2_z - Iz;
|
||||
|
||||
valid1 = (R1 >= 1e-5);
|
||||
valid2 = (R2 >= 1e-5);
|
||||
if (valid1 && valid2) {
|
||||
N_new_x = (R1 < R2) ? N1_x : N2_x;
|
||||
N_new_z = (R1 < R2) ? N1_z : N2_z;
|
||||
if (NI > 0) {
|
||||
R = (2 * NI) * N - I;
|
||||
NgR = dot(Ng, R);
|
||||
threshold = min(0.9 * dot(Ng, I), 0.01);
|
||||
if (NgR >= threshold) {
|
||||
return N;
|
||||
}
|
||||
else {
|
||||
N_new_x = (R1 > R2) ? N1_x : N2_x;
|
||||
N_new_z = (R1 > R2) ? N1_z : N2_z;
|
||||
}
|
||||
}
|
||||
else if (valid1 || valid2) {
|
||||
float Nz2 = valid1 ? N1_z2 : N2_z2;
|
||||
N_new_x = sqrt(1.0 - Nz2);
|
||||
N_new_z = sqrt(Nz2);
|
||||
}
|
||||
else {
|
||||
return Ng;
|
||||
R = -I;
|
||||
NgR = dot(Ng, R);
|
||||
threshold = 0.01;
|
||||
}
|
||||
|
||||
return N_new_x * X + N_new_z * Ng;
|
||||
R = R + Ng * (threshold - NgR);
|
||||
return normalize(I * length(R) + R * length(I));
|
||||
}
|
||||
|
||||
#endif /* CCL_STDOSL_H */
|
||||
|
@@ -20,7 +20,7 @@ CCL_NAMESPACE_BEGIN
|
||||
* coordinates to act as a seed since the noise functions don't have seed values.
|
||||
* A seed value is needed for generating distortion textures and color outputs.
|
||||
* The offset's components are in the range [100, 200], not too high to cause
|
||||
* bad precision and not too small to be noticeable. We use float seed because
|
||||
* bad precision and not to small to be noticeable. We use float seed because
|
||||
* OSL only support float hashes.
|
||||
*/
|
||||
|
||||
|
@@ -370,13 +370,10 @@ ccl_device void svm_node_tangent(KernelGlobals *kg, ShaderData *sd, float *stack
|
||||
|
||||
if (direction_type == NODE_TANGENT_UVMAP) {
|
||||
/* UV map */
|
||||
if (desc.offset == ATTR_STD_NOT_FOUND) {
|
||||
stack_store_float3(stack, tangent_offset, zero_float3());
|
||||
return;
|
||||
}
|
||||
else {
|
||||
if (desc.offset == ATTR_STD_NOT_FOUND)
|
||||
tangent = make_float3(0.0f, 0.0f, 0.0f);
|
||||
else
|
||||
tangent = attribute_value;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* radial */
|
||||
|
@@ -24,7 +24,6 @@ set(INC_SYS
|
||||
|
||||
set(SRC
|
||||
alembic.cpp
|
||||
alembic_read.cpp
|
||||
attribute.cpp
|
||||
background.cpp
|
||||
bake.cpp
|
||||
@@ -68,7 +67,6 @@ set(SRC
|
||||
|
||||
set(SRC_HEADERS
|
||||
alembic.h
|
||||
alembic_read.h
|
||||
attribute.h
|
||||
bake.h
|
||||
background.h
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -152,10 +152,6 @@ template<typename T> class DataStore {
|
||||
double last_loaded_time = std::numeric_limits<double>::max();
|
||||
|
||||
public:
|
||||
/* Keys used to compare values. */
|
||||
Alembic::AbcCoreAbstract::ArraySample::Key key1;
|
||||
Alembic::AbcCoreAbstract::ArraySample::Key key2;
|
||||
|
||||
void set_time_sampling(Alembic::AbcCoreAbstract::TimeSampling time_sampling_)
|
||||
{
|
||||
time_sampling = time_sampling_;
|
||||
@@ -229,11 +225,6 @@ template<typename T> class DataStore {
|
||||
index_data_map.push_back({time, data_index.source_time, data_index.index});
|
||||
}
|
||||
|
||||
void add_no_data(double time)
|
||||
{
|
||||
index_data_map.push_back({time, time, -1ul});
|
||||
}
|
||||
|
||||
bool is_constant() const
|
||||
{
|
||||
return data.size() <= 1;
|
||||
@@ -293,7 +284,7 @@ struct CachedData {
|
||||
DataStore<array<int3>> triangles{};
|
||||
/* triangle "loops" are the polygons' vertices indices used for indexing face varying attributes
|
||||
* (like UVs) */
|
||||
DataStore<array<int>> uv_loops{};
|
||||
DataStore<array<int3>> triangles_loops{};
|
||||
DataStore<array<int>> shader{};
|
||||
|
||||
/* subd data */
|
||||
@@ -371,18 +362,16 @@ class AlembicObject : public Node {
|
||||
void set_object(Object *object);
|
||||
Object *get_object();
|
||||
|
||||
void load_data_in_cache(CachedData &cached_data,
|
||||
AlembicProcedural *proc,
|
||||
Alembic::AbcGeom::IPolyMeshSchema &schema,
|
||||
Progress &progress);
|
||||
void load_data_in_cache(CachedData &cached_data,
|
||||
AlembicProcedural *proc,
|
||||
Alembic::AbcGeom::ISubDSchema &schema,
|
||||
Progress &progress);
|
||||
void load_data_in_cache(CachedData &cached_data,
|
||||
AlembicProcedural *proc,
|
||||
const Alembic::AbcGeom::ICurvesSchema &schema,
|
||||
Progress &progress);
|
||||
void load_all_data(AlembicProcedural *proc,
|
||||
Alembic::AbcGeom::IPolyMeshSchema &schema,
|
||||
Progress &progress);
|
||||
void load_all_data(AlembicProcedural *proc,
|
||||
Alembic::AbcGeom::ISubDSchema &schema,
|
||||
Progress &progress);
|
||||
void load_all_data(AlembicProcedural *proc,
|
||||
const Alembic::AbcGeom::ICurvesSchema &schema,
|
||||
Progress &progress,
|
||||
float default_radius);
|
||||
|
||||
bool has_data_loaded() const;
|
||||
|
||||
@@ -408,21 +397,33 @@ class AlembicObject : public Node {
|
||||
|
||||
CachedData &get_cached_data()
|
||||
{
|
||||
return cached_data_;
|
||||
return cached_data;
|
||||
}
|
||||
|
||||
bool is_constant() const
|
||||
{
|
||||
return cached_data_.is_constant();
|
||||
return cached_data.is_constant();
|
||||
}
|
||||
|
||||
Object *object = nullptr;
|
||||
|
||||
bool data_loaded = false;
|
||||
|
||||
CachedData cached_data_;
|
||||
CachedData cached_data;
|
||||
|
||||
void setup_transform_cache(CachedData &cached_data, float scale);
|
||||
void update_shader_attributes(const Alembic::AbcGeom::ICompoundProperty &arb_geom_params,
|
||||
Progress &progress);
|
||||
|
||||
void read_attribute(const Alembic::AbcGeom::ICompoundProperty &arb_geom_params,
|
||||
const ustring &attr_name,
|
||||
Progress &progress);
|
||||
|
||||
template<typename SchemaType>
|
||||
void read_face_sets(SchemaType &schema,
|
||||
array<int> &polygon_to_shader,
|
||||
Alembic::AbcGeom::ISampleSelector sample_sel);
|
||||
|
||||
void setup_transform_cache(float scale);
|
||||
|
||||
AttributeRequestSet get_requested_attributes();
|
||||
};
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,134 +0,0 @@
|
||||
/*
|
||||
* Copyright 2021 Blender Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef WITH_ALEMBIC
|
||||
|
||||
# include <Alembic/AbcCoreFactory/All.h>
|
||||
# include <Alembic/AbcGeom/All.h>
|
||||
|
||||
# include "util/util_vector.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
class AlembicProcedural;
|
||||
class AttributeRequestSet;
|
||||
class Progress;
|
||||
struct CachedData;
|
||||
|
||||
/* Maps a FaceSet whose name matches that of a Shader to the index of said shader in the Geometry's
|
||||
* used_shaders list. */
|
||||
struct FaceSetShaderIndexPair {
|
||||
Alembic::AbcGeom::IFaceSet face_set;
|
||||
int shader_index;
|
||||
};
|
||||
|
||||
/* Data of an IPolyMeshSchema that we need to read. */
|
||||
struct PolyMeshSchemaData {
|
||||
Alembic::AbcGeom::TimeSamplingPtr time_sampling;
|
||||
size_t num_samples;
|
||||
Alembic::AbcGeom::MeshTopologyVariance topology_variance;
|
||||
|
||||
Alembic::AbcGeom::IP3fArrayProperty positions;
|
||||
Alembic::AbcGeom::IInt32ArrayProperty face_indices;
|
||||
Alembic::AbcGeom::IInt32ArrayProperty face_counts;
|
||||
|
||||
Alembic::AbcGeom::IN3fGeomParam normals;
|
||||
|
||||
vector<FaceSetShaderIndexPair> shader_face_sets;
|
||||
|
||||
// Unsupported for now.
|
||||
Alembic::AbcGeom::IV3fArrayProperty velocities;
|
||||
};
|
||||
|
||||
void read_geometry_data(AlembicProcedural *proc,
|
||||
CachedData &cached_data,
|
||||
const PolyMeshSchemaData &data,
|
||||
Progress &progress);
|
||||
|
||||
/* Data of an ISubDSchema that we need to read. */
|
||||
struct SubDSchemaData {
|
||||
Alembic::AbcGeom::TimeSamplingPtr time_sampling;
|
||||
size_t num_samples;
|
||||
Alembic::AbcGeom::MeshTopologyVariance topology_variance;
|
||||
|
||||
Alembic::AbcGeom::IInt32ArrayProperty face_counts;
|
||||
Alembic::AbcGeom::IInt32ArrayProperty face_indices;
|
||||
Alembic::AbcGeom::IP3fArrayProperty positions;
|
||||
|
||||
Alembic::AbcGeom::IInt32ArrayProperty crease_indices;
|
||||
Alembic::AbcGeom::IInt32ArrayProperty crease_lengths;
|
||||
Alembic::AbcGeom::IFloatArrayProperty crease_sharpnesses;
|
||||
|
||||
vector<FaceSetShaderIndexPair> shader_face_sets;
|
||||
|
||||
// Those are unsupported for now.
|
||||
Alembic::AbcGeom::IInt32ArrayProperty corner_indices;
|
||||
Alembic::AbcGeom::IFloatArrayProperty corner_sharpnesses;
|
||||
Alembic::AbcGeom::IInt32Property face_varying_interpolate_boundary;
|
||||
Alembic::AbcGeom::IInt32Property face_varying_propagate_corners;
|
||||
Alembic::AbcGeom::IInt32Property interpolate_boundary;
|
||||
Alembic::AbcGeom::IInt32ArrayProperty holes;
|
||||
Alembic::AbcGeom::IStringProperty subdivision_scheme;
|
||||
Alembic::AbcGeom::IV3fArrayProperty velocities;
|
||||
};
|
||||
|
||||
void read_geometry_data(AlembicProcedural *proc,
|
||||
CachedData &cached_data,
|
||||
const SubDSchemaData &data,
|
||||
Progress &progress);
|
||||
|
||||
/* Data of a ICurvesSchema that we need to read. */
|
||||
struct CurvesSchemaData {
|
||||
Alembic::AbcGeom::TimeSamplingPtr time_sampling;
|
||||
size_t num_samples;
|
||||
Alembic::AbcGeom::MeshTopologyVariance topology_variance;
|
||||
|
||||
Alembic::AbcGeom::IP3fArrayProperty positions;
|
||||
|
||||
Alembic::AbcGeom::IInt32ArrayProperty num_vertices;
|
||||
|
||||
float default_radius;
|
||||
float radius_scale;
|
||||
|
||||
// Those are unsupported for now.
|
||||
Alembic::AbcGeom::IV3fArrayProperty velocities;
|
||||
// if this property is invalid then the weight for every point is 1
|
||||
Alembic::AbcGeom::IFloatArrayProperty position_weights;
|
||||
Alembic::AbcGeom::IN3fGeomParam normals;
|
||||
Alembic::AbcGeom::IFloatGeomParam widths;
|
||||
Alembic::AbcGeom::IUcharArrayProperty orders;
|
||||
Alembic::AbcGeom::IFloatArrayProperty knots;
|
||||
|
||||
// TODO(@kevindietrich): type, basis, wrap
|
||||
};
|
||||
|
||||
void read_geometry_data(AlembicProcedural *proc,
|
||||
CachedData &cached_data,
|
||||
const CurvesSchemaData &data,
|
||||
Progress &progress);
|
||||
|
||||
void read_attributes(AlembicProcedural *proc,
|
||||
CachedData &cache,
|
||||
const Alembic::AbcGeom::ICompoundProperty &arb_geom_params,
|
||||
const Alembic::AbcGeom::IV2fGeomParam &default_uvs_param,
|
||||
const AttributeRequestSet &requested_attributes,
|
||||
Progress &progress);
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif
|
@@ -383,23 +383,6 @@ AttributeStandard Attribute::name_standard(const char *name)
|
||||
return ATTR_STD_NONE;
|
||||
}
|
||||
|
||||
AttrKernelDataType Attribute::kernel_type(const Attribute &attr)
|
||||
{
|
||||
if (attr.element == ATTR_ELEMENT_CORNER) {
|
||||
return AttrKernelDataType::UCHAR4;
|
||||
}
|
||||
|
||||
if (attr.type == TypeDesc::TypeFloat) {
|
||||
return AttrKernelDataType::FLOAT;
|
||||
}
|
||||
|
||||
if (attr.type == TypeFloat2) {
|
||||
return AttrKernelDataType::FLOAT2;
|
||||
}
|
||||
|
||||
return AttrKernelDataType::FLOAT3;
|
||||
}
|
||||
|
||||
void Attribute::get_uv_tiles(Geometry *geom,
|
||||
AttributePrimitive prim,
|
||||
unordered_set<int> &tiles) const
|
||||
@@ -434,7 +417,7 @@ void Attribute::get_uv_tiles(Geometry *geom,
|
||||
/* Attribute Set */
|
||||
|
||||
AttributeSet::AttributeSet(Geometry *geometry, AttributePrimitive prim)
|
||||
: modified_flag(~0u), geometry(geometry), prim(prim)
|
||||
: geometry(geometry), prim(prim)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -457,7 +440,7 @@ Attribute *AttributeSet::add(ustring name, TypeDesc type, AttributeElement eleme
|
||||
|
||||
Attribute new_attr(name, type, element, geometry, prim);
|
||||
attributes.emplace_back(std::move(new_attr));
|
||||
tag_modified(attributes.back());
|
||||
modified = true;
|
||||
return &attributes.back();
|
||||
}
|
||||
|
||||
@@ -479,7 +462,8 @@ void AttributeSet::remove(ustring name)
|
||||
|
||||
for (it = attributes.begin(); it != attributes.end(); it++) {
|
||||
if (&*it == attr) {
|
||||
remove(it);
|
||||
modified = true;
|
||||
attributes.erase(it);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -624,7 +608,8 @@ void AttributeSet::remove(AttributeStandard std)
|
||||
|
||||
for (it = attributes.begin(); it != attributes.end(); it++) {
|
||||
if (&*it == attr) {
|
||||
remove(it);
|
||||
modified = true;
|
||||
attributes.erase(it);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -649,12 +634,6 @@ void AttributeSet::remove(Attribute *attribute)
|
||||
}
|
||||
}
|
||||
|
||||
void AttributeSet::remove(list<Attribute>::iterator it)
|
||||
{
|
||||
tag_modified(*it);
|
||||
attributes.erase(it);
|
||||
}
|
||||
|
||||
void AttributeSet::resize(bool reserve_only)
|
||||
{
|
||||
foreach (Attribute &attr, attributes) {
|
||||
@@ -695,22 +674,21 @@ void AttributeSet::update(AttributeSet &&new_attributes)
|
||||
for (it = attributes.begin(); it != attributes.end();) {
|
||||
if (it->std != ATTR_STD_NONE) {
|
||||
if (new_attributes.find(it->std) == nullptr) {
|
||||
remove(it++);
|
||||
modified = true;
|
||||
attributes.erase(it++);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (it->name != "") {
|
||||
if (new_attributes.find(it->name) == nullptr) {
|
||||
remove(it++);
|
||||
modified = true;
|
||||
attributes.erase(it++);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
it++;
|
||||
}
|
||||
|
||||
/* If all attributes were replaced, transform is no longer applied. */
|
||||
geometry->transform_applied = false;
|
||||
}
|
||||
|
||||
void AttributeSet::clear_modified()
|
||||
@@ -718,27 +696,7 @@ void AttributeSet::clear_modified()
|
||||
foreach (Attribute &attr, attributes) {
|
||||
attr.modified = false;
|
||||
}
|
||||
|
||||
modified_flag = 0;
|
||||
}
|
||||
|
||||
void AttributeSet::tag_modified(const Attribute &attr)
|
||||
{
|
||||
/* Some attributes are not stored in the various kernel attribute arrays
|
||||
* (DeviceScene::attribute_*), so the modified flags are only set if the associated standard
|
||||
* corresponds to an attribute which will be stored in the kernel's attribute arrays. */
|
||||
const bool modifies_device_array = (attr.std != ATTR_STD_FACE_NORMAL &&
|
||||
attr.std != ATTR_STD_VERTEX_NORMAL);
|
||||
|
||||
if (modifies_device_array) {
|
||||
AttrKernelDataType kernel_type = Attribute::kernel_type(attr);
|
||||
modified_flag |= (1u << kernel_type);
|
||||
}
|
||||
}
|
||||
|
||||
bool AttributeSet::modified(AttrKernelDataType kernel_type) const
|
||||
{
|
||||
return (modified_flag & (1u << kernel_type)) != 0;
|
||||
modified = false;
|
||||
}
|
||||
|
||||
/* AttributeRequest */
|
||||
|
@@ -39,21 +39,6 @@ class Hair;
|
||||
class Mesh;
|
||||
struct Transform;
|
||||
|
||||
/* AttrKernelDataType.
|
||||
*
|
||||
* The data type of the device arrays storing the attribute's data. Those data types are different
|
||||
* than the ones for attributes as some attribute types are stored in the same array, e.g. Point,
|
||||
* Vector, and Transform are all stored as float3 in the kernel.
|
||||
*
|
||||
* The values of this enumeration are also used as flags to detect changes in AttributeSet. */
|
||||
|
||||
enum AttrKernelDataType {
|
||||
FLOAT = 0,
|
||||
FLOAT2 = 1,
|
||||
FLOAT3 = 2,
|
||||
UCHAR4 = 3,
|
||||
};
|
||||
|
||||
/* Attribute
|
||||
*
|
||||
* Arbitrary data layers on meshes.
|
||||
@@ -182,8 +167,6 @@ class Attribute {
|
||||
static const char *standard_name(AttributeStandard std);
|
||||
static AttributeStandard name_standard(const char *name);
|
||||
|
||||
static AttrKernelDataType kernel_type(const Attribute &attr);
|
||||
|
||||
void get_uv_tiles(Geometry *geom, AttributePrimitive prim, unordered_set<int> &tiles) const;
|
||||
};
|
||||
|
||||
@@ -192,12 +175,11 @@ class Attribute {
|
||||
* Set of attributes on a mesh. */
|
||||
|
||||
class AttributeSet {
|
||||
uint32_t modified_flag;
|
||||
|
||||
public:
|
||||
Geometry *geometry;
|
||||
AttributePrimitive prim;
|
||||
list<Attribute> attributes;
|
||||
bool modified = true;
|
||||
|
||||
AttributeSet(Geometry *geometry, AttributePrimitive prim);
|
||||
AttributeSet(AttributeSet &&) = default;
|
||||
@@ -215,8 +197,6 @@ class AttributeSet {
|
||||
|
||||
void remove(Attribute *attribute);
|
||||
|
||||
void remove(list<Attribute>::iterator it);
|
||||
|
||||
void resize(bool reserve_only = false);
|
||||
void clear(bool preserve_voxel_data = false);
|
||||
|
||||
@@ -224,18 +204,7 @@ class AttributeSet {
|
||||
* and remove any attribute not found on the new set from this. */
|
||||
void update(AttributeSet &&new_attributes);
|
||||
|
||||
/* Return whether the attributes of the given kernel_type are modified, where "modified" means
|
||||
* that some attributes of the given type were added or removed from this AttributeSet. This does
|
||||
* not mean that the data of the remaining attributes in this AttributeSet were also modified. To
|
||||
* check this, use Attribute.modified. */
|
||||
bool modified(AttrKernelDataType kernel_type) const;
|
||||
|
||||
void clear_modified();
|
||||
|
||||
private:
|
||||
/* Set the relevant modified flag for the attribute. Only attributes that are stored in device
|
||||
* arrays will be considered for tagging this AttributeSet as modified. */
|
||||
void tag_modified(const Attribute &attr);
|
||||
};
|
||||
|
||||
/* AttributeRequest
|
||||
|
@@ -59,7 +59,6 @@ Background::Background() : Node(get_node_type())
|
||||
|
||||
Background::~Background()
|
||||
{
|
||||
dereference_all_used_nodes();
|
||||
}
|
||||
|
||||
void Background::device_update(Device *device, DeviceScene *dscene, Scene *scene)
|
||||
|
@@ -46,12 +46,6 @@ CCL_NAMESPACE_BEGIN
|
||||
|
||||
/* Geometry */
|
||||
|
||||
PackFlags operator|=(PackFlags &pack_flags, uint32_t value)
|
||||
{
|
||||
pack_flags = (PackFlags)((uint32_t)pack_flags | value);
|
||||
return pack_flags;
|
||||
}
|
||||
|
||||
NODE_ABSTRACT_DEFINE(Geometry)
|
||||
{
|
||||
NodeType *type = NodeType::add("geometry_base", NULL);
|
||||
@@ -85,7 +79,6 @@ Geometry::Geometry(const NodeType *node_type, const Type type)
|
||||
|
||||
Geometry::~Geometry()
|
||||
{
|
||||
dereference_all_used_nodes();
|
||||
delete bvh;
|
||||
}
|
||||
|
||||
@@ -830,13 +823,10 @@ void GeometryManager::device_update_attributes(Device *device,
|
||||
dscene->attributes_float3.alloc(attr_float3_size);
|
||||
dscene->attributes_uchar4.alloc(attr_uchar4_size);
|
||||
|
||||
/* The order of those flags needs to match that of AttrKernelDataType. */
|
||||
const bool attributes_need_realloc[4] = {
|
||||
dscene->attributes_float.need_realloc(),
|
||||
dscene->attributes_float2.need_realloc(),
|
||||
dscene->attributes_float3.need_realloc(),
|
||||
dscene->attributes_uchar4.need_realloc(),
|
||||
};
|
||||
const bool copy_all_data = dscene->attributes_float.need_realloc() ||
|
||||
dscene->attributes_float2.need_realloc() ||
|
||||
dscene->attributes_float3.need_realloc() ||
|
||||
dscene->attributes_uchar4.need_realloc();
|
||||
|
||||
size_t attr_float_offset = 0;
|
||||
size_t attr_float2_offset = 0;
|
||||
@@ -855,7 +845,7 @@ void GeometryManager::device_update_attributes(Device *device,
|
||||
|
||||
if (attr) {
|
||||
/* force a copy if we need to reallocate all the data */
|
||||
attr->modified |= attributes_need_realloc[Attribute::kernel_type(*attr)];
|
||||
attr->modified |= copy_all_data;
|
||||
}
|
||||
|
||||
update_attribute_element_offset(geom,
|
||||
@@ -878,7 +868,7 @@ void GeometryManager::device_update_attributes(Device *device,
|
||||
|
||||
if (subd_attr) {
|
||||
/* force a copy if we need to reallocate all the data */
|
||||
subd_attr->modified |= attributes_need_realloc[Attribute::kernel_type(*subd_attr)];
|
||||
subd_attr->modified |= copy_all_data;
|
||||
}
|
||||
|
||||
update_attribute_element_offset(mesh,
|
||||
@@ -909,10 +899,6 @@ void GeometryManager::device_update_attributes(Device *device,
|
||||
foreach (AttributeRequest &req, attributes.requests) {
|
||||
Attribute *attr = values.find(req);
|
||||
|
||||
if (attr) {
|
||||
attr->modified |= attributes_need_realloc[Attribute::kernel_type(*attr)];
|
||||
}
|
||||
|
||||
update_attribute_element_offset(object->geometry,
|
||||
dscene->attributes_float,
|
||||
attr_float_offset,
|
||||
@@ -948,10 +934,10 @@ void GeometryManager::device_update_attributes(Device *device,
|
||||
/* copy to device */
|
||||
progress.set_status("Updating Mesh", "Copying Attributes to device");
|
||||
|
||||
dscene->attributes_float.copy_to_device_if_modified();
|
||||
dscene->attributes_float2.copy_to_device_if_modified();
|
||||
dscene->attributes_float3.copy_to_device_if_modified();
|
||||
dscene->attributes_uchar4.copy_to_device_if_modified();
|
||||
dscene->attributes_float.copy_to_device();
|
||||
dscene->attributes_float2.copy_to_device();
|
||||
dscene->attributes_float3.copy_to_device();
|
||||
dscene->attributes_uchar4.copy_to_device();
|
||||
|
||||
if (progress.get_cancel())
|
||||
return;
|
||||
@@ -1249,16 +1235,7 @@ void GeometryManager::device_update_bvh(Device *device,
|
||||
|
||||
const bool can_refit = scene->bvh != nullptr &&
|
||||
(bparams.bvh_layout == BVHLayout::BVH_LAYOUT_OPTIX);
|
||||
|
||||
PackFlags pack_flags = PackFlags::PACK_NONE;
|
||||
|
||||
if (scene->bvh == nullptr) {
|
||||
pack_flags |= PackFlags::PACK_ALL;
|
||||
}
|
||||
|
||||
if (dscene->prim_visibility.is_modified()) {
|
||||
pack_flags |= PackFlags::PACK_VISIBILITY;
|
||||
}
|
||||
const bool pack_all = scene->bvh == nullptr;
|
||||
|
||||
BVH *bvh = scene->bvh;
|
||||
if (!scene->bvh) {
|
||||
@@ -1296,14 +1273,10 @@ void GeometryManager::device_update_bvh(Device *device,
|
||||
|
||||
pack.root_index = -1;
|
||||
|
||||
if (pack_flags != PackFlags::PACK_ALL) {
|
||||
if (!pack_all) {
|
||||
/* if we do not need to recreate the BVH, then only the vertices are updated, so we can
|
||||
* safely retake the memory */
|
||||
dscene->prim_tri_verts.give_data(pack.prim_tri_verts);
|
||||
|
||||
if ((pack_flags & PackFlags::PACK_VISIBILITY) != 0) {
|
||||
dscene->prim_visibility.give_data(pack.prim_visibility);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* It is not strictly necessary to skip those resizes we if do not have to repack, as the OS
|
||||
@@ -1332,21 +1305,13 @@ void GeometryManager::device_update_bvh(Device *device,
|
||||
// Iterate over scene mesh list instead of objects, since 'optix_prim_offset' was calculated
|
||||
// based on that list, which may be ordered differently from the object list.
|
||||
foreach (Geometry *geom, scene->geometry) {
|
||||
/* Make a copy of the pack_flags so the current geometry's flags do not pollute the others'.
|
||||
*/
|
||||
PackFlags geom_pack_flags = pack_flags;
|
||||
|
||||
if (geom->is_modified()) {
|
||||
geom_pack_flags |= PackFlags::PACK_VERTICES;
|
||||
}
|
||||
|
||||
if (geom_pack_flags == PACK_NONE) {
|
||||
if (!pack_all && !geom->is_modified()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const pair<int, uint> &info = geometry_to_object_info[geom];
|
||||
pool.push(function_bind(
|
||||
&Geometry::pack_primitives, geom, &pack, info.first, info.second, geom_pack_flags));
|
||||
&Geometry::pack_primitives, geom, &pack, info.first, info.second, pack_all));
|
||||
}
|
||||
pool.wait_work();
|
||||
}
|
||||
@@ -1381,7 +1346,7 @@ void GeometryManager::device_update_bvh(Device *device,
|
||||
dscene->prim_type.steal_data(pack.prim_type);
|
||||
dscene->prim_type.copy_to_device();
|
||||
}
|
||||
if (pack.prim_visibility.size() && (dscene->prim_visibility.is_modified() || has_bvh2_layout)) {
|
||||
if (pack.prim_visibility.size() && (dscene->prim_visibility.need_realloc() || has_bvh2_layout)) {
|
||||
dscene->prim_visibility.steal_data(pack.prim_visibility);
|
||||
dscene->prim_visibility.copy_to_device();
|
||||
}
|
||||
@@ -1438,43 +1403,21 @@ static void update_device_flags_attribute(uint32_t &device_update_flags,
|
||||
continue;
|
||||
}
|
||||
|
||||
AttrKernelDataType kernel_type = Attribute::kernel_type(attr);
|
||||
|
||||
switch (kernel_type) {
|
||||
case AttrKernelDataType::FLOAT: {
|
||||
device_update_flags |= ATTR_FLOAT_MODIFIED;
|
||||
break;
|
||||
}
|
||||
case AttrKernelDataType::FLOAT2: {
|
||||
device_update_flags |= ATTR_FLOAT2_MODIFIED;
|
||||
break;
|
||||
}
|
||||
case AttrKernelDataType::FLOAT3: {
|
||||
device_update_flags |= ATTR_FLOAT3_MODIFIED;
|
||||
break;
|
||||
}
|
||||
case AttrKernelDataType::UCHAR4: {
|
||||
device_update_flags |= ATTR_UCHAR4_MODIFIED;
|
||||
break;
|
||||
}
|
||||
if (attr.element == ATTR_ELEMENT_CORNER) {
|
||||
device_update_flags |= ATTR_UCHAR4_MODIFIED;
|
||||
}
|
||||
else if (attr.type == TypeDesc::TypeFloat) {
|
||||
device_update_flags |= ATTR_FLOAT_MODIFIED;
|
||||
}
|
||||
else if (attr.type == TypeFloat2) {
|
||||
device_update_flags |= ATTR_FLOAT2_MODIFIED;
|
||||
}
|
||||
else if (attr.type == TypeDesc::TypeMatrix) {
|
||||
device_update_flags |= ATTR_FLOAT3_MODIFIED;
|
||||
}
|
||||
else if (attr.element != ATTR_ELEMENT_VOXEL) {
|
||||
device_update_flags |= ATTR_FLOAT3_MODIFIED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void update_attribute_realloc_flags(uint32_t &device_update_flags,
|
||||
const AttributeSet &attributes)
|
||||
{
|
||||
if (attributes.modified(AttrKernelDataType::FLOAT)) {
|
||||
device_update_flags |= ATTR_FLOAT_NEEDS_REALLOC;
|
||||
}
|
||||
if (attributes.modified(AttrKernelDataType::FLOAT2)) {
|
||||
device_update_flags |= ATTR_FLOAT2_NEEDS_REALLOC;
|
||||
}
|
||||
if (attributes.modified(AttrKernelDataType::FLOAT3)) {
|
||||
device_update_flags |= ATTR_FLOAT3_NEEDS_REALLOC;
|
||||
}
|
||||
if (attributes.modified(AttrKernelDataType::UCHAR4)) {
|
||||
device_update_flags |= ATTR_UCHAR4_NEEDS_REALLOC;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1500,11 +1443,16 @@ void GeometryManager::device_update_preprocess(Device *device, Scene *scene, Pro
|
||||
foreach (Geometry *geom, scene->geometry) {
|
||||
geom->has_volume = false;
|
||||
|
||||
update_attribute_realloc_flags(device_update_flags, geom->attributes);
|
||||
if (geom->attributes.modified) {
|
||||
device_update_flags |= ATTRS_NEED_REALLOC;
|
||||
}
|
||||
|
||||
if (geom->is_mesh()) {
|
||||
Mesh *mesh = static_cast<Mesh *>(geom);
|
||||
update_attribute_realloc_flags(device_update_flags, mesh->subd_attributes);
|
||||
|
||||
if (mesh->subd_attributes.modified) {
|
||||
device_update_flags |= ATTRS_NEED_REALLOC;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (Node *node, geom->get_used_shaders()) {
|
||||
@@ -1646,10 +1594,6 @@ void GeometryManager::device_update_preprocess(Device *device, Scene *scene, Pro
|
||||
}
|
||||
}
|
||||
|
||||
if ((update_flags & VISIBILITY_MODIFIED) != 0) {
|
||||
dscene->prim_visibility.tag_modified();
|
||||
}
|
||||
|
||||
if (device_update_flags & ATTR_FLOAT_NEEDS_REALLOC) {
|
||||
dscene->attributes_map.tag_realloc();
|
||||
dscene->attributes_float.tag_realloc();
|
||||
@@ -1976,8 +1920,7 @@ void GeometryManager::device_update(Device *device,
|
||||
* Also update the BVH if the transformations change, we cannot rely on tagging the Geometry
|
||||
* as modified in this case, as we may accumulate displacement if the vertices do not also
|
||||
* change. */
|
||||
bool need_update_scene_bvh = (scene->bvh == nullptr ||
|
||||
(update_flags & (TRANSFORM_MODIFIED | VISIBILITY_MODIFIED)) != 0);
|
||||
bool need_update_scene_bvh = (scene->bvh == nullptr || (update_flags & TRANSFORM_MODIFIED) != 0);
|
||||
{
|
||||
scoped_callback_timer timer([scene](double time) {
|
||||
if (scene->update_stats) {
|
||||
@@ -2063,7 +2006,7 @@ void GeometryManager::device_update(Device *device,
|
||||
* for meshes with correct bounding boxes.
|
||||
*
|
||||
* This wouldn't cause wrong results, just true
|
||||
* displacement might be less optimal to calculate.
|
||||
* displacement might be less optimal ot calculate.
|
||||
*/
|
||||
scene->object_manager->need_flags_update = old_need_object_flags_update;
|
||||
}
|
||||
|
@@ -43,24 +43,6 @@ class Shader;
|
||||
class Volume;
|
||||
struct PackedBVH;
|
||||
|
||||
/* Flags used to determine which geometry data need to be packed. */
|
||||
enum PackFlags : uint32_t {
|
||||
PACK_NONE = 0u,
|
||||
|
||||
/* Pack the geometry information (e.g. triangle or curve keys indices). */
|
||||
PACK_GEOMETRY = (1u << 0),
|
||||
|
||||
/* Pack the vertices, for Meshes and Volumes' bounding meshes. */
|
||||
PACK_VERTICES = (1u << 1),
|
||||
|
||||
/* Pack the visibility flags for each triangle or curve. */
|
||||
PACK_VISIBILITY = (1u << 2),
|
||||
|
||||
PACK_ALL = (PACK_GEOMETRY | PACK_VERTICES | PACK_VISIBILITY),
|
||||
};
|
||||
|
||||
PackFlags operator|=(PackFlags &pack_flags, uint32_t value);
|
||||
|
||||
/* Geometry
|
||||
*
|
||||
* Base class for geometric types like Mesh and Hair. */
|
||||
@@ -144,10 +126,7 @@ class Geometry : public Node {
|
||||
int n,
|
||||
int total);
|
||||
|
||||
virtual void pack_primitives(PackedBVH *pack,
|
||||
int object,
|
||||
uint visibility,
|
||||
PackFlags pack_flags) = 0;
|
||||
virtual void pack_primitives(PackedBVH *pack, int object, uint visibility, bool pack_all) = 0;
|
||||
|
||||
/* Check whether the geometry should have own BVH built separately. Briefly,
|
||||
* own BVH is needed for geometry, if:
|
||||
@@ -212,8 +191,6 @@ class GeometryManager {
|
||||
|
||||
TRANSFORM_MODIFIED = (1 << 10),
|
||||
|
||||
VISIBILITY_MODIFIED = (1 << 11),
|
||||
|
||||
/* tag everything in the manager for an update */
|
||||
UPDATE_ALL = ~0u,
|
||||
|
||||
|
@@ -494,47 +494,38 @@ void Hair::pack_curves(Scene *scene,
|
||||
}
|
||||
}
|
||||
|
||||
void Hair::pack_primitives(PackedBVH *pack, int object, uint visibility, PackFlags pack_flags)
|
||||
void Hair::pack_primitives(PackedBVH *pack, int object, uint visibility, bool pack_all)
|
||||
{
|
||||
if (curve_first_key.empty())
|
||||
return;
|
||||
|
||||
/* Separate loop as other arrays are not initialized if their packing is not required. */
|
||||
if ((pack_flags & PACK_VISIBILITY) != 0) {
|
||||
unsigned int *prim_visibility = &pack->prim_visibility[optix_prim_offset];
|
||||
|
||||
size_t index = 0;
|
||||
for (size_t j = 0; j < num_curves(); ++j) {
|
||||
Curve curve = get_curve(j);
|
||||
for (size_t k = 0; k < curve.num_segments(); ++k, ++index) {
|
||||
prim_visibility[index] = visibility;
|
||||
}
|
||||
}
|
||||
/* If the BVH does not have to be recreated, we can bail out. */
|
||||
if (!pack_all) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((pack_flags & PACK_GEOMETRY) != 0) {
|
||||
unsigned int *prim_tri_index = &pack->prim_tri_index[optix_prim_offset];
|
||||
int *prim_type = &pack->prim_type[optix_prim_offset];
|
||||
int *prim_index = &pack->prim_index[optix_prim_offset];
|
||||
int *prim_object = &pack->prim_object[optix_prim_offset];
|
||||
// 'pack->prim_time' is unused by Embree and OptiX
|
||||
unsigned int *prim_tri_index = &pack->prim_tri_index[optix_prim_offset];
|
||||
int *prim_type = &pack->prim_type[optix_prim_offset];
|
||||
unsigned int *prim_visibility = &pack->prim_visibility[optix_prim_offset];
|
||||
int *prim_index = &pack->prim_index[optix_prim_offset];
|
||||
int *prim_object = &pack->prim_object[optix_prim_offset];
|
||||
// 'pack->prim_time' is unused by Embree and OptiX
|
||||
|
||||
uint type = has_motion_blur() ?
|
||||
((curve_shape == CURVE_RIBBON) ? PRIMITIVE_MOTION_CURVE_RIBBON :
|
||||
PRIMITIVE_MOTION_CURVE_THICK) :
|
||||
((curve_shape == CURVE_RIBBON) ? PRIMITIVE_CURVE_RIBBON :
|
||||
PRIMITIVE_CURVE_THICK);
|
||||
uint type = has_motion_blur() ?
|
||||
((curve_shape == CURVE_RIBBON) ? PRIMITIVE_MOTION_CURVE_RIBBON :
|
||||
PRIMITIVE_MOTION_CURVE_THICK) :
|
||||
((curve_shape == CURVE_RIBBON) ? PRIMITIVE_CURVE_RIBBON : PRIMITIVE_CURVE_THICK);
|
||||
|
||||
size_t index = 0;
|
||||
for (size_t j = 0; j < num_curves(); ++j) {
|
||||
Curve curve = get_curve(j);
|
||||
for (size_t k = 0; k < curve.num_segments(); ++k, ++index) {
|
||||
prim_tri_index[index] = -1;
|
||||
prim_type[index] = PRIMITIVE_PACK_SEGMENT(type, k);
|
||||
// Each curve segment points back to its curve index
|
||||
prim_index[index] = j + prim_offset;
|
||||
prim_object[index] = object;
|
||||
}
|
||||
size_t index = 0;
|
||||
for (size_t j = 0; j < num_curves(); ++j) {
|
||||
Curve curve = get_curve(j);
|
||||
for (size_t k = 0; k < curve.num_segments(); ++k, ++index) {
|
||||
prim_tri_index[index] = -1;
|
||||
prim_type[index] = PRIMITIVE_PACK_SEGMENT(type, k);
|
||||
prim_visibility[index] = visibility;
|
||||
// Each curve segment points back to its curve index
|
||||
prim_index[index] = j + prim_offset;
|
||||
prim_object[index] = object;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -146,10 +146,7 @@ class Hair : public Geometry {
|
||||
/* BVH */
|
||||
void pack_curves(Scene *scene, float4 *curve_key_co, float4 *curve_data, size_t curvekey_offset);
|
||||
|
||||
void pack_primitives(PackedBVH *pack,
|
||||
int object,
|
||||
uint visibility,
|
||||
PackFlags pack_flags) override;
|
||||
void pack_primitives(PackedBVH *pack, int object, uint visibility, bool pack_all) override;
|
||||
};
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
@@ -159,7 +159,6 @@ NODE_DEFINE(Light)
|
||||
|
||||
Light::Light() : Node(get_node_type())
|
||||
{
|
||||
dereference_all_used_nodes();
|
||||
}
|
||||
|
||||
void Light::tag_update(Scene *scene)
|
||||
@@ -865,7 +864,7 @@ void LightManager::device_update_points(Device *, DeviceScene *dscene, Scene *sc
|
||||
const float min_spread_angle = 1.0f * M_PI_F / 180.0f;
|
||||
const float spread_angle = 0.5f * (M_PI_F - max(light->spread, min_spread_angle));
|
||||
/* Normalization computed using:
|
||||
* integrate cos(x) * (1 - tan(x) * tan(a)) * sin(x) from x = 0 to pi/2 - a. */
|
||||
* integrate cos(x) (1 - tan(x) * tan(a)) * sin(x) from x = a to pi/2. */
|
||||
const float tan_spread = tanf(spread_angle);
|
||||
const float normalize_spread = 2.0f / (2.0f + (2.0f * spread_angle - M_PI_F) * tan_spread);
|
||||
|
||||
|
@@ -805,7 +805,7 @@ void Mesh::pack_patches(uint *patch_data, uint vert_offset, uint face_offset, ui
|
||||
}
|
||||
}
|
||||
|
||||
void Mesh::pack_primitives(ccl::PackedBVH *pack, int object, uint visibility, PackFlags pack_flags)
|
||||
void Mesh::pack_primitives(ccl::PackedBVH *pack, int object, uint visibility, bool pack_all)
|
||||
{
|
||||
if (triangles.empty())
|
||||
return;
|
||||
@@ -819,38 +819,28 @@ void Mesh::pack_primitives(ccl::PackedBVH *pack, int object, uint visibility, Pa
|
||||
|
||||
uint type = has_motion_blur() ? PRIMITIVE_MOTION_TRIANGLE : PRIMITIVE_TRIANGLE;
|
||||
|
||||
/* Separate loop as other arrays are not initialized if their packing is not required. */
|
||||
if ((pack_flags & PackFlags::PACK_VISIBILITY) != 0) {
|
||||
unsigned int *prim_visibility = &pack->prim_visibility[optix_prim_offset];
|
||||
for (size_t k = 0; k < num_prims; ++k) {
|
||||
prim_visibility[k] = visibility;
|
||||
}
|
||||
}
|
||||
|
||||
if ((pack_flags & PackFlags::PACK_GEOMETRY) != 0) {
|
||||
if (pack_all) {
|
||||
/* Use optix_prim_offset for indexing as those arrays also contain data for Hair geometries. */
|
||||
unsigned int *prim_tri_index = &pack->prim_tri_index[optix_prim_offset];
|
||||
int *prim_type = &pack->prim_type[optix_prim_offset];
|
||||
unsigned int *prim_visibility = &pack->prim_visibility[optix_prim_offset];
|
||||
int *prim_index = &pack->prim_index[optix_prim_offset];
|
||||
int *prim_object = &pack->prim_object[optix_prim_offset];
|
||||
|
||||
for (size_t k = 0; k < num_prims; ++k) {
|
||||
if ((pack_flags & PackFlags::PACK_GEOMETRY) != 0) {
|
||||
prim_tri_index[k] = (prim_offset + k) * 3;
|
||||
prim_type[k] = type;
|
||||
prim_index[k] = prim_offset + k;
|
||||
prim_object[k] = object;
|
||||
}
|
||||
prim_tri_index[k] = (prim_offset + k) * 3;
|
||||
prim_type[k] = type;
|
||||
prim_index[k] = prim_offset + k;
|
||||
prim_object[k] = object;
|
||||
prim_visibility[k] = visibility;
|
||||
}
|
||||
}
|
||||
|
||||
if ((pack_flags & PackFlags::PACK_VERTICES) != 0) {
|
||||
for (size_t k = 0; k < num_prims; ++k) {
|
||||
const Mesh::Triangle t = get_triangle(k);
|
||||
prim_tri_verts[k * 3] = float3_to_float4(verts[t.v[0]]);
|
||||
prim_tri_verts[k * 3 + 1] = float3_to_float4(verts[t.v[1]]);
|
||||
prim_tri_verts[k * 3 + 2] = float3_to_float4(verts[t.v[2]]);
|
||||
}
|
||||
for (size_t k = 0; k < num_prims; ++k) {
|
||||
const Mesh::Triangle t = get_triangle(k);
|
||||
prim_tri_verts[k * 3] = float3_to_float4(verts[t.v[0]]);
|
||||
prim_tri_verts[k * 3 + 1] = float3_to_float4(verts[t.v[1]]);
|
||||
prim_tri_verts[k * 3 + 2] = float3_to_float4(verts[t.v[2]]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -232,10 +232,7 @@ class Mesh : public Geometry {
|
||||
size_t tri_offset);
|
||||
void pack_patches(uint *patch_data, uint vert_offset, uint face_offset, uint corner_offset);
|
||||
|
||||
void pack_primitives(PackedBVH *pack,
|
||||
int object,
|
||||
uint visibility,
|
||||
PackFlags pack_flags) override;
|
||||
void pack_primitives(PackedBVH *pack, int object, uint visibility, bool pack_all) override;
|
||||
|
||||
void tessellate(DiagSplit *split);
|
||||
|
||||
|
@@ -1600,23 +1600,11 @@ class SetNormalNode : public ShaderNode {
|
||||
NODE_SOCKET_API(float3, direction)
|
||||
};
|
||||
|
||||
class OSLNode final : public ShaderNode {
|
||||
class OSLNode : public ShaderNode {
|
||||
public:
|
||||
static OSLNode *create(ShaderGraph *graph, size_t num_inputs, const OSLNode *from = NULL);
|
||||
~OSLNode();
|
||||
|
||||
static void operator delete(void *ptr)
|
||||
{
|
||||
/* Override delete operator to silence new-delete-type-mismatch ASAN warnings
|
||||
* regarding size mismatch in the destructor. This is intentional as we allocate
|
||||
* extra space at the end of the node. */
|
||||
::operator delete(ptr);
|
||||
}
|
||||
static void operator delete(void *, void *)
|
||||
{
|
||||
/* Deliberately empty placement delete operator, to avoid MSVC warning C4291. */
|
||||
}
|
||||
|
||||
ShaderNode *clone(ShaderGraph *graph) const;
|
||||
|
||||
char *input_default_value();
|
||||
|
@@ -220,10 +220,6 @@ void Object::tag_update(Scene *scene)
|
||||
flag |= ObjectManager::TRANSFORM_MODIFIED;
|
||||
}
|
||||
|
||||
if (visibility_is_modified()) {
|
||||
flag |= ObjectManager::VISIBILITY_MODIFIED;
|
||||
}
|
||||
|
||||
foreach (Node *node, geometry->get_used_shaders()) {
|
||||
Shader *shader = static_cast<Shader *>(node);
|
||||
if (shader->get_use_mis() && shader->has_surface_emission)
|
||||
@@ -918,10 +914,6 @@ void ObjectManager::tag_update(Scene *scene, uint32_t flag)
|
||||
geometry_flag |= GeometryManager::TRANSFORM_MODIFIED;
|
||||
}
|
||||
|
||||
if ((flag & VISIBILITY_MODIFIED) != 0) {
|
||||
geometry_flag |= GeometryManager::VISIBILITY_MODIFIED;
|
||||
}
|
||||
|
||||
scene->geometry_manager->tag_update(scene, geometry_flag);
|
||||
}
|
||||
|
||||
|
@@ -134,7 +134,6 @@ class ObjectManager {
|
||||
OBJECT_MODIFIED = (1 << 5),
|
||||
HOLDOUT_MODIFIED = (1 << 6),
|
||||
TRANSFORM_MODIFIED = (1 << 7),
|
||||
VISIBILITY_MODIFIED = (1 << 8),
|
||||
|
||||
/* tag everything in the manager for an update */
|
||||
UPDATE_ALL = ~0u,
|
||||
|
@@ -91,10 +91,10 @@ void OSLShaderManager::reset(Scene * /*scene*/)
|
||||
shading_system_init();
|
||||
}
|
||||
|
||||
void OSLShaderManager::device_update_specific(Device *device,
|
||||
DeviceScene *dscene,
|
||||
Scene *scene,
|
||||
Progress &progress)
|
||||
void OSLShaderManager::device_update(Device *device,
|
||||
DeviceScene *dscene,
|
||||
Scene *scene,
|
||||
Progress &progress)
|
||||
{
|
||||
if (!need_update())
|
||||
return;
|
||||
@@ -1149,7 +1149,7 @@ void OSLCompiler::compile(OSLGlobals *og, Shader *shader)
|
||||
shader->has_integrator_dependency = false;
|
||||
|
||||
/* generate surface shader */
|
||||
if (shader->reference_count() && graph && output->input("Surface")->link) {
|
||||
if (shader->used && graph && output->input("Surface")->link) {
|
||||
shader->osl_surface_ref = compile_type(shader, shader->graph, SHADER_TYPE_SURFACE);
|
||||
|
||||
if (has_bump)
|
||||
@@ -1165,7 +1165,7 @@ void OSLCompiler::compile(OSLGlobals *og, Shader *shader)
|
||||
}
|
||||
|
||||
/* generate volume shader */
|
||||
if (shader->reference_count() && graph && output->input("Volume")->link) {
|
||||
if (shader->used && graph && output->input("Volume")->link) {
|
||||
shader->osl_volume_ref = compile_type(shader, shader->graph, SHADER_TYPE_VOLUME);
|
||||
shader->has_volume = true;
|
||||
}
|
||||
@@ -1173,7 +1173,7 @@ void OSLCompiler::compile(OSLGlobals *og, Shader *shader)
|
||||
shader->osl_volume_ref = OSL::ShaderGroupRef();
|
||||
|
||||
/* generate displacement shader */
|
||||
if (shader->reference_count() && graph && output->input("Displacement")->link) {
|
||||
if (shader->used && graph && output->input("Displacement")->link) {
|
||||
shader->osl_displacement_ref = compile_type(shader, shader->graph, SHADER_TYPE_DISPLACEMENT);
|
||||
shader->has_displacement = true;
|
||||
}
|
||||
|
@@ -72,18 +72,15 @@ class OSLShaderManager : public ShaderManager {
|
||||
|
||||
static void free_memory();
|
||||
|
||||
void reset(Scene *scene) override;
|
||||
void reset(Scene *scene);
|
||||
|
||||
bool use_osl() override
|
||||
bool use_osl()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void device_update_specific(Device *device,
|
||||
DeviceScene *dscene,
|
||||
Scene *scene,
|
||||
Progress &progress) override;
|
||||
void device_free(Device *device, DeviceScene *dscene, Scene *scene) override;
|
||||
void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress);
|
||||
void device_free(Device *device, DeviceScene *dscene, Scene *scene);
|
||||
|
||||
/* osl compile and query */
|
||||
static bool osl_compile(const string &inputfile, const string &outputfile);
|
||||
|
@@ -143,27 +143,21 @@ void Scene::free_memory(bool final)
|
||||
delete bvh;
|
||||
bvh = NULL;
|
||||
|
||||
/* The order of deletion is important to make sure data is freed based on possible dependencies
|
||||
* as the Nodes' reference counts are decremented in the destructors:
|
||||
*
|
||||
* - Procedurals can create and hold pointers to any other types.
|
||||
* - Objects can hold pointers to Geometries and ParticleSystems
|
||||
* - Lights and Geometries can hold pointers to Shaders.
|
||||
*
|
||||
* Similarly, we first delete all nodes and their associated device data, and then the managers
|
||||
* and their associated device data.
|
||||
*/
|
||||
foreach (Shader *s, shaders)
|
||||
delete s;
|
||||
/* delete procedurals before other types as they may hold pointers to those types */
|
||||
foreach (Procedural *p, procedurals)
|
||||
delete p;
|
||||
foreach (Object *o, objects)
|
||||
delete o;
|
||||
foreach (Geometry *g, geometry)
|
||||
delete g;
|
||||
foreach (ParticleSystem *p, particle_systems)
|
||||
delete p;
|
||||
foreach (Object *o, objects)
|
||||
delete o;
|
||||
foreach (Light *l, lights)
|
||||
delete l;
|
||||
foreach (ParticleSystem *p, particle_systems)
|
||||
delete p;
|
||||
|
||||
shaders.clear();
|
||||
geometry.clear();
|
||||
objects.clear();
|
||||
lights.clear();
|
||||
@@ -175,25 +169,7 @@ void Scene::free_memory(bool final)
|
||||
film->device_free(device, &dscene, this);
|
||||
background->device_free(device, &dscene);
|
||||
integrator->device_free(device, &dscene, true);
|
||||
}
|
||||
|
||||
if (final) {
|
||||
delete camera;
|
||||
delete dicing_camera;
|
||||
delete film;
|
||||
delete background;
|
||||
delete integrator;
|
||||
}
|
||||
|
||||
/* Delete Shaders after every other nodes to ensure that we do not try to decrement the reference
|
||||
* count on some dangling pointer. */
|
||||
foreach (Shader *s, shaders)
|
||||
delete s;
|
||||
|
||||
shaders.clear();
|
||||
|
||||
/* Now that all nodes have been deleted, we can safely delete managers and device data. */
|
||||
if (device) {
|
||||
object_manager->device_free(device, &dscene, true);
|
||||
geometry_manager->device_free(device, &dscene, true);
|
||||
shader_manager->device_free(device, &dscene, this);
|
||||
@@ -213,6 +189,11 @@ void Scene::free_memory(bool final)
|
||||
|
||||
if (final) {
|
||||
delete lookup_tables;
|
||||
delete camera;
|
||||
delete dicing_camera;
|
||||
delete film;
|
||||
delete background;
|
||||
delete integrator;
|
||||
delete object_manager;
|
||||
delete geometry_manager;
|
||||
delete shader_manager;
|
||||
@@ -523,6 +504,9 @@ bool Scene::update(Progress &progress, bool &kernel_switch_needed)
|
||||
{
|
||||
/* update scene */
|
||||
if (need_update()) {
|
||||
/* Updated used shader tag so we know which features are need for the kernel. */
|
||||
shader_manager->update_shaders_used(this);
|
||||
|
||||
/* Update max_closures. */
|
||||
KernelIntegrator *kintegrator = &dscene.data.integrator;
|
||||
if (params.background) {
|
||||
@@ -542,6 +526,9 @@ bool Scene::update(Progress &progress, bool &kernel_switch_needed)
|
||||
DeviceKernelStatus kernel_switch_status = device->get_active_kernel_switch_state();
|
||||
kernel_switch_needed = kernel_switch_status == DEVICE_KERNEL_FEATURE_KERNEL_AVAILABLE ||
|
||||
kernel_switch_status == DEVICE_KERNEL_FEATURE_KERNEL_INVALID;
|
||||
if (kernel_switch_status == DEVICE_KERNEL_WAITING_FOR_FEATURE_KERNEL) {
|
||||
progress.set_kernel_status("Compiling render kernels");
|
||||
}
|
||||
if (new_kernels_needed || kernel_switch_needed) {
|
||||
progress.set_kernel_status("Compiling render kernels");
|
||||
device->wait_for_availability(loaded_kernel_features);
|
||||
@@ -579,6 +566,9 @@ bool Scene::load_kernels(Progress &progress, bool lock_scene)
|
||||
return false;
|
||||
}
|
||||
|
||||
progress.add_skip_time(timer, false);
|
||||
VLOG(1) << "Total time spent loading kernels: " << time_dt() - timer.get_start();
|
||||
|
||||
kernels_loaded = true;
|
||||
loaded_kernel_features = requested_features;
|
||||
return true;
|
||||
@@ -597,7 +587,7 @@ int Scene::get_max_closure_count()
|
||||
int max_closures = 0;
|
||||
for (int i = 0; i < shaders.size(); i++) {
|
||||
Shader *shader = shaders[i];
|
||||
if (shader->reference_count()) {
|
||||
if (shader->used) {
|
||||
int num_closures = shader->graph->get_num_closures();
|
||||
max_closures = max(max_closures, num_closures);
|
||||
}
|
||||
@@ -758,10 +748,9 @@ template<> void Scene::delete_node_impl(ParticleSystem *node)
|
||||
particle_system_manager->tag_update(this);
|
||||
}
|
||||
|
||||
template<> void Scene::delete_node_impl(Shader *shader)
|
||||
template<> void Scene::delete_node_impl(Shader * /*node*/)
|
||||
{
|
||||
/* don't delete unused shaders, not supported */
|
||||
shader->clear_reference_count();
|
||||
}
|
||||
|
||||
template<> void Scene::delete_node_impl(Procedural *node)
|
||||
@@ -828,12 +817,9 @@ template<> void Scene::delete_nodes(const set<ParticleSystem *> &nodes, const No
|
||||
particle_system_manager->tag_update(this);
|
||||
}
|
||||
|
||||
template<> void Scene::delete_nodes(const set<Shader *> &nodes, const NodeOwner * /*owner*/)
|
||||
template<> void Scene::delete_nodes(const set<Shader *> & /*nodes*/, const NodeOwner * /*owner*/)
|
||||
{
|
||||
/* don't delete unused shaders, not supported */
|
||||
for (Shader *shader : nodes) {
|
||||
shader->clear_reference_count();
|
||||
}
|
||||
}
|
||||
|
||||
template<> void Scene::delete_nodes(const set<Procedural *> &nodes, const NodeOwner *owner)
|
||||
|
@@ -243,6 +243,11 @@ void Session::run_gpu()
|
||||
}
|
||||
}
|
||||
|
||||
/* Don't go in pause mode when image was rendered with preview kernels
|
||||
* When feature kernels become available the session will be reset. */
|
||||
else if (no_tiles && kernel_state == DEVICE_KERNEL_WAITING_FOR_FEATURE_KERNEL) {
|
||||
time_sleep(0.1);
|
||||
}
|
||||
else if (no_tiles && kernel_state == DEVICE_KERNEL_FEATURE_KERNEL_AVAILABLE) {
|
||||
reset_gpu(tile_manager.params, params.samples);
|
||||
}
|
||||
@@ -757,6 +762,11 @@ void Session::run_cpu()
|
||||
}
|
||||
}
|
||||
|
||||
/* Don't go in pause mode when preview kernels are used
|
||||
* When feature kernels become available the session will be reset. */
|
||||
else if (no_tiles && kernel_state == DEVICE_KERNEL_WAITING_FOR_FEATURE_KERNEL) {
|
||||
time_sleep(0.1);
|
||||
}
|
||||
else if (no_tiles && kernel_state == DEVICE_KERNEL_FEATURE_KERNEL_AVAILABLE) {
|
||||
reset_cpu(tile_manager.params, params.samples);
|
||||
}
|
||||
|
@@ -16,6 +16,7 @@
|
||||
|
||||
#include "device/device.h"
|
||||
|
||||
#include "render/alembic.h"
|
||||
#include "render/background.h"
|
||||
#include "render/camera.h"
|
||||
#include "render/colorspace.h"
|
||||
@@ -26,7 +27,6 @@
|
||||
#include "render/nodes.h"
|
||||
#include "render/object.h"
|
||||
#include "render/osl.h"
|
||||
#include "render/procedural.h"
|
||||
#include "render/scene.h"
|
||||
#include "render/shader.h"
|
||||
#include "render/svm.h"
|
||||
@@ -218,6 +218,7 @@ Shader::Shader() : Node(get_node_type())
|
||||
displacement_method = DISPLACE_BUMP;
|
||||
|
||||
id = -1;
|
||||
used = false;
|
||||
|
||||
need_update_uvs = true;
|
||||
need_update_attribute = true;
|
||||
@@ -381,9 +382,8 @@ void Shader::tag_used(Scene *scene)
|
||||
{
|
||||
/* if an unused shader suddenly gets used somewhere, it needs to be
|
||||
* recompiled because it was skipped for compilation before */
|
||||
if (!reference_count()) {
|
||||
if (!used) {
|
||||
tag_modified();
|
||||
/* We do not reference here as the shader will be referenced when added to a socket. */
|
||||
scene->shader_manager->tag_update(scene, ShaderManager::SHADER_MODIFIED);
|
||||
}
|
||||
}
|
||||
@@ -461,28 +461,52 @@ int ShaderManager::get_shader_id(Shader *shader, bool smooth)
|
||||
return id;
|
||||
}
|
||||
|
||||
void ShaderManager::device_update(Device *device,
|
||||
DeviceScene *dscene,
|
||||
Scene *scene,
|
||||
Progress &progress)
|
||||
void ShaderManager::update_shaders_used(Scene *scene)
|
||||
{
|
||||
if (!need_update()) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* figure out which shaders are in use, so SVM/OSL can skip compiling them
|
||||
* for speed and avoid loading image textures into memory */
|
||||
uint id = 0;
|
||||
foreach (Shader *shader, scene->shaders) {
|
||||
shader->used = false;
|
||||
shader->id = id++;
|
||||
}
|
||||
|
||||
/* Those shaders should always be compiled as they are used as fallback if a shader cannot be
|
||||
* found, e.g. bad shader index for the triangle shaders on a Mesh. */
|
||||
assert(scene->default_surface->reference_count() != 0);
|
||||
assert(scene->default_light->reference_count() != 0);
|
||||
assert(scene->default_background->reference_count() != 0);
|
||||
assert(scene->default_empty->reference_count() != 0);
|
||||
scene->default_surface->used = true;
|
||||
scene->default_light->used = true;
|
||||
scene->default_background->used = true;
|
||||
scene->default_empty->used = true;
|
||||
|
||||
device_update_specific(device, dscene, scene, progress);
|
||||
if (scene->background->get_shader())
|
||||
scene->background->get_shader()->used = true;
|
||||
|
||||
#ifdef WITH_ALEMBIC
|
||||
foreach (Procedural *procedural, scene->procedurals) {
|
||||
AlembicProcedural *abc_proc = static_cast<AlembicProcedural *>(procedural);
|
||||
|
||||
foreach (Node *abc_node, abc_proc->get_objects()) {
|
||||
AlembicObject *abc_object = static_cast<AlembicObject *>(abc_node);
|
||||
|
||||
foreach (Node *node, abc_object->get_used_shaders()) {
|
||||
Shader *shader = static_cast<Shader *>(node);
|
||||
shader->used = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
foreach (Geometry *geom, scene->geometry)
|
||||
foreach (Node *node, geom->get_used_shaders()) {
|
||||
Shader *shader = static_cast<Shader *>(node);
|
||||
shader->used = true;
|
||||
}
|
||||
|
||||
foreach (Light *light, scene->lights)
|
||||
if (light->get_shader())
|
||||
const_cast<Shader *>(light->get_shader())->used = true;
|
||||
}
|
||||
|
||||
void ShaderManager::device_update_common(Device *device,
|
||||
@@ -615,7 +639,6 @@ void ShaderManager::add_default(Scene *scene)
|
||||
Shader *shader = scene->create_node<Shader>();
|
||||
shader->name = "default_surface";
|
||||
shader->set_graph(graph);
|
||||
shader->reference();
|
||||
scene->default_surface = shader;
|
||||
shader->tag_update(scene);
|
||||
}
|
||||
@@ -634,8 +657,6 @@ void ShaderManager::add_default(Scene *scene)
|
||||
shader->set_graph(graph);
|
||||
scene->default_volume = shader;
|
||||
shader->tag_update(scene);
|
||||
/* No default reference for the volume to avoid compiling volume kernels if there are no actual
|
||||
* volumes in the scene */
|
||||
}
|
||||
|
||||
/* default light */
|
||||
@@ -652,7 +673,6 @@ void ShaderManager::add_default(Scene *scene)
|
||||
Shader *shader = scene->create_node<Shader>();
|
||||
shader->name = "default_light";
|
||||
shader->set_graph(graph);
|
||||
shader->reference();
|
||||
scene->default_light = shader;
|
||||
shader->tag_update(scene);
|
||||
}
|
||||
@@ -664,7 +684,6 @@ void ShaderManager::add_default(Scene *scene)
|
||||
Shader *shader = scene->create_node<Shader>();
|
||||
shader->name = "default_background";
|
||||
shader->set_graph(graph);
|
||||
shader->reference();
|
||||
scene->default_background = shader;
|
||||
shader->tag_update(scene);
|
||||
}
|
||||
@@ -676,7 +695,6 @@ void ShaderManager::add_default(Scene *scene)
|
||||
Shader *shader = scene->create_node<Shader>();
|
||||
shader->name = "default_empty";
|
||||
shader->set_graph(graph);
|
||||
shader->reference();
|
||||
scene->default_empty = shader;
|
||||
shader->tag_update(scene);
|
||||
}
|
||||
@@ -717,7 +735,7 @@ void ShaderManager::get_requested_features(Scene *scene,
|
||||
requested_features->nodes_features = 0;
|
||||
for (int i = 0; i < scene->shaders.size(); i++) {
|
||||
Shader *shader = scene->shaders[i];
|
||||
if (!shader->reference_count()) {
|
||||
if (!shader->used) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user