Compare commits
1 Commits
temp-gpenc
...
temp-inter
Author | SHA1 | Date | |
---|---|---|---|
2038250c62 |
@@ -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
|
||||
|
@@ -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?)
|
||||
|
@@ -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
|
||||
@@ -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),
|
||||
@@ -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}
|
||||
|
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;
|
||||
}
|
||||
|
@@ -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")
|
||||
|
||||
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -237,9 +237,6 @@ 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_render,
|
||||
|
@@ -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,18 +213,8 @@ void BlenderSync::sync_recalc(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d
|
||||
|
||||
if (b_v3d) {
|
||||
BlenderViewportParameters new_viewport_parameters(b_v3d);
|
||||
|
||||
if (viewport_parameters.modified(new_viewport_parameters)) {
|
||||
world_recalc = true;
|
||||
has_updates_ = true;
|
||||
}
|
||||
|
||||
if (!has_updates_) {
|
||||
Film *film = scene->film;
|
||||
|
||||
const PassType new_display_pass = new_viewport_parameters.get_viewport_display_render_pass(
|
||||
b_v3d);
|
||||
has_updates_ |= film->get_display_pass() != new_display_pass;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -248,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);
|
||||
@@ -279,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 */
|
||||
@@ -451,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();
|
||||
|
||||
@@ -766,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;
|
||||
}
|
||||
@@ -902,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) {
|
||||
@@ -957,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) {
|
||||
@@ -993,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,
|
||||
@@ -150,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);
|
||||
|
||||
@@ -264,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
|
||||
|
@@ -32,26 +32,17 @@ BlenderViewportParameters::BlenderViewportParameters()
|
||||
BlenderViewportParameters::BlenderViewportParameters(BL::SpaceView3D &b_v3d)
|
||||
: BlenderViewportParameters()
|
||||
{
|
||||
if (!b_v3d) {
|
||||
return;
|
||||
}
|
||||
|
||||
BL::View3DShading shading = b_v3d.shading();
|
||||
|
||||
/* 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) {
|
||||
return;
|
||||
}
|
||||
|
||||
use_scene_world = shading.use_scene_world_render();
|
||||
use_scene_lights = 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();
|
||||
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 = 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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.
|
||||
*/
|
||||
|
||||
|
@@ -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) {
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -132,6 +132,7 @@ class Shader : public Node {
|
||||
|
||||
/* determined before compiling */
|
||||
uint id;
|
||||
bool used;
|
||||
|
||||
#ifdef WITH_OSL
|
||||
/* osl shading state references */
|
||||
@@ -186,11 +187,10 @@ class ShaderManager {
|
||||
}
|
||||
|
||||
/* device update */
|
||||
void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress);
|
||||
virtual void device_update_specific(Device *device,
|
||||
DeviceScene *dscene,
|
||||
Scene *scene,
|
||||
Progress &progress) = 0;
|
||||
virtual void device_update(Device *device,
|
||||
DeviceScene *dscene,
|
||||
Scene *scene,
|
||||
Progress &progress) = 0;
|
||||
virtual void device_free(Device *device, DeviceScene *dscene, Scene *scene) = 0;
|
||||
|
||||
void device_update_common(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress);
|
||||
@@ -208,6 +208,7 @@ class ShaderManager {
|
||||
static void add_default(Scene *scene);
|
||||
|
||||
/* Selective nodes compilation. */
|
||||
void update_shaders_used(Scene *scene);
|
||||
void get_requested_features(Scene *scene, DeviceRequestedFeatures *requested_features);
|
||||
|
||||
static void free_memory();
|
||||
|
@@ -69,10 +69,10 @@ void SVMShaderManager::device_update_shader(Scene *scene,
|
||||
<< summary.full_report();
|
||||
}
|
||||
|
||||
void SVMShaderManager::device_update_specific(Device *device,
|
||||
DeviceScene *dscene,
|
||||
Scene *scene,
|
||||
Progress &progress)
|
||||
void SVMShaderManager::device_update(Device *device,
|
||||
DeviceScene *dscene,
|
||||
Scene *scene,
|
||||
Progress &progress)
|
||||
{
|
||||
if (!need_update())
|
||||
return;
|
||||
@@ -776,7 +776,7 @@ void SVMCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty
|
||||
add_node(NODE_ENTER_BUMP_EVAL, bump_state_offset);
|
||||
}
|
||||
|
||||
if (shader->reference_count()) {
|
||||
if (shader->used) {
|
||||
CompilerState state(graph);
|
||||
if (clin->link) {
|
||||
bool generate = false;
|
||||
|
@@ -44,13 +44,10 @@ class SVMShaderManager : public ShaderManager {
|
||||
SVMShaderManager();
|
||||
~SVMShaderManager();
|
||||
|
||||
void reset(Scene *scene) override;
|
||||
void reset(Scene *scene);
|
||||
|
||||
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);
|
||||
|
||||
protected:
|
||||
void device_update_shader(Scene *scene,
|
||||
|
@@ -362,7 +362,7 @@ ccl_device float fast_atan2f(float y, float x)
|
||||
ccl_device float fast_log2f(float x)
|
||||
{
|
||||
/* NOTE: clamp to avoid special cases and make result "safe" from large
|
||||
* negative values/NAN's. */
|
||||
* negative values/nans. */
|
||||
x = clamp(x, FLT_MIN, FLT_MAX);
|
||||
unsigned bits = __float_as_uint(x);
|
||||
int exponent = (int)(bits >> 23) - 127;
|
||||
|
@@ -145,8 +145,7 @@ int system_cpu_num_active_group_processors()
|
||||
return numaAPI_GetNumCurrentNodesProcessors();
|
||||
}
|
||||
|
||||
/* Equivalent of Windows __cpuid for x86 processors on other platforms. */
|
||||
#if (!defined(_WIN32) || defined(FREE_WINDOWS)) && (defined(__x86_64__) || defined(__i386__))
|
||||
#if !defined(_WIN32) || defined(FREE_WINDOWS)
|
||||
static void __cpuid(int data[4], int selector)
|
||||
{
|
||||
# if defined(__x86_64__)
|
||||
@@ -167,34 +166,7 @@ static void __cpuid(int data[4], int selector)
|
||||
|
||||
string system_cpu_brand_string()
|
||||
{
|
||||
#if defined(__APPLE__)
|
||||
/* Get from system on macOS. */
|
||||
char modelname[512] = "";
|
||||
size_t bufferlen = 512;
|
||||
if (sysctlbyname("machdep.cpu.brand_string", &modelname, &bufferlen, NULL, 0) == 0) {
|
||||
return modelname;
|
||||
}
|
||||
#elif defined(WIN32) || defined(__x86_64__) || defined(__i386__)
|
||||
/* Get from intrinsics on Windows and x86. */
|
||||
char buf[49] = {0};
|
||||
int result[4] = {0};
|
||||
|
||||
__cpuid(result, 0x80000000);
|
||||
|
||||
if (result[0] != 0 && result[0] >= (int)0x80000004) {
|
||||
__cpuid((int *)(buf + 0), 0x80000002);
|
||||
__cpuid((int *)(buf + 16), 0x80000003);
|
||||
__cpuid((int *)(buf + 32), 0x80000004);
|
||||
|
||||
string brand = buf;
|
||||
|
||||
/* Make it a bit more presentable. */
|
||||
brand = string_remove_trademark(brand);
|
||||
|
||||
return brand;
|
||||
}
|
||||
#else
|
||||
/* Get from /proc/cpuinfo on Unix systems. */
|
||||
#if !defined(WIN32) && !defined(__x86_64__) && !defined(__i386__)
|
||||
FILE *cpuinfo = fopen("/proc/cpuinfo", "r");
|
||||
if (cpuinfo != nullptr) {
|
||||
char cpuinfo_buf[513] = "";
|
||||
@@ -214,6 +186,24 @@ string system_cpu_brand_string()
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
char buf[49] = {0};
|
||||
int result[4] = {0};
|
||||
|
||||
__cpuid(result, 0x80000000);
|
||||
|
||||
if (result[0] != 0 && result[0] >= (int)0x80000004) {
|
||||
__cpuid((int *)(buf + 0), 0x80000002);
|
||||
__cpuid((int *)(buf + 16), 0x80000003);
|
||||
__cpuid((int *)(buf + 32), 0x80000004);
|
||||
|
||||
string brand = buf;
|
||||
|
||||
/* make it a bit more presentable */
|
||||
brand = string_remove_trademark(brand);
|
||||
|
||||
return brand;
|
||||
}
|
||||
#endif
|
||||
return "Unknown CPU";
|
||||
}
|
||||
@@ -223,7 +213,7 @@ int system_cpu_bits()
|
||||
return (sizeof(void *) * 8);
|
||||
}
|
||||
|
||||
#if defined(__x86_64__) || defined(_M_X64) || defined(__i386__) || defined(_M_IX86)
|
||||
#if defined(__x86_64__) || defined(_M_X64) || defined(i386) || defined(_M_IX86)
|
||||
|
||||
struct CPUCapabilities {
|
||||
bool x64;
|
||||
|
@@ -43,8 +43,8 @@ class vector : public std::vector<value_type, allocator_type> {
|
||||
/* Try as hard as possible to use zero memory. */
|
||||
void free_memory()
|
||||
{
|
||||
vector<value_type, allocator_type> empty;
|
||||
BaseClass::swap(empty);
|
||||
BaseClass::resize(0);
|
||||
BaseClass::shrink_to_fit();
|
||||
}
|
||||
|
||||
/* Some external API might demand working with std::vector. */
|
||||
|
@@ -22,17 +22,10 @@
|
||||
|
||||
#include <libavformat/avformat.h>
|
||||
|
||||
/* Check if our ffmpeg is new enough, avoids user complaints.
|
||||
* Minimum supported version is currently 3.2.0 which mean the following library versions:
|
||||
* libavutil > 55.30
|
||||
* libavcodec > 57.60
|
||||
* libavformat > 57.50
|
||||
*
|
||||
* We only check for one of these as they are usually updated in tandem.
|
||||
*/
|
||||
#if (LIBAVFORMAT_VERSION_MAJOR < 57) || \
|
||||
((LIBAVFORMAT_VERSION_MAJOR == 57) && (LIBAVFORMAT_VERSION_MINOR <= 50))
|
||||
# error "FFmpeg 3.2.0 or newer is needed, Upgrade your FFmpeg or disable it"
|
||||
/* check our ffmpeg is new enough, avoids user complaints */
|
||||
#if (LIBAVFORMAT_VERSION_MAJOR < 52) || \
|
||||
((LIBAVFORMAT_VERSION_MAJOR == 52) && (LIBAVFORMAT_VERSION_MINOR <= 64))
|
||||
# error "FFmpeg 0.7 or newer is needed, Upgrade your FFmpeg or disable it"
|
||||
#endif
|
||||
/* end sanity check */
|
||||
|
||||
@@ -43,6 +36,274 @@
|
||||
# define FFMPEG_INLINE static inline
|
||||
#endif
|
||||
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavutil/mathematics.h>
|
||||
#include <libavutil/opt.h>
|
||||
#include <libavutil/rational.h>
|
||||
|
||||
#if (LIBAVFORMAT_VERSION_MAJOR > 52) || \
|
||||
((LIBAVFORMAT_VERSION_MAJOR >= 52) && (LIBAVFORMAT_VERSION_MINOR >= 101))
|
||||
# define FFMPEG_HAVE_PARSE_UTILS 1
|
||||
# include <libavutil/parseutils.h>
|
||||
#endif
|
||||
|
||||
#include <libswscale/swscale.h>
|
||||
|
||||
#if (LIBAVFORMAT_VERSION_MAJOR > 52) || \
|
||||
((LIBAVFORMAT_VERSION_MAJOR >= 52) && (LIBAVFORMAT_VERSION_MINOR >= 105))
|
||||
# define FFMPEG_HAVE_AVIO 1
|
||||
#endif
|
||||
|
||||
#if (LIBAVCODEC_VERSION_MAJOR > 53) || \
|
||||
((LIBAVCODEC_VERSION_MAJOR == 53) && (LIBAVCODEC_VERSION_MINOR > 1)) || \
|
||||
((LIBAVCODEC_VERSION_MAJOR == 53) && (LIBAVCODEC_VERSION_MINOR == 1) && \
|
||||
(LIBAVCODEC_VERSION_MICRO >= 1)) || \
|
||||
((LIBAVCODEC_VERSION_MAJOR == 52) && (LIBAVCODEC_VERSION_MINOR >= 121))
|
||||
# define FFMPEG_HAVE_DEFAULT_VAL_UNION 1
|
||||
#endif
|
||||
|
||||
#if (LIBAVFORMAT_VERSION_MAJOR > 52) || \
|
||||
((LIBAVFORMAT_VERSION_MAJOR >= 52) && (LIBAVFORMAT_VERSION_MINOR >= 101))
|
||||
# define FFMPEG_HAVE_AV_DUMP_FORMAT 1
|
||||
#endif
|
||||
|
||||
#if (LIBAVFORMAT_VERSION_MAJOR > 52) || \
|
||||
((LIBAVFORMAT_VERSION_MAJOR >= 52) && (LIBAVFORMAT_VERSION_MINOR >= 45))
|
||||
# define FFMPEG_HAVE_AV_GUESS_FORMAT 1
|
||||
#endif
|
||||
|
||||
#if (LIBAVCODEC_VERSION_MAJOR > 52) || \
|
||||
((LIBAVCODEC_VERSION_MAJOR >= 52) && (LIBAVCODEC_VERSION_MINOR >= 23))
|
||||
# define FFMPEG_HAVE_DECODE_AUDIO3 1
|
||||
# define FFMPEG_HAVE_DECODE_VIDEO2 1
|
||||
#endif
|
||||
|
||||
#if (LIBAVCODEC_VERSION_MAJOR > 52) || \
|
||||
((LIBAVCODEC_VERSION_MAJOR >= 52) && (LIBAVCODEC_VERSION_MINOR >= 64))
|
||||
# define FFMPEG_HAVE_AVMEDIA_TYPES 1
|
||||
#endif
|
||||
|
||||
#if ((LIBAVCODEC_VERSION_MAJOR > 52) || \
|
||||
(LIBAVCODEC_VERSION_MAJOR >= 52) && (LIBAVCODEC_VERSION_MINOR >= 29)) && \
|
||||
((LIBSWSCALE_VERSION_MAJOR > 0) || \
|
||||
(LIBSWSCALE_VERSION_MAJOR >= 0) && (LIBSWSCALE_VERSION_MINOR >= 10))
|
||||
# define FFMPEG_SWSCALE_COLOR_SPACE_SUPPORT
|
||||
#endif
|
||||
|
||||
#if ((LIBAVCODEC_VERSION_MAJOR > 54) || \
|
||||
(LIBAVCODEC_VERSION_MAJOR >= 54) && (LIBAVCODEC_VERSION_MINOR > 14))
|
||||
# define FFMPEG_HAVE_CANON_H264_RESOLUTION_FIX
|
||||
#endif
|
||||
|
||||
#if ((LIBAVCODEC_VERSION_MAJOR > 53) || \
|
||||
(LIBAVCODEC_VERSION_MAJOR >= 53) && (LIBAVCODEC_VERSION_MINOR >= 60))
|
||||
# define FFMPEG_HAVE_ENCODE_AUDIO2
|
||||
#endif
|
||||
|
||||
#if ((LIBAVCODEC_VERSION_MAJOR > 53) || \
|
||||
(LIBAVCODEC_VERSION_MAJOR >= 53) && (LIBAVCODEC_VERSION_MINOR >= 42))
|
||||
# define FFMPEG_HAVE_DECODE_AUDIO4
|
||||
#endif
|
||||
|
||||
#if ((LIBAVCODEC_VERSION_MAJOR > 54) || \
|
||||
(LIBAVCODEC_VERSION_MAJOR >= 54) && (LIBAVCODEC_VERSION_MINOR >= 13))
|
||||
# define FFMPEG_HAVE_AVFRAME_SAMPLE_RATE
|
||||
#endif
|
||||
|
||||
#if ((LIBAVUTIL_VERSION_MAJOR > 51) || \
|
||||
(LIBAVUTIL_VERSION_MAJOR == 51) && (LIBAVUTIL_VERSION_MINOR >= 21))
|
||||
# define FFMPEG_FFV1_ALPHA_SUPPORTED
|
||||
# define FFMPEG_SAMPLE_FMT_S16P_SUPPORTED
|
||||
#else
|
||||
|
||||
FFMPEG_INLINE
|
||||
int av_sample_fmt_is_planar(enum AVSampleFormat sample_fmt)
|
||||
{
|
||||
/* no planar formats in FFmpeg < 0.9 */
|
||||
(void)sample_fmt;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* XXX TODO Probably fix to correct modern flags in code? Not sure how old FFMPEG we want to
|
||||
* support though, so for now this will do. */
|
||||
|
||||
#ifndef FF_MIN_BUFFER_SIZE
|
||||
# ifdef AV_INPUT_BUFFER_MIN_SIZE
|
||||
# define FF_MIN_BUFFER_SIZE AV_INPUT_BUFFER_MIN_SIZE
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef FF_INPUT_BUFFER_PADDING_SIZE
|
||||
# ifdef AV_INPUT_BUFFER_PADDING_SIZE
|
||||
# define FF_INPUT_BUFFER_PADDING_SIZE AV_INPUT_BUFFER_PADDING_SIZE
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef CODEC_FLAG_GLOBAL_HEADER
|
||||
# ifdef AV_CODEC_FLAG_GLOBAL_HEADER
|
||||
# define CODEC_FLAG_GLOBAL_HEADER AV_CODEC_FLAG_GLOBAL_HEADER
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef CODEC_FLAG_GLOBAL_HEADER
|
||||
# ifdef AV_CODEC_FLAG_GLOBAL_HEADER
|
||||
# define CODEC_FLAG_GLOBAL_HEADER AV_CODEC_FLAG_GLOBAL_HEADER
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef CODEC_FLAG_INTERLACED_DCT
|
||||
# ifdef AV_CODEC_FLAG_INTERLACED_DCT
|
||||
# define CODEC_FLAG_INTERLACED_DCT AV_CODEC_FLAG_INTERLACED_DCT
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef CODEC_FLAG_INTERLACED_ME
|
||||
# ifdef AV_CODEC_FLAG_INTERLACED_ME
|
||||
# define CODEC_FLAG_INTERLACED_ME AV_CODEC_FLAG_INTERLACED_ME
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* FFmpeg upstream 1.0 is the first who added AV_ prefix. */
|
||||
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54, 59, 100)
|
||||
# define AV_CODEC_ID_NONE CODEC_ID_NONE
|
||||
# define AV_CODEC_ID_MPEG4 CODEC_ID_MPEG4
|
||||
# define AV_CODEC_ID_MJPEG CODEC_ID_MJPEG
|
||||
# define AV_CODEC_ID_DNXHD CODEC_ID_DNXHD
|
||||
# define AV_CODEC_ID_MPEG2VIDEO CODEC_ID_MPEG2VIDEO
|
||||
# define AV_CODEC_ID_MPEG1VIDEO CODEC_ID_MPEG1VIDEO
|
||||
# define AV_CODEC_ID_DVVIDEO CODEC_ID_DVVIDEO
|
||||
# define AV_CODEC_ID_THEORA CODEC_ID_THEORA
|
||||
# define AV_CODEC_ID_PNG CODEC_ID_PNG
|
||||
# define AV_CODEC_ID_QTRLE CODEC_ID_QTRLE
|
||||
# define AV_CODEC_ID_FFV1 CODEC_ID_FFV1
|
||||
# define AV_CODEC_ID_HUFFYUV CODEC_ID_HUFFYUV
|
||||
# define AV_CODEC_ID_H264 CODEC_ID_H264
|
||||
# define AV_CODEC_ID_FLV1 CODEC_ID_FLV1
|
||||
|
||||
# define AV_CODEC_ID_AAC CODEC_ID_AAC
|
||||
# define AV_CODEC_ID_AC3 CODEC_ID_AC3
|
||||
# define AV_CODEC_ID_MP3 CODEC_ID_MP3
|
||||
# define AV_CODEC_ID_MP2 CODEC_ID_MP2
|
||||
# define AV_CODEC_ID_FLAC CODEC_ID_FLAC
|
||||
# define AV_CODEC_ID_PCM_U8 CODEC_ID_PCM_U8
|
||||
# define AV_CODEC_ID_PCM_S16LE CODEC_ID_PCM_S16LE
|
||||
# define AV_CODEC_ID_PCM_S24LE CODEC_ID_PCM_S24LE
|
||||
# define AV_CODEC_ID_PCM_S32LE CODEC_ID_PCM_S32LE
|
||||
# define AV_CODEC_ID_PCM_F32LE CODEC_ID_PCM_F32LE
|
||||
# define AV_CODEC_ID_PCM_F64LE CODEC_ID_PCM_F64LE
|
||||
# define AV_CODEC_ID_VORBIS CODEC_ID_VORBIS
|
||||
#endif
|
||||
|
||||
FFMPEG_INLINE
|
||||
int av_get_cropped_height_from_codec(AVCodecContext *pCodecCtx)
|
||||
{
|
||||
int y = pCodecCtx->height;
|
||||
|
||||
#ifndef FFMPEG_HAVE_CANON_H264_RESOLUTION_FIX
|
||||
/* really bad hack to remove this dreadfull black bar at the bottom
|
||||
with Canon footage and old ffmpeg versions.
|
||||
(to fix this properly in older ffmpeg versions one has to write a new
|
||||
demuxer...)
|
||||
|
||||
see the actual fix here for reference:
|
||||
|
||||
http://git.libav.org/?p=libav.git;a=commit;h=30f515091c323da59c0f1b533703dedca2f4b95d
|
||||
|
||||
We do our best to apply this only to matching footage.
|
||||
*/
|
||||
if (pCodecCtx->width == 1920 && pCodecCtx->height == 1088 &&
|
||||
pCodecCtx->pix_fmt == PIX_FMT_YUVJ420P && pCodecCtx->codec_id == AV_CODEC_ID_H264) {
|
||||
y = 1080;
|
||||
}
|
||||
#endif
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
#if ((LIBAVUTIL_VERSION_MAJOR < 51) || \
|
||||
(LIBAVUTIL_VERSION_MAJOR == 51) && (LIBAVUTIL_VERSION_MINOR < 22))
|
||||
FFMPEG_INLINE
|
||||
int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
|
||||
{
|
||||
const AVOption *rv = NULL;
|
||||
(void)search_flags;
|
||||
av_set_string3(obj, name, val, 1, &rv);
|
||||
return rv != NULL;
|
||||
}
|
||||
|
||||
FFMPEG_INLINE
|
||||
int av_opt_set_int(void *obj, const char *name, int64_t val, int search_flags)
|
||||
{
|
||||
const AVOption *rv = NULL;
|
||||
(void)search_flags;
|
||||
rv = av_set_int(obj, name, val);
|
||||
return rv != NULL;
|
||||
}
|
||||
|
||||
FFMPEG_INLINE
|
||||
int av_opt_set_double(void *obj, const char *name, double val, int search_flags)
|
||||
{
|
||||
const AVOption *rv = NULL;
|
||||
(void)search_flags;
|
||||
rv = av_set_double(obj, name, val);
|
||||
return rv != NULL;
|
||||
}
|
||||
|
||||
# define AV_OPT_TYPE_INT FF_OPT_TYPE_INT
|
||||
# define AV_OPT_TYPE_INT64 FF_OPT_TYPE_INT64
|
||||
# define AV_OPT_TYPE_STRING FF_OPT_TYPE_STRING
|
||||
# define AV_OPT_TYPE_CONST FF_OPT_TYPE_CONST
|
||||
# define AV_OPT_TYPE_DOUBLE FF_OPT_TYPE_DOUBLE
|
||||
# define AV_OPT_TYPE_FLOAT FF_OPT_TYPE_FLOAT
|
||||
#endif
|
||||
|
||||
#if ((LIBAVUTIL_VERSION_MAJOR < 51) || \
|
||||
(LIBAVUTIL_VERSION_MAJOR == 51) && (LIBAVUTIL_VERSION_MINOR < 54))
|
||||
FFMPEG_INLINE
|
||||
enum AVSampleFormat av_get_packed_sample_fmt(enum AVSampleFormat sample_fmt)
|
||||
{
|
||||
if (sample_fmt < 0 || sample_fmt >= AV_SAMPLE_FMT_NB)
|
||||
return AV_SAMPLE_FMT_NONE;
|
||||
return sample_fmt;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ((LIBAVCODEC_VERSION_MAJOR < 53) || \
|
||||
(LIBAVCODEC_VERSION_MAJOR == 53 && LIBAVCODEC_VERSION_MINOR < 35))
|
||||
FFMPEG_INLINE
|
||||
int avcodec_open2(AVCodecContext *avctx, AVCodec *codec, AVDictionary **options)
|
||||
{
|
||||
/* TODO: no options are taking into account */
|
||||
(void)options;
|
||||
return avcodec_open(avctx, codec);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ((LIBAVFORMAT_VERSION_MAJOR < 53) || \
|
||||
(LIBAVFORMAT_VERSION_MAJOR == 53 && LIBAVFORMAT_VERSION_MINOR < 21))
|
||||
FFMPEG_INLINE
|
||||
AVStream *avformat_new_stream(AVFormatContext *s, AVCodec *c)
|
||||
{
|
||||
/* TODO: no codec is taking into account */
|
||||
(void)c;
|
||||
return av_new_stream(s, 0);
|
||||
}
|
||||
|
||||
FFMPEG_INLINE
|
||||
int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
|
||||
{
|
||||
/* TODO: no options are taking into account */
|
||||
(void)options;
|
||||
return av_find_stream_info(ic);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ((LIBAVFORMAT_VERSION_MAJOR > 53) || \
|
||||
((LIBAVFORMAT_VERSION_MAJOR == 53) && (LIBAVFORMAT_VERSION_MINOR > 32)) || \
|
||||
((LIBAVFORMAT_VERSION_MAJOR == 53) && (LIBAVFORMAT_VERSION_MINOR == 24) && \
|
||||
(LIBAVFORMAT_VERSION_MICRO >= 100)))
|
||||
FFMPEG_INLINE
|
||||
void my_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp)
|
||||
{
|
||||
@@ -62,12 +323,103 @@ void av_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp)
|
||||
{
|
||||
my_update_cur_dts(s, ref_st, timestamp);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ((LIBAVCODEC_VERSION_MAJOR < 54) || \
|
||||
(LIBAVCODEC_VERSION_MAJOR == 54 && LIBAVCODEC_VERSION_MINOR < 28))
|
||||
FFMPEG_INLINE
|
||||
void avcodec_free_frame(AVFrame **frame)
|
||||
{
|
||||
/* don't need to do anything with old AVFrame
|
||||
* since it does not have malloced members */
|
||||
(void)frame;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ((LIBAVCODEC_VERSION_MAJOR > 54) || \
|
||||
(LIBAVCODEC_VERSION_MAJOR >= 54) && (LIBAVCODEC_VERSION_MINOR >= 13))
|
||||
# define FFMPEG_HAVE_AVFRAME_SAMPLE_RATE
|
||||
#endif
|
||||
|
||||
#if ((LIBAVCODEC_VERSION_MAJOR > 54) || \
|
||||
(LIBAVCODEC_VERSION_MAJOR == 54 && LIBAVCODEC_VERSION_MINOR >= 13))
|
||||
# define FFMPEG_HAVE_FRAME_CHANNEL_LAYOUT
|
||||
#endif
|
||||
|
||||
#ifndef FFMPEG_HAVE_AVIO
|
||||
# define AVIO_FLAG_WRITE URL_WRONLY
|
||||
# define avio_open url_fopen
|
||||
# define avio_tell url_ftell
|
||||
# define avio_close url_fclose
|
||||
# define avio_size url_fsize
|
||||
#endif
|
||||
|
||||
/* There are some version in between, which have avio_... functions but no
|
||||
* AVIO_FLAG_... */
|
||||
#ifndef AVIO_FLAG_WRITE
|
||||
# define AVIO_FLAG_WRITE URL_WRONLY
|
||||
#endif
|
||||
|
||||
#ifndef AV_PKT_FLAG_KEY
|
||||
# define AV_PKT_FLAG_KEY PKT_FLAG_KEY
|
||||
#endif
|
||||
|
||||
#ifndef FFMPEG_HAVE_AV_DUMP_FORMAT
|
||||
# define av_dump_format dump_format
|
||||
#endif
|
||||
|
||||
#ifndef FFMPEG_HAVE_AV_GUESS_FORMAT
|
||||
# define av_guess_format guess_format
|
||||
#endif
|
||||
|
||||
#ifndef FFMPEG_HAVE_PARSE_UTILS
|
||||
# define av_parse_video_rate av_parse_video_frame_rate
|
||||
#endif
|
||||
|
||||
#ifdef FFMPEG_HAVE_DEFAULT_VAL_UNION
|
||||
# define FFMPEG_DEF_OPT_VAL_INT(OPT) OPT->default_val.i64
|
||||
# define FFMPEG_DEF_OPT_VAL_DOUBLE(OPT) OPT->default_val.dbl
|
||||
#else
|
||||
# define FFMPEG_DEF_OPT_VAL_INT(OPT) OPT->default_val
|
||||
# define FFMPEG_DEF_OPT_VAL_DOUBLE(OPT) OPT->default_val
|
||||
#endif
|
||||
|
||||
#ifndef FFMPEG_HAVE_AVMEDIA_TYPES
|
||||
# define AVMEDIA_TYPE_VIDEO CODEC_TYPE_VIDEO
|
||||
# define AVMEDIA_TYPE_AUDIO CODEC_TYPE_AUDIO
|
||||
#endif
|
||||
|
||||
#ifndef FFMPEG_HAVE_DECODE_AUDIO3
|
||||
FFMPEG_INLINE
|
||||
int avcodec_decode_audio3(AVCodecContext *avctx,
|
||||
int16_t *samples,
|
||||
int *frame_size_ptr,
|
||||
AVPacket *avpkt)
|
||||
{
|
||||
return avcodec_decode_audio2(avctx, samples, frame_size_ptr, avpkt->data, avpkt->size);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef FFMPEG_HAVE_DECODE_VIDEO2
|
||||
FFMPEG_INLINE
|
||||
int avcodec_decode_video2(AVCodecContext *avctx,
|
||||
AVFrame *picture,
|
||||
int *got_picture_ptr,
|
||||
AVPacket *avpkt)
|
||||
{
|
||||
return avcodec_decode_video(avctx, picture, got_picture_ptr, avpkt->data, avpkt->size);
|
||||
}
|
||||
#endif
|
||||
|
||||
FFMPEG_INLINE
|
||||
int64_t av_get_pts_from_frame(AVFormatContext *avctx, AVFrame *picture)
|
||||
{
|
||||
int64_t pts;
|
||||
#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(55, 34, 100)
|
||||
pts = picture->pts;
|
||||
#else
|
||||
pts = picture->pkt_pts;
|
||||
#endif
|
||||
|
||||
if (pts == AV_NOPTS_VALUE) {
|
||||
pts = picture->pkt_dts;
|
||||
@@ -80,16 +432,124 @@ int64_t av_get_pts_from_frame(AVFormatContext *avctx, AVFrame *picture)
|
||||
return pts;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Deinterlace code block
|
||||
*
|
||||
* NOTE: The code in this block are from FFmpeg 2.6.4, which is licensed by LGPL.
|
||||
* \{ */
|
||||
/* obsolete constant formerly defined in FFMpeg libavcodec/avcodec.h */
|
||||
#ifndef AVCODEC_MAX_AUDIO_FRAME_SIZE
|
||||
# define AVCODEC_MAX_AUDIO_FRAME_SIZE 192000 // 1 second of 48khz 32bit audio
|
||||
#endif
|
||||
|
||||
#define MAX_NEG_CROP 1024
|
||||
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54, 1, 0)
|
||||
FFMPEG_INLINE
|
||||
int avcodec_encode_video2(AVCodecContext *avctx,
|
||||
AVPacket *pkt,
|
||||
const AVFrame *frame,
|
||||
int *got_output)
|
||||
{
|
||||
int outsize, ret;
|
||||
|
||||
#define times4(x) x, x, x, x
|
||||
#define times256(x) times4(times4(times4(times4(times4(x)))))
|
||||
ret = av_new_packet(pkt, avctx->width * avctx->height * 7 + 10000);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
outsize = avcodec_encode_video(avctx, pkt->data, pkt->size, frame);
|
||||
if (outsize <= 0) {
|
||||
*got_output = 0;
|
||||
av_free_packet(pkt);
|
||||
}
|
||||
else {
|
||||
*got_output = 1;
|
||||
av_shrink_packet(pkt, outsize);
|
||||
if (avctx->coded_frame) {
|
||||
pkt->pts = avctx->coded_frame->pts;
|
||||
if (avctx->coded_frame->key_frame)
|
||||
pkt->flags |= AV_PKT_FLAG_KEY;
|
||||
}
|
||||
}
|
||||
|
||||
return outsize >= 0 ? 0 : outsize;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(53, 17, 0)
|
||||
FFMPEG_INLINE
|
||||
void avformat_close_input(AVFormatContext **ctx)
|
||||
{
|
||||
av_close_input_file(*ctx);
|
||||
*ctx = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(52, 8, 0)
|
||||
FFMPEG_INLINE
|
||||
AVFrame *av_frame_alloc(void)
|
||||
{
|
||||
return avcodec_alloc_frame();
|
||||
}
|
||||
|
||||
FFMPEG_INLINE
|
||||
void av_frame_free(AVFrame **frame)
|
||||
{
|
||||
av_freep(frame);
|
||||
}
|
||||
#endif
|
||||
|
||||
FFMPEG_INLINE
|
||||
const char *av_get_metadata_key_value(AVDictionary *metadata, const char *key)
|
||||
{
|
||||
if (metadata == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
AVDictionaryEntry *tag = NULL;
|
||||
while ((tag = av_dict_get(metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) {
|
||||
if (!strcmp(tag->key, key)) {
|
||||
return tag->value;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FFMPEG_INLINE
|
||||
bool av_check_encoded_with_ffmpeg(AVFormatContext *ctx)
|
||||
{
|
||||
const char *encoder = av_get_metadata_key_value(ctx->metadata, "ENCODER");
|
||||
if (encoder != NULL && !strncmp(encoder, "Lavf", 4)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(51, 32, 0)
|
||||
# define AV_OPT_SEARCH_FAKE_OBJ 0
|
||||
#endif
|
||||
|
||||
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54, 59, 100)
|
||||
# define FFMPEG_HAVE_DEPRECATED_FLAGS2
|
||||
#endif
|
||||
|
||||
/* Since FFmpeg-1.1 this constant have AV_ prefix. */
|
||||
#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(52, 3, 100)
|
||||
# define AV_PIX_FMT_BGR32 PIX_FMT_BGR32
|
||||
# define AV_PIX_FMT_YUV422P PIX_FMT_YUV422P
|
||||
# define AV_PIX_FMT_BGRA PIX_FMT_BGRA
|
||||
# define AV_PIX_FMT_ARGB PIX_FMT_ARGB
|
||||
# define AV_PIX_FMT_RGBA PIX_FMT_RGBA
|
||||
#endif
|
||||
|
||||
/* New API from FFmpeg-2.0 which soon became recommended one. */
|
||||
#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(52, 38, 100)
|
||||
# define av_frame_alloc avcodec_alloc_frame
|
||||
# define av_frame_free avcodec_free_frame
|
||||
# define av_frame_unref avcodec_get_frame_defaults
|
||||
#endif
|
||||
|
||||
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 24, 102)
|
||||
|
||||
/* NOTE: The code in this block are from FFmpeg 2.6.4, which is licensed by LGPL. */
|
||||
|
||||
# define MAX_NEG_CROP 1024
|
||||
|
||||
# define times4(x) x, x, x, x
|
||||
# define times256(x) times4(times4(times4(times4(times4(x)))))
|
||||
|
||||
static const uint8_t ff_compat_crop_tab[256 + 2 * MAX_NEG_CROP] = {
|
||||
times256(0x00), 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,
|
||||
@@ -115,8 +575,8 @@ static const uint8_t ff_compat_crop_tab[256 + 2 * MAX_NEG_CROP] = {
|
||||
0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA,
|
||||
0xFB, 0xFC, 0xFD, 0xFE, 0xFF, times256(0xFF)};
|
||||
|
||||
#undef times4
|
||||
#undef times256
|
||||
# undef times4
|
||||
# undef times256
|
||||
|
||||
/* filter parameters: [-1 4 2 4 -1] // 8 */
|
||||
FFMPEG_INLINE
|
||||
@@ -208,9 +668,8 @@ int deinterlace_bottom_field_inplace(uint8_t *src1, int src_wrap, int width, int
|
||||
uint8_t *src_m1, *src_0, *src_p1, *src_p2;
|
||||
int y;
|
||||
uint8_t *buf = (uint8_t *)av_malloc(width);
|
||||
if (!buf) {
|
||||
if (!buf)
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
|
||||
src_m1 = src1;
|
||||
memcpy(buf, src_m1, width);
|
||||
@@ -230,21 +689,24 @@ int deinterlace_bottom_field_inplace(uint8_t *src1, int src_wrap, int width, int
|
||||
return 0;
|
||||
}
|
||||
|
||||
# ifdef __GNUC__
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
# endif
|
||||
|
||||
FFMPEG_INLINE
|
||||
int av_image_deinterlace(
|
||||
AVFrame *dst, const AVFrame *src, enum AVPixelFormat pix_fmt, int width, int height)
|
||||
int avpicture_deinterlace(
|
||||
AVPicture *dst, const AVPicture *src, enum AVPixelFormat pix_fmt, int width, int height)
|
||||
{
|
||||
int i, ret;
|
||||
|
||||
if (pix_fmt != AV_PIX_FMT_YUV420P && pix_fmt != AV_PIX_FMT_YUVJ420P &&
|
||||
pix_fmt != AV_PIX_FMT_YUV422P && pix_fmt != AV_PIX_FMT_YUVJ422P &&
|
||||
pix_fmt != AV_PIX_FMT_YUV444P && pix_fmt != AV_PIX_FMT_YUV411P &&
|
||||
pix_fmt != AV_PIX_FMT_GRAY8) {
|
||||
pix_fmt != AV_PIX_FMT_GRAY8)
|
||||
return -1;
|
||||
}
|
||||
if ((width & 3) != 0 || (height & 3) != 0) {
|
||||
if ((width & 3) != 0 || (height & 3) != 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (i == 1) {
|
||||
@@ -270,9 +732,8 @@ int av_image_deinterlace(
|
||||
}
|
||||
if (src == dst) {
|
||||
ret = deinterlace_bottom_field_inplace(dst->data[i], dst->linesize[i], width, height);
|
||||
if (ret < 0) {
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
else {
|
||||
deinterlace_bottom_field(
|
||||
@@ -282,6 +743,10 @@ int av_image_deinterlace(
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** \} Deinterlace code block */
|
||||
# ifdef __GNUC__
|
||||
# pragma GCC diagnostic pop
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@@ -79,7 +79,6 @@ set(SRC
|
||||
intern/GHOST_SystemPaths.h
|
||||
intern/GHOST_TimerManager.h
|
||||
intern/GHOST_TimerTask.h
|
||||
intern/GHOST_Util.h
|
||||
intern/GHOST_Window.h
|
||||
intern/GHOST_WindowManager.h
|
||||
)
|
||||
@@ -439,7 +438,6 @@ endif()
|
||||
if(WITH_XR_OPENXR)
|
||||
list(APPEND SRC
|
||||
intern/GHOST_Xr.cpp
|
||||
intern/GHOST_XrAction.cpp
|
||||
intern/GHOST_XrContext.cpp
|
||||
intern/GHOST_XrEvent.cpp
|
||||
intern/GHOST_XrGraphicsBinding.cpp
|
||||
@@ -448,7 +446,6 @@ if(WITH_XR_OPENXR)
|
||||
|
||||
GHOST_IXrContext.h
|
||||
intern/GHOST_IXrGraphicsBinding.h
|
||||
intern/GHOST_XrAction.h
|
||||
intern/GHOST_XrContext.h
|
||||
intern/GHOST_XrException.h
|
||||
intern/GHOST_XrSession.h
|
||||
|
@@ -276,7 +276,7 @@ extern int GHOST_GetFullScreen(GHOST_SystemHandle systemhandle);
|
||||
* wait (block) until the next event before returning.
|
||||
* \return Indication of the presence of events.
|
||||
*/
|
||||
extern bool GHOST_ProcessEvents(GHOST_SystemHandle systemhandle, bool waitForEvent);
|
||||
extern int GHOST_ProcessEvents(GHOST_SystemHandle systemhandle, int waitForEvent);
|
||||
|
||||
/**
|
||||
* Retrieves events from the queue and send them to the event consumers.
|
||||
@@ -1059,110 +1059,7 @@ int GHOST_XrSessionNeedsUpsideDownDrawing(const GHOST_XrContextHandle xr_context
|
||||
* \returns GHOST_kSuccess if any event was handled, otherwise GHOST_kFailure.
|
||||
*/
|
||||
GHOST_TSuccess GHOST_XrEventsHandle(GHOST_XrContextHandle xr_context);
|
||||
|
||||
/* actions */
|
||||
/**
|
||||
* Create an OpenXR action set for input/output.
|
||||
*/
|
||||
int GHOST_XrCreateActionSet(GHOST_XrContextHandle xr_context, const GHOST_XrActionSetInfo *info);
|
||||
|
||||
/**
|
||||
* Destroy a previously created OpenXR action set.
|
||||
*/
|
||||
void GHOST_XrDestroyActionSet(GHOST_XrContextHandle xr_context, const char *action_set_name);
|
||||
|
||||
/**
|
||||
* Create OpenXR input/output actions.
|
||||
*/
|
||||
int GHOST_XrCreateActions(GHOST_XrContextHandle xr_context,
|
||||
const char *action_set_name,
|
||||
GHOST_TUns32 count,
|
||||
const GHOST_XrActionInfo *infos);
|
||||
|
||||
/**
|
||||
* Destroy previously created OpenXR actions.
|
||||
*/
|
||||
void GHOST_XrDestroyActions(GHOST_XrContextHandle xr_context,
|
||||
const char *action_set_name,
|
||||
GHOST_TUns32 count,
|
||||
const char *const *action_names);
|
||||
|
||||
/**
|
||||
* Create spaces for pose-based OpenXR actions.
|
||||
*/
|
||||
int GHOST_XrCreateActionSpaces(GHOST_XrContextHandle xr_context,
|
||||
const char *action_set_name,
|
||||
GHOST_TUns32 count,
|
||||
const GHOST_XrActionSpaceInfo *infos);
|
||||
|
||||
/**
|
||||
* Destroy previously created spaces for OpenXR actions.
|
||||
*/
|
||||
void GHOST_XrDestroyActionSpaces(GHOST_XrContextHandle xr_context,
|
||||
const char *action_set_name,
|
||||
GHOST_TUns32 count,
|
||||
const GHOST_XrActionSpaceInfo *infos);
|
||||
|
||||
/**
|
||||
* Create input/output path bindings for OpenXR actions.
|
||||
*/
|
||||
int GHOST_XrCreateActionBindings(GHOST_XrContextHandle xr_context,
|
||||
const char *action_set_name,
|
||||
GHOST_TUns32 count,
|
||||
const GHOST_XrActionProfileInfo *infos);
|
||||
|
||||
/**
|
||||
* Destroy previously created bindings for OpenXR actions.
|
||||
*/
|
||||
void GHOST_XrDestroyActionBindings(GHOST_XrContextHandle xr_context,
|
||||
const char *action_set_name,
|
||||
GHOST_TUns32 count,
|
||||
const GHOST_XrActionProfileInfo *infos);
|
||||
|
||||
/**
|
||||
* Attach all created action sets to the current OpenXR session.
|
||||
*/
|
||||
int GHOST_XrAttachActionSets(GHOST_XrContextHandle xr_context);
|
||||
|
||||
/**
|
||||
* Update button/tracking states for OpenXR actions.
|
||||
*
|
||||
* \param action_set_name: The name of the action set to sync. If NULL, all action sets
|
||||
* attached to the session will be synced.
|
||||
*/
|
||||
int GHOST_XrSyncActions(GHOST_XrContextHandle xr_context, const char *action_set_name);
|
||||
|
||||
/**
|
||||
* Apply an OpenXR haptic output action.
|
||||
*/
|
||||
int GHOST_XrApplyHapticAction(GHOST_XrContextHandle xr_context,
|
||||
const char *action_set_name,
|
||||
const char *action_name,
|
||||
const GHOST_TInt64 *duration,
|
||||
const float *frequency,
|
||||
const float *amplitude);
|
||||
|
||||
/**
|
||||
* Stop a previously applied OpenXR haptic output action.
|
||||
*/
|
||||
void GHOST_XrStopHapticAction(GHOST_XrContextHandle xr_context,
|
||||
const char *action_set_name,
|
||||
const char *action_name);
|
||||
|
||||
/**
|
||||
* Get action set custom data (owned by Blender, not GHOST).
|
||||
*/
|
||||
void *GHOST_XrGetActionSetCustomdata(GHOST_XrContextHandle xr_context,
|
||||
const char *action_set_name);
|
||||
|
||||
/**
|
||||
* Get action custom data (owned by Blender, not GHOST).
|
||||
*/
|
||||
void *GHOST_XrGetActionCustomdata(GHOST_XrContextHandle xr_context,
|
||||
const char *action_set_name,
|
||||
const char *action_name);
|
||||
|
||||
#endif /* WITH_XR_OPENXR */
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@@ -22,8 +22,6 @@
|
||||
|
||||
#include "GHOST_Types.h"
|
||||
|
||||
class GHOST_XrSession;
|
||||
|
||||
class GHOST_IXrContext {
|
||||
public:
|
||||
virtual ~GHOST_IXrContext() = default;
|
||||
@@ -33,10 +31,6 @@ class GHOST_IXrContext {
|
||||
virtual bool isSessionRunning() const = 0;
|
||||
virtual void drawSessionViews(void *draw_customdata) = 0;
|
||||
|
||||
/* Needed for the GHOST C api. */
|
||||
virtual GHOST_XrSession *getSession() = 0;
|
||||
virtual const GHOST_XrSession *getSession() const = 0;
|
||||
|
||||
virtual void dispatchErrorMessage(const class GHOST_XrException *) const = 0;
|
||||
|
||||
virtual void setGraphicsContextBindFuncs(GHOST_XrGraphicsContextBindFn bind_fn,
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user