Mesh: Replace MLoop struct with generic attributes #104424

Merged
Hans Goudey merged 261 commits from refactor-mesh-corners-generic into main 2023-03-20 15:55:25 +01:00
319 changed files with 8078 additions and 1828 deletions
Showing only changes of commit c8a49937d0 - Show all commits

12
.gitmodules vendored
View File

@ -1,20 +1,16 @@
[submodule "release/scripts/addons"]
path = release/scripts/addons
url = ../blender-addons.git
branch = master
ignore = all
branch = main
[submodule "release/scripts/addons_contrib"]
path = release/scripts/addons_contrib
url = ../blender-addons-contrib.git
branch = master
ignore = all
branch = main
[submodule "release/datafiles/locale"]
path = release/datafiles/locale
url = ../blender-translations.git
branch = master
ignore = all
branch = main
[submodule "source/tools"]
path = source/tools
url = ../blender-dev-tools.git
branch = master
ignore = all
branch = main

View File

@ -40,7 +40,8 @@ ExternalProject_Add(external_igc_llvm
${PATCH_CMD} -p 1 -d ${IGC_LLVM_SOURCE_DIR} < ${IGC_OPENCL_CLANG_PATCH_DIR}/clang/0004-OpenCL-support-cl_ext_float_atomics.patch &&
${PATCH_CMD} -p 1 -d ${IGC_LLVM_SOURCE_DIR} < ${IGC_OPENCL_CLANG_PATCH_DIR}/clang/0005-OpenCL-Add-cl_khr_integer_dot_product.patch &&
${PATCH_CMD} -p 1 -d ${IGC_LLVM_SOURCE_DIR} < ${IGC_OPENCL_CLANG_PATCH_DIR}/llvm/0001-Memory-leak-fix-for-Managed-Static-Mutex.patch &&
${PATCH_CMD} -p 1 -d ${IGC_LLVM_SOURCE_DIR} < ${IGC_OPENCL_CLANG_PATCH_DIR}/llvm/0002-Remove-repo-name-in-LLVM-IR.patch
${PATCH_CMD} -p 1 -d ${IGC_LLVM_SOURCE_DIR} < ${IGC_OPENCL_CLANG_PATCH_DIR}/llvm/0002-Remove-repo-name-in-LLVM-IR.patch &&
${PATCH_CMD} -p 1 -d ${IGC_LLVM_SOURCE_DIR} < ${IGC_OPENCL_CLANG_PATCH_DIR}/llvm/0003-Add-missing-include-limit-in-benchmark.patch
)
add_dependencies(
external_igc_llvm
@ -55,9 +56,6 @@ ExternalProject_Add(external_igc_spirv_translator
CONFIGURE_COMMAND echo .
BUILD_COMMAND echo .
INSTALL_COMMAND echo .
PATCH_COMMAND ${PATCH_CMD} -p 1 -d ${IGC_SPIRV_TRANSLATOR_SOURCE_DIR} < ${IGC_OPENCL_CLANG_PATCH_DIR}/spirv/0001-update-SPIR-V-headers-for-SPV_INTEL_split_barrier.patch &&
${PATCH_CMD} -p 1 -d ${IGC_SPIRV_TRANSLATOR_SOURCE_DIR} < ${IGC_OPENCL_CLANG_PATCH_DIR}/spirv/0002-Add-support-for-split-barriers-extension-SPV_INTEL_s.patch &&
${PATCH_CMD} -p 1 -d ${IGC_SPIRV_TRANSLATOR_SOURCE_DIR} < ${IGC_OPENCL_CLANG_PATCH_DIR}/spirv/0003-Support-cl_bf16_conversions.patch
)
add_dependencies(
external_igc_spirv_translator

View File

@ -88,6 +88,19 @@ else()
export LDFLAGS=${PYTHON_LDFLAGS} &&
export PKG_CONFIG_PATH=${LIBDIR}/ffi/lib/pkgconfig)
# NOTE: untested on APPLE so far.
if(NOT APPLE)
set(PYTHON_CONFIGURE_EXTRA_ARGS
${PYTHON_CONFIGURE_EXTRA_ARGS}
# Used on most release Linux builds (Fedora for e.g.),
# increases build times noticeably with the benefit of a modest speedup at runtime.
--enable-optimizations
# While LTO is OK when building on the same system, it's incompatible across GCC versions,
# making it impractical for developers to build against, so keep it disabled.
# `--with-lto`
)
endif()
ExternalProject_Add(external_python
URL file://${PACKAGE_DIR}/${PYTHON_FILE}
DOWNLOAD_DIR ${DOWNLOAD_DIR}

View File

@ -668,9 +668,9 @@ set(SPIRV_HEADERS_FILE SPIR-V-Headers-${SPIRV_HEADERS_VERSION}.tar.gz)
# compiler, the versions used are taken from the following location
# https://github.com/intel/intel-graphics-compiler/releases
set(IGC_VERSION 1.0.12149.1)
set(IGC_VERSION 1.0.13064.7)
set(IGC_URI https://github.com/intel/intel-graphics-compiler/archive/refs/tags/igc-${IGC_VERSION}.tar.gz)
set(IGC_HASH 44f67f24e3bc5130f9f062533abf8154782a9d0a992bc19b498639a8521ae836)
set(IGC_HASH a929abd4cca2b293961ec0437ee4b3b2147bd3b2c8a3c423af78c0c359b2e5ae)
set(IGC_HASH_TYPE SHA256)
set(IGC_FILE igc-${IGC_VERSION}.tar.gz)
@ -690,15 +690,15 @@ set(IGC_LLVM_FILE ${IGC_LLVM_VERSION}.tar.gz)
#
# WARNING WARNING WARNING
set(IGC_OPENCL_CLANG_VERSION 363a5262d8c7cff3fb28f3bdb5d85c8d7e91c1bb)
set(IGC_OPENCL_CLANG_VERSION ee31812ea8b89d08c2918f045d11a19bd33525c5)
set(IGC_OPENCL_CLANG_URI https://github.com/intel/opencl-clang/archive/${IGC_OPENCL_CLANG_VERSION}.tar.gz)
set(IGC_OPENCL_CLANG_HASH aa8cf72bb239722ce8ce44f79413c6887ecc8ca18477dd520aa5c4809756da9a)
set(IGC_OPENCL_CLANG_HASH 1db6735bbcfaa31e8a9ba39f121d6bafa806ea8919e9f56782d6aaa67771ddda)
set(IGC_OPENCL_CLANG_HASH_TYPE SHA256)
set(IGC_OPENCL_CLANG_FILE opencl-clang-${IGC_OPENCL_CLANG_VERSION}.tar.gz)
set(IGC_VCINTRINSICS_VERSION v0.5.0)
set(IGC_VCINTRINSICS_VERSION v0.11.0)
set(IGC_VCINTRINSICS_URI https://github.com/intel/vc-intrinsics/archive/refs/tags/${IGC_VCINTRINSICS_VERSION}.tar.gz)
set(IGC_VCINTRINSICS_HASH 70bb47c5e32173cf61514941e83ae7c7eb4485e6d2fca60cfa1f50d4f42c41f2)
set(IGC_VCINTRINSICS_HASH e5acd5626ce7fa6d41ce154c50ac805eda734ee66af94ef28e680ac2ad81bb9f)
set(IGC_VCINTRINSICS_HASH_TYPE SHA256)
set(IGC_VCINTRINSICS_FILE vc-intrinsics-${IGC_VCINTRINSICS_VERSION}.tar.gz)
@ -714,9 +714,9 @@ set(IGC_SPIRV_TOOLS_HASH 6e19900e948944243024aedd0a201baf3854b377b9cc7a386553bc1
set(IGC_SPIRV_TOOLS_HASH_TYPE SHA256)
set(IGC_SPIRV_TOOLS_FILE SPIR-V-Tools-${IGC_SPIRV_TOOLS_VERSION}.tar.gz)
set(IGC_SPIRV_TRANSLATOR_VERSION a31ffaeef77e23d500b3ea3d35e0c42ff5648ad9)
set(IGC_SPIRV_TRANSLATOR_VERSION d739c01d65ec00dee64dedd40deed805216a7193)
set(IGC_SPIRV_TRANSLATOR_URI https://github.com/KhronosGroup/SPIRV-LLVM-Translator/archive/${IGC_SPIRV_TRANSLATOR_VERSION}.tar.gz)
set(IGC_SPIRV_TRANSLATOR_HASH 9e26c96a45341b8f8af521bacea20e752623346340addd02af95d669f6e89252)
set(IGC_SPIRV_TRANSLATOR_HASH ddc0cc9ccbe59dadeaf291012d59de142b2e9f2b124dbb634644d39daddaa13e)
set(IGC_SPIRV_TRANSLATOR_HASH_TYPE SHA256)
set(IGC_SPIRV_TRANSLATOR_FILE SPIR-V-Translator-${IGC_SPIRV_TRANSLATOR_VERSION}.tar.gz)
@ -724,15 +724,15 @@ set(IGC_SPIRV_TRANSLATOR_FILE SPIR-V-Translator-${IGC_SPIRV_TRANSLATOR_VERSION}.
### Intel Graphics Compiler DEPS END ###
########################################
set(GMMLIB_VERSION intel-gmmlib-22.1.8)
set(GMMLIB_VERSION intel-gmmlib-22.3.0)
set(GMMLIB_URI https://github.com/intel/gmmlib/archive/refs/tags/${GMMLIB_VERSION}.tar.gz)
set(GMMLIB_HASH bf23e9a3742b4fb98c7666c9e9b29f3219e4b2fb4d831aaf4eed71f5e2d17368)
set(GMMLIB_HASH c1f33e1519edfc527127baeb0436b783430dfd256c643130169a3a71dc86aff9)
set(GMMLIB_HASH_TYPE SHA256)
set(GMMLIB_FILE ${GMMLIB_VERSION}.tar.gz)
set(OCLOC_VERSION 22.38.24278)
set(OCLOC_VERSION 22.49.25018.21)
set(OCLOC_URI https://github.com/intel/compute-runtime/archive/refs/tags/${OCLOC_VERSION}.tar.gz)
set(OCLOC_HASH db0c542fccd651e6404b15a74d46027f1ce0eda8dc9e25a40cbb6c0faef257ee)
set(OCLOC_HASH 92362dae08b503a34e5d3820ed284198c452bcd5e7504d90eb69887b20492c06)
set(OCLOC_HASH_TYPE SHA256)
set(OCLOC_FILE ocloc-${OCLOC_VERSION}.tar.gz)

View File

@ -1,7 +1,7 @@
diff -Naur external_igc_opencl_clang.orig/CMakeLists.txt external_igc_opencl_clang/CMakeLists.txt
--- external_igc_opencl_clang.orig/CMakeLists.txt 2022-03-16 05:51:10 -0600
+++ external_igc_opencl_clang/CMakeLists.txt 2022-05-23 10:40:09 -0600
@@ -126,22 +126,24 @@
@@ -147,22 +147,24 @@
)
endif()

View File

@ -170,7 +170,7 @@ def git_update_skip(args: argparse.Namespace, check_remote_exists: bool = True)
return "rebase or merge in progress, complete it first"
# Abort if uncommitted changes.
changes = check_output([args.git_command, 'status', '--porcelain', '--untracked-files=no'])
changes = check_output([args.git_command, 'status', '--porcelain', '--untracked-files=no', '--ignore-submodules'])
if len(changes) != 0:
return "you have unstaged changes"

View File

@ -12,6 +12,7 @@ from bpy.props import (
PointerProperty,
StringProperty,
)
from bpy.app.translations import pgettext_iface as iface_
from math import pi
@ -1664,30 +1665,48 @@ class CyclesPreferences(bpy.types.AddonPreferences):
col.label(text="No compatible GPUs found for Cycles", icon='INFO')
if device_type == 'CUDA':
col.label(text="Requires NVIDIA GPU with compute capability 3.0", icon='BLANK1')
compute_capability = "3.0"
col.label(text=iface_("Requires NVIDIA GPU with compute capability %s") % compute_capability,
icon='BLANK1', translate=False)
elif device_type == 'OPTIX':
col.label(text="Requires NVIDIA GPU with compute capability 5.0", icon='BLANK1')
col.label(text="and NVIDIA driver version 470 or newer", icon='BLANK1')
compute_capability = "5.0"
driver_version = "470"
col.label(text=iface_("Requires NVIDIA GPU with compute capability %s") % compute_capability,
icon='BLANK1', translate=False)
col.label(text="and NVIDIA driver version %s or newer" % driver_version,
icon='BLANK1', translate=False)
elif device_type == 'HIP':
import sys
if sys.platform[:3] == "win":
driver_version = "21.Q4"
col.label(text="Requires AMD GPU with RDNA architecture", icon='BLANK1')
col.label(text="and AMD Radeon Pro 21.Q4 driver or newer", icon='BLANK1')
col.label(text=iface_("and AMD Radeon Pro %s driver or newer") % driver_version,
icon='BLANK1', translate=False)
elif sys.platform.startswith("linux"):
driver_version = "22.10"
col.label(text="Requires AMD GPU with RDNA architecture", icon='BLANK1')
col.label(text="and AMD driver version 22.10 or newer", icon='BLANK1')
col.label(text=iface_("and AMD driver version %s or newer") % driver_version, icon='BLANK1',
translate=False)
elif device_type == 'ONEAPI':
import sys
if sys.platform.startswith("win"):
driver_version = "101.4032"
col.label(text="Requires Intel GPU with Xe-HPG architecture", icon='BLANK1')
col.label(text="and Windows driver version 101.4032 or newer", icon='BLANK1')
col.label(text=iface_("and Windows driver version %s or newer") % driver_version,
icon='BLANK1', translate=False)
elif sys.platform.startswith("linux"):
driver_version = "1.3.24931"
col.label(text="Requires Intel GPU with Xe-HPG architecture and", icon='BLANK1')
col.label(text=" - intel-level-zero-gpu version 1.3.24931 or newer", icon='BLANK1')
col.label(text=iface_(" - intel-level-zero-gpu version %s or newer") % driver_version,
icon='BLANK1', translate=False)
col.label(text=" - oneAPI Level-Zero Loader", icon='BLANK1')
elif device_type == 'METAL':
col.label(text="Requires Apple Silicon with macOS 12.2 or newer", icon='BLANK1')
col.label(text="or AMD with macOS 12.3 or newer", icon='BLANK1')
silicon_mac_version = "12.2"
amd_mac_version = "12.3"
col.label(text=iface_("Requires Apple Silicon with macOS %s or newer") % silicon_mac_version,
icon='BLANK1', translate=False)
col.label(text=iface_("or AMD with macOS %s or newer") % amd_mac_version, icon='BLANK1',
translate=False)
return
for device in devices:

View File

@ -648,7 +648,7 @@ GPUDevice::Mem *GPUDevice::generic_alloc(device_memory &mem, size_t pitch_paddin
}
if (mem_alloc_result) {
assert(transform_host_pointer(&device_pointer, shared_pointer));
assert(transform_host_pointer(device_pointer, shared_pointer));
map_host_used += size;
status = " in host memory";
}

View File

@ -13,6 +13,7 @@
#include "scene/light.h"
#include "scene/mesh.h"
#include "scene/object.h"
#include "scene/osl.h"
#include "scene/pointcloud.h"
#include "scene/scene.h"
#include "scene/shader.h"
@ -25,7 +26,6 @@
#ifdef WITH_OSL
# include "kernel/osl/globals.h"
# include "kernel/osl/services.h"
#endif
#include "util/foreach.h"
@ -1717,20 +1717,7 @@ void GeometryManager::device_update_displacement_images(Device *device,
/* If any OSL node is used for displacement, it may reference a texture. But it's
* unknown which ones, so have to load them all. */
if (has_osl_node) {
set<OSLRenderServices *> services_shared;
device->foreach_device([&services_shared](Device *sub_device) {
OSLGlobals *og = (OSLGlobals *)sub_device->get_cpu_osl_memory();
services_shared.insert(og->services);
});
for (OSLRenderServices *services : services_shared) {
for (auto it = services->textures.begin(); it != services->textures.end(); ++it) {
if (it->second->handle.get_manager() == image_manager) {
const int slot = it->second->handle.svm_slot();
bump_images.insert(slot);
}
}
}
OSLShaderManager::osl_image_slots(device, image_manager, bump_images);
}
#endif

View File

@ -665,6 +665,27 @@ OSLNode *OSLShaderManager::osl_node(ShaderGraph *graph,
return node;
}
/* Static function, so only this file needs to be compile with RTTT. */
void OSLShaderManager::osl_image_slots(Device *device,
ImageManager *image_manager,
set<int> &image_slots)
{
set<OSLRenderServices *> services_shared;
device->foreach_device([&services_shared](Device *sub_device) {
OSLGlobals *og = (OSLGlobals *)sub_device->get_cpu_osl_memory();
services_shared.insert(og->services);
});
for (OSLRenderServices *services : services_shared) {
for (auto it = services->textures.begin(); it != services->textures.end(); ++it) {
if (it->second->handle.get_manager() == image_manager) {
const int slot = it->second->handle.svm_slot();
image_slots.insert(slot);
}
}
}
}
/* Graph Compiler */
OSLCompiler::OSLCompiler(OSLShaderManager *manager, OSL::ShadingSystem *ss, Scene *scene)

View File

@ -92,6 +92,9 @@ class OSLShaderManager : public ShaderManager {
const std::string &bytecode_hash = "",
const std::string &bytecode = "");
/* Get image slots used by OSL services on device. */
static void osl_image_slots(Device *device, ImageManager *image_manager, set<int> &image_slots);
private:
void texture_system_init();
void texture_system_free();

View File

@ -602,7 +602,7 @@ void GHOST_SystemSDL::processEvent(SDL_Event *sdl_event)
/* NOTE: the `sdl_sub_evt.keysym.sym` is truncated,
* for unicode support ghost has to be modified. */
/* TODO(@campbellbarton): support full unicode, SDL supports this but it needs to be
/* TODO(@ideasman42): support full unicode, SDL supports this but it needs to be
* explicitly enabled via #SDL_StartTextInput which GHOST would have to wrap. */
char utf8_buf[sizeof(GHOST_TEventKeyData::utf8_buf)] = {'\0'};
if (type == GHOST_kEventKeyDown) {

View File

@ -241,7 +241,7 @@ enum {
BTN_STYLUS = 0x14b,
/** Use as right-mouse. */
BTN_STYLUS2 = 0x14c,
/** NOTE(@campbellbarton): Map to an additional button (not sure which hardware uses this). */
/** NOTE(@ideasman42): Map to an additional button (not sure which hardware uses this). */
BTN_STYLUS3 = 0x149,
};
@ -916,7 +916,7 @@ struct GWL_Display {
* The main purpose of having an active seat is an alternative from always using the first
* seat which prevents events from any other seat.
*
* NOTE(@campbellbarton): This could be extended and developed further extended to support
* NOTE(@ideasman42): This could be extended and developed further extended to support
* an active seat per window (for e.g.), basic support is sufficient for now as currently isn't
* a widely used feature.
*/
@ -957,7 +957,7 @@ struct GWL_Display {
* Needed because #GHOST_System::dispatchEvents fires timers
* outside of WAYLAND (without locking the `timer_mutex`).
*/
GHOST_TimerManager *ghost_timer_manager;
GHOST_TimerManager *ghost_timer_manager = nullptr;
#endif /* USE_EVENT_BACKGROUND_THREAD */
};
@ -1014,8 +1014,10 @@ static void gwl_display_destroy(GWL_Display *display)
}
/* Important to remove after the seats which may have key repeat timers active. */
delete display->ghost_timer_manager;
display->ghost_timer_manager = nullptr;
if (display->ghost_timer_manager) {
delete display->ghost_timer_manager;
display->ghost_timer_manager = nullptr;
}
#endif /* USE_EVENT_BACKGROUND_THREAD */
@ -1237,7 +1239,7 @@ static void gwl_registry_entry_remove_all(GWL_Display *display)
{
const bool on_exit = true;
/* NOTE(@campbellbarton): Free by slot instead of simply looping over
/* NOTE(@ideasman42): Free by slot instead of simply looping over
* `display->registry_entry` so the order of freeing is always predictable.
* Otherwise global objects would be feed in the order they are registered.
* While this works in my tests, it could cause difficult to reproduce bugs
@ -1267,7 +1269,7 @@ static void gwl_registry_entry_remove_all(GWL_Display *display)
* so there is no reason to update all other outputs that an output was removed (for e.g.).
* Pass as -1 to update all slots.
*
* NOTE(@campbellbarton): Updating all other items on a single change is typically worth avoiding.
* NOTE(@ideasman42): Updating all other items on a single change is typically worth avoiding.
* In practice this isn't a problem as so there are so few elements in `display->registry_entry`,
* so few use update functions and adding/removal at runtime is rarely called (plugging/unplugging)
* hardware for e.g. So while it's possible to store dependency links to avoid unnecessary
@ -1316,7 +1318,7 @@ static void ghost_wl_display_report_error(struct wl_display *display)
fprintf(stderr, "The Wayland connection experienced a fatal error: %s\n", strerror(ecode));
}
/* NOTE(@campbellbarton): The application is running,
/* NOTE(@ideasman42): The application is running,
* however an error closes all windows and most importantly:
* shuts down the GPU context (loosing all GPU state - shaders, bind codes etc),
* so recovering from this effectively involves restarting.
@ -2968,7 +2970,7 @@ static void gesture_pinch_handle_begin(void *data,
if (wl_surface *wl_surface_focus = seat->pointer.wl_surface_window) {
win = ghost_wl_surface_user_data(wl_surface_focus);
}
/* NOTE(@campbellbarton): Blender's use of track-pad coordinates is inconsistent and needs work.
/* NOTE(@ideasman42): Blender's use of track-pad coordinates is inconsistent and needs work.
* This isn't specific to WAYLAND, in practice they tend to work well enough in most cases.
* Some operators scale by the UI scale, some don't.
* Even this window scale is not correct because it doesn't account for:
@ -2982,7 +2984,7 @@ static void gesture_pinch_handle_begin(void *data,
*/
const wl_fixed_t win_scale = win ? win->scale() : 1;
/* NOTE(@campbellbarton): Scale factors match Blender's operators & default preferences.
/* NOTE(@ideasman42): Scale factors match Blender's operators & default preferences.
* For these values to work correctly, operator logic will need to be changed not to scale input
* by the region size (as with 3D view zoom) or preference for 3D view orbit sensitivity.
*
@ -3145,7 +3147,7 @@ static const struct zwp_pointer_gesture_swipe_v1_listener gesture_swipe_listener
/* -------------------------------------------------------------------- */
/** \name Listener (Touch Seat), #wl_touch_listener
*
* NOTE(@campbellbarton): It's not clear if this interface is used by popular compositors.
* NOTE(@ideasman42): It's not clear if this interface is used by popular compositors.
* It looks like GNOME/KDE only support `zwp_pointer_gestures_v1_interface`.
* If this isn't used anywhere, it could be removed.
* \{ */
@ -3806,7 +3808,7 @@ static xkb_keysym_t xkb_state_key_get_one_sym_without_modifiers(
/* Use an empty keyboard state to access key symbol without modifiers. */
xkb_keysym_t sym = xkb_state_key_get_one_sym(xkb_state_empty, key);
/* NOTE(@campbellbarton): Only perform the number-locked lookup as a fallback
/* NOTE(@ideasman42): Only perform the number-locked lookup as a fallback
* when a number-pad key has been pressed. This is important as some key-maps use number lock
* for switching other layers (in particular `de(neo_qwertz)` turns on layer-4), see: T96170.
* Alternative solutions could be to inspect the layout however this could get involved
@ -3936,7 +3938,7 @@ static void keyboard_handle_key(void *data,
else {
/* Key-up from keys that were not repeating cause the repeat timer to pause.
*
* NOTE(@campbellbarton): This behavior isn't universal, some text input systems will
* NOTE(@ideasman42): This behavior isn't universal, some text input systems will
* stop the repeat entirely. Choose to pause repeat instead as this is what GTK/WIN32 do,
* and it fits better for keyboard input that isn't related to text entry. */
timer_action = RESET;
@ -7035,7 +7037,7 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod
UNPACK2(xy_next));
wl_surface_commit(wl_surface);
/* NOTE(@campbellbarton): The new cursor position is a hint,
/* NOTE(@ideasman42): The new cursor position is a hint,
* it's possible the hint is ignored. It doesn't seem like there is a good way to
* know if the hint will be used or not, at least not immediately. */
xy_motion[0] = xy_next[0];
@ -7078,7 +7080,7 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod
if (mode != GHOST_kGrabDisable) {
if (grab_state_next.use_lock) {
if (!grab_state_prev.use_lock) {
/* TODO(@campbellbarton): As WAYLAND does not support warping the pointer it may not be
/* TODO(@ideasman42): As WAYLAND does not support warping the pointer it may not be
* possible to support #GHOST_kGrabWrap by pragmatically settings it's coordinates.
* An alternative could be to draw the cursor in software (and hide the real cursor),
* or just accept a locked cursor on WAYLAND. */

View File

@ -1080,7 +1080,7 @@ GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *wind
if (window->getCursorGrabMode() == GHOST_kGrabHide) {
window->getClientBounds(bounds);
/* WARNING(@campbellbarton): The current warping logic fails to warp on every event,
/* WARNING(@ideasman42): The current warping logic fails to warp on every event,
* so the box needs to small enough not to let the cursor escape the window but large
* enough that the cursor isn't being warped every time.
* If this was not the case it would be less trouble to simply warp the cursor to the
@ -1179,7 +1179,7 @@ GHOST_EventKey *GHOST_SystemWin32::processKeyEvent(GHOST_WindowWin32 *window, RA
GHOST_TKey key = system->hardKey(raw, &key_down);
GHOST_EventKey *event;
/* NOTE(@campbellbarton): key repeat in WIN32 also applies to modifier-keys.
/* NOTE(@ideasman42): key repeat in WIN32 also applies to modifier-keys.
* Check for this case and filter out modifier-repeat.
* Typically keyboard events are *not* filtered as part of GHOST's event handling.
* As other GHOST back-ends don't have the behavior, it's simplest not to send them through.

View File

@ -278,7 +278,7 @@ uint8_t GHOST_SystemX11::getNumDisplays() const
void GHOST_SystemX11::getMainDisplayDimensions(uint32_t &width, uint32_t &height) const
{
if (m_display) {
/* NOTE(@campbellbarton): for this to work as documented,
/* NOTE(@ideasman42): for this to work as documented,
* we would need to use Xinerama check r54370 for code that did this,
* we've since removed since its not worth the extra dependency. */
getAllDisplayDimensions(width, height);
@ -927,7 +927,7 @@ void GHOST_SystemX11::processEvent(XEvent *xe)
if (window->getCursorGrabMode() == GHOST_kGrabHide) {
window->getClientBounds(bounds);
/* TODO(@campbellbarton): warp the cursor to `window->getCursorGrabInitPos`,
/* TODO(@ideasman42): warp the cursor to `window->getCursorGrabInitPos`,
* on every motion event, see: D16557 (alternative fix for T102346). */
const int32_t subregion_div = 4; /* One quarter of the region. */
const int32_t size[2] = {bounds.getWidth(), bounds.getHeight()};

View File

@ -669,7 +669,7 @@ static void xdg_surface_handle_configure(void *data,
GHOST_SystemWayland *system = win->ghost_system;
const bool is_main_thread = system->main_thread_id == std::this_thread::get_id();
if (!is_main_thread) {
/* NOTE(@campbellbarton): this only gets one redraw,
/* NOTE(@ideasman42): this only gets one redraw,
* I could not find a case where this causes problems. */
gwl_window_pending_actions_tag(win, PENDING_FRAME_CONFIGURE);
}
@ -774,7 +774,7 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
window_->ghost_window = this;
window_->ghost_system = system;
/* NOTE(@campbellbarton): The scale set here to avoid flickering on startup.
/* NOTE(@ideasman42): The scale set here to avoid flickering on startup.
* When all monitors use the same scale (which is quite common) there aren't any problems.
*
* When monitors have different scales there may still be a visible window resize on startup.
@ -1078,7 +1078,7 @@ GHOST_WindowWayland::~GHOST_WindowWayland()
wl_surface_destroy(window_->wl_surface);
/* NOTE(@campbellbarton): Flushing will often run the appropriate handlers event
/* NOTE(@ideasman42): Flushing will often run the appropriate handlers event
* (#wl_surface_listener.leave in particular) to avoid attempted access to the freed surfaces.
* This is not fool-proof though, hence the call to #window_surface_unref, see: T99078. */
wl_display_flush(system_->wl_display());

View File

@ -3,6 +3,7 @@
import requests
class ReleaseLogLine:
"""
Class containing the information of a single line of the release log

View File

@ -1002,11 +1002,11 @@ def unregister_tool(tool_cls):
# we start with the built-in default mapping
def _blender_default_map():
import rna_manual_reference as ref_mod
ret = (ref_mod.url_manual_prefix, ref_mod.url_manual_mapping)
# avoid storing in memory
del _sys.modules["rna_manual_reference"]
return ret
# NOTE(@ideasman42): Avoid importing this as there is no need to keep the lookup table in memory.
# As this runs when the user accesses the "Online Manual", the overhead loading the file is acceptable.
# In my tests it's under 1/100th of a second loading from a `pyc`.
ref_mod = execfile(_os.path.join(_script_base_dir, "modules", "rna_manual_reference.py"))
return (ref_mod.url_manual_prefix, ref_mod.url_manual_mapping)
# hooks for doc lookups

View File

@ -6344,6 +6344,8 @@ def km_node_link_modal_map(_params):
return keymap
# Fallback for gizmos that don't have custom a custom key-map.
def km_generic_gizmo(_params):
keymap = (
"Generic Gizmo",

View File

@ -338,6 +338,7 @@ class NODE_MT_geometry_node_GEO_MESH_READ(Menu):
node_add_menu.add_node_type(layout, "GeometryNodeInputMeshEdgeAngle")
node_add_menu.add_node_type(layout, "GeometryNodeInputMeshEdgeNeighbors")
node_add_menu.add_node_type(layout, "GeometryNodeInputMeshEdgeVertices")
node_add_menu.add_node_type(layout, "GeometryNodeEdgesToFaceGroups")
node_add_menu.add_node_type(layout, "GeometryNodeInputMeshFaceArea")
node_add_menu.add_node_type(layout, "GeometryNodeInputMeshFaceNeighbors")
node_add_menu.add_node_type(layout, "GeometryNodeMeshFaceSetBoundaries")

View File

@ -140,7 +140,7 @@ class DATA_PT_EEVEE_light_distance(DataButtonsPanel, Panel):
class DATA_PT_EEVEE_shadow(DataButtonsPanel, Panel):
bl_label = "Shadow"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_EEVEE'}
COMPAT_ENGINES = {'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT'}
@classmethod
def poll(cls, context):
@ -168,7 +168,8 @@ class DATA_PT_EEVEE_shadow(DataButtonsPanel, Panel):
if light.type != 'SUN':
sub.prop(light, "shadow_buffer_clip_start", text="Clip Start")
col.prop(light, "shadow_buffer_bias", text="Bias")
if context.engine != 'BLENDER_EEVEE_NEXT':
col.prop(light, "shadow_buffer_bias", text="Bias")
class DATA_PT_EEVEE_shadow_cascaded_shadow_map(DataButtonsPanel, Panel):

View File

@ -460,6 +460,32 @@ class RENDER_PT_eevee_shadows(RenderButtonsPanel, Panel):
col.prop(props, "light_threshold")
class RENDER_PT_eevee_next_shadows(RenderButtonsPanel, Panel):
bl_label = "Shadows"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_EEVEE_NEXT'}
@classmethod
def poll(cls, context):
return (context.engine in cls.COMPAT_ENGINES)
def draw_header(self, context):
scene = context.scene
props = scene.eevee
self.layout.prop(props, "use_shadows", text="")
def draw(self, context):
layout = self.layout
layout.use_property_split = True
scene = context.scene
props = scene.eevee
col = layout.column()
col.prop(props, "shadow_pool_size", text="Pool Size")
col.prop(props, "light_threshold")
class RENDER_PT_eevee_sampling(RenderButtonsPanel, Panel):
bl_label = "Sampling"
COMPAT_ENGINES = {'BLENDER_EEVEE'}
@ -808,6 +834,10 @@ class RENDER_PT_simplify_viewport(RenderButtonsPanel, Panel):
col = flow.column()
col.prop(rd, "simplify_volumes", text="Volume Resolution")
if context.engine in 'BLENDER_EEVEE_NEXT':
col = flow.column()
col.prop(rd, "simplify_shadows", text="Shadow Resolution")
class RENDER_PT_simplify_render(RenderButtonsPanel, Panel):
bl_label = "Render"
@ -835,6 +865,10 @@ class RENDER_PT_simplify_render(RenderButtonsPanel, Panel):
col = flow.column()
col.prop(rd, "simplify_child_particles_render", text="Max Child Particles")
if context.engine in 'BLENDER_EEVEE_NEXT':
col = flow.column()
col.prop(rd, "simplify_shadows_render", text="Shadow Resolution")
class RENDER_PT_simplify_greasepencil(RenderButtonsPanel, Panel, GreasePencilSimplifyPanel):
bl_label = "Grease Pencil"
@ -869,6 +903,7 @@ classes = (
RENDER_PT_eevee_performance,
RENDER_PT_eevee_hair,
RENDER_PT_eevee_shadows,
RENDER_PT_eevee_next_shadows,
RENDER_PT_eevee_indirect_lighting,
RENDER_PT_eevee_indirect_lighting_display,
RENDER_PT_eevee_film,

View File

@ -1996,7 +1996,7 @@ class SEQUENCER_PT_adjust_sound(SequencerButtonsPanel, Panel):
split = col.split(factor=0.4)
split.alignment = 'RIGHT'
split.label(text="Pan", heading_ctxt=i18n_contexts.id_sound)
split.label(text="Pan", text_ctxt=i18n_contexts.id_sound)
split.prop(strip, "pan", text="")
split.enabled = pan_enabled

File diff suppressed because it is too large Load Diff

View File

@ -2319,13 +2319,18 @@ class USERPREF_PT_experimental_new_features(ExperimentalPanel, Panel):
bl_label = "New Features"
def draw(self, context):
self._draw_items(
context, (
({"property": "use_sculpt_tools_tilt"}, ("blender/blender/issues/82877", "#82877")),
({"property": "use_extended_asset_browser"}, ("blender/blender/projects/10", "Pipeline, Assets & IO Project Page")),
({"property": "use_override_templates"}, ("blender/blender/issues/73318", "Milestone 4")),
),
)
self._draw_items(context,
(({"property": "use_sculpt_tools_tilt"},
("blender/blender/issues/82877",
"#82877")),
({"property": "use_extended_asset_browser"},
("blender/blender/projects/10",
"Pipeline, Assets & IO Project Page")),
({"property": "use_override_templates"},
("blender/blender/issues/73318",
"Milestone 4")),
),
)
class USERPREF_PT_experimental_prototypes(ExperimentalPanel, Panel):

View File

@ -40,7 +40,7 @@ typedef int32_t ft_pix;
/* Macros copied from `include/freetype/internal/ftobjs.h`. */
/**
* FIXME(@campbellbarton): Follow rounding from Blender 3.1x and older.
* FIXME(@ideasman42): Follow rounding from Blender 3.1x and older.
* This is what users will expect and changing this creates wider spaced text.
* Use this macro to communicate that rounding should be used, using floor is to avoid
* user visible changes, which can be reviewed and handled separately.

View File

@ -2,17 +2,12 @@
#pragma once
#include "BKE_curves.h"
/** \file
* \ingroup bke
* \brief Low-level operations for curves.
*/
#include <mutex>
#include "BLI_bounds_types.hh"
#include "BLI_cache_mutex.hh"
#include "BLI_generic_virtual_array.hh"
#include "BLI_index_mask.hh"
#include "BLI_math_matrix_types.hh"
@ -20,12 +15,12 @@
#include "BLI_offset_indices.hh"
#include "BLI_shared_cache.hh"
#include "BLI_span.hh"
#include "BLI_task.hh"
#include "BLI_vector.hh"
#include "BLI_virtual_array.hh"
#include "BKE_attribute.hh"
#include "BKE_attribute_math.hh"
#include "BKE_curves.h"
namespace blender::bke {

View File

@ -425,7 +425,7 @@ int set_listbasepointers(struct Main *main, struct ListBase *lb[]);
/**
* The size of thumbnails (optionally) stored in the `.blend` files header.
*
* NOTE(@campbellbarton): This is kept small as it's stored uncompressed in the `.blend` file,
* NOTE(@ideasman42): This is kept small as it's stored uncompressed in the `.blend` file,
* where a larger size would increase the size of every `.blend` file unreasonably.
* If we wanted to increase the size, we'd want to use compression (JPEG or similar).
*/

View File

@ -229,10 +229,6 @@ void BKE_mesh_material_remap(struct Mesh *me, const unsigned int *remap, unsigne
void BKE_mesh_smooth_flag_set(struct Mesh *me, bool use_smooth);
void BKE_mesh_auto_smooth_flag_set(struct Mesh *me, bool use_auto_smooth, float auto_smooth_angle);
/**
* Needed after converting a mesh with subsurf optimal display to mesh.
*/
void BKE_mesh_edges_set_draw_render(struct Mesh *me);
/**
* Used for unit testing; compares two meshes, checking only

View File

@ -152,10 +152,7 @@ void BKE_mesh_convert_mfaces_to_mpolys(struct Mesh *mesh);
*/
void BKE_mesh_do_versions_convert_mfaces_to_mpolys(struct Mesh *mesh);
/**
* Convert legacy #MFace.edcode to edge #ME_EDGEDRAW.
*/
void BKE_mesh_calc_edges_legacy(struct Mesh *me, bool use_old);
void BKE_mesh_calc_edges_legacy(struct Mesh *me);
void BKE_mesh_do_versions_cd_flag_init(struct Mesh *mesh);

View File

@ -357,6 +357,9 @@ Array<Vector<int>> build_vert_to_poly_map(Span<MPoly> polys,
int verts_num);
Array<Vector<int>> build_vert_to_loop_map(Span<int> corner_verts, int verts_num);
Array<Vector<int>> build_edge_to_loop_map(Span<int> corner_edges, int edges_num);
Array<Vector<int, 2>> build_edge_to_poly_map(Span<MPoly> polys,
Span<int> corner_edges,
int edges_num);
Vector<Vector<int>> build_edge_to_loop_map_resizable(Span<int> corner_edges, int edges_num);
inline int poly_loop_prev(const MPoly &poly, int loop_i)

View File

@ -174,6 +174,13 @@ struct MeshRuntime {
*/
BitVector<> subsurf_face_dot_tags;
/**
* A bit vector the size of the number of edges, set to true for edges that should be drawn in
* the viewport. Created by the "Optimimal Display" feature of the subdivision surface modifier.
* Otherwise it will be empty.
*/
BitVector<> subsurf_optimal_display_edges;
MeshRuntime() = default;
~MeshRuntime();

View File

@ -1534,6 +1534,7 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i
#define GEO_NODE_BLUR_ATTRIBUTE 1190
#define GEO_NODE_IMAGE 1191
#define GEO_NODE_INTERPOLATE_CURVES 1192
#define GEO_NODE_EDGES_TO_FACE_GROUPS 1193
/** \} */

View File

@ -32,8 +32,13 @@ typedef struct SubsurfRuntimeData {
SubdivSettings settings;
/* Cached subdivision surface descriptor, with topology and settings. */
struct Subdiv *subdiv;
bool set_by_draw_code;
struct Subdiv *subdiv_cpu;
struct Subdiv *subdiv_gpu;
/* Recent usage markers for UI diagnostics. To avoid UI flicker due to races
* between evaluation and UI redraw, they are set to 2 when an evaluator is used,
* and count down every frame. */
char used_cpu, used_gpu;
/* Cached mesh wrapper data, to be used for GPU subdiv or lazy evaluation on CPU. */
bool has_gpu_subdiv;

View File

@ -1489,7 +1489,7 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph,
/* Add orco coordinates to final and deformed mesh if requested. */
if (final_datamask.vmask & CD_MASK_ORCO) {
/* FIXME(@campbellbarton): avoid the need to convert to mesh data just to add an orco layer. */
/* FIXME(@ideasman42): avoid the need to convert to mesh data just to add an orco layer. */
BKE_mesh_wrapper_ensure_mdata(mesh_final);
add_orco_mesh(ob, em_input, mesh_final, mesh_orco, CD_ORCO);

View File

@ -884,7 +884,7 @@ static void where_am_i(char *fullname, const size_t maxlen, const char *name)
void BKE_appdir_program_path_init(const char *argv0)
{
#ifdef WITH_PYTHON_MODULE
/* NOTE(@campbellbarton): Always use `argv[0]` as is, when building as a Python module.
/* NOTE(@ideasman42): Always use `argv[0]` as is, when building as a Python module.
* Otherwise other methods of detecting the binary that override this argument
* which must point to the Python module for data-files to be detected. */
STRNCPY(g_app.program_filepath, argv0);

View File

@ -144,7 +144,7 @@ static float color_sample_remove_cost(const struct ColorResampleElem *c)
return area;
}
/* TODO(@campbellbarton): create `BLI_math_filter` ? */
/* TODO(@ideasman42): create `BLI_math_filter` ? */
static float filter_gauss(float x)
{
const float gaussfac = 1.6f;

View File

@ -1558,7 +1558,7 @@ static void followpath_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *
/* un-apply scaling caused by path */
if ((data->followflag & FOLLOWPATH_RADIUS) == 0) {
/* XXX(@campbellbarton): Assume that scale correction means that radius
/* XXX(@ideasman42): Assume that scale correction means that radius
* will have some scale error in it. */
float obsize[3];
@ -3835,7 +3835,7 @@ static void clampto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar
unit_m4(targetMatrix);
INIT_MINMAX(curveMin, curveMax);
/* XXX(@campbellbarton): don't think this is good calling this here because
/* XXX(@ideasman42): don't think this is good calling this here because
* the other object's data is lazily initializing bounding-box information.
* This could cause issues when evaluating from a thread.
* If the depsgraph ensures the bound-box is always available, a code-path could

View File

@ -2251,7 +2251,7 @@ static void make_bevel_list_3D_minimum_twist(BevList *bl)
int nr;
float q[4];
const bool is_cyclic = bl->poly != -1;
/* NOTE(@campbellbarton): For non-cyclic curves only initialize the first direction
/* NOTE(@ideasman42): For non-cyclic curves only initialize the first direction
* (via `vec_to_quat`), necessary for symmetry, see T71137.
* Otherwise initialize the first and second points before propagating rotation forward.
* This is historical as changing this can cause significantly different output.
@ -2480,7 +2480,7 @@ static void make_bevel_list_segment_2D(BevList *bl)
static void make_bevel_list_2D(BevList *bl)
{
/* NOTE(@campbellbarton): `bevp->dir` and `bevp->quat` are not needed for beveling but are
/* NOTE(@ideasman42): `bevp->dir` and `bevp->quat` are not needed for beveling but are
* used when making a path from a 2D curve, therefore they need to be set. */
BevPoint *bevp0, *bevp1, *bevp2;

View File

@ -6,6 +6,8 @@
#include <algorithm>
#include "BLI_task.hh"
#include "BKE_attribute_math.hh"
#include "BKE_curves.hh"

View File

@ -4,6 +4,8 @@
* \ingroup bke
*/
#include "BLI_task.hh"
#include "BKE_attribute_math.hh"
#include "BKE_curves.hh"

View File

@ -63,7 +63,6 @@ static void fill_mesh_topology(const int vert_offset,
MEdge &edge = edges[profile_edge_offset + i_ring];
edge.v1 = ring_vert_offset + i_profile;
edge.v2 = next_ring_vert_offset + i_profile;
edge.flag = ME_EDGEDRAW;
}
}
@ -79,7 +78,6 @@ static void fill_mesh_topology(const int vert_offset,
MEdge &edge = edges[ring_edge_offset + i_profile];
edge.v1 = ring_vert_offset + i_profile;
edge.v2 = ring_vert_offset + i_next_profile;
edge.flag = ME_EDGEDRAW;
}
}

View File

@ -1122,7 +1122,7 @@ void BKE_effectors_apply(ListBase *effectors,
float *wind_force,
float *impulse)
{
/* WARNING(@campbellbarton): historic comment?
/* WARNING(@ideasman42): historic comment?
* Many of these parameters don't exist!
*
* scene = scene where it runs in, for time and stuff.

View File

@ -74,7 +74,7 @@ ImBuf *BKE_icon_geom_rasterize(const struct Icon_Geom *geom, const uint size_x,
const uchar(*pos)[2] = geom->coords;
const uint *col = (void *)geom->colors;
/* TODO(@campbellbarton): Currently rasterizes to fixed size, then scales.
/* TODO(@ideasman42): Currently rasterizes to fixed size, then scales.
* Should rasterize to double size for eg instead. */
const int rect_size[2] = {max_ii(256, (int)size_x * 2), max_ii(256, (int)size_y * 2)};

View File

@ -797,7 +797,7 @@ IDProperty *IDP_GetProperties(ID *id, const bool create_if_needed)
if (create_if_needed) {
id->properties = MEM_callocN(sizeof(IDProperty), "IDProperty");
id->properties->type = IDP_GROUP;
/* NOTE(@campbellbarton): Don't overwrite the data's name and type
/* NOTE(@ideasman42): Don't overwrite the data's name and type
* some functions might need this if they
* don't have a real ID, should be named elsewhere. */
// strcpy(id->name, "top_level_group");

View File

@ -121,7 +121,7 @@ void BKE_library_filepath_set(Main *bmain, Library *lib, const char *filepath)
/* Not essential but set `filepath_abs` is an absolute copy of value which
* is more useful if its kept in sync. */
if (BLI_path_is_rel(lib->filepath_abs)) {
/* NOTE(@campbellbarton): the file may be unsaved, in this case, setting the
/* NOTE(@ideasman42): the file may be unsaved, in this case, setting the
* `filepath_abs` on an indirectly linked path is not allowed from the
* outliner, and its not really supported but allow from here for now
* since making local could cause this to be directly linked.

View File

@ -850,7 +850,7 @@ void BKE_object_material_resize(Main *bmain, Object *ob, const short totcol, boo
ob->mat = newmatar;
ob->matbits = newmatbits;
}
/* XXX(@campbellbarton): why not realloc on shrink? */
/* XXX(@ideasman42): why not realloc on shrink? */
ob->totcol = totcol;
if (ob->totcol && ob->actcol == 0) {

View File

@ -277,7 +277,7 @@ bool BKE_mball_is_basis(const Object *ob)
/* Meta-Ball Basis Notes from Blender-2.5x
* =======================================
*
* NOTE(@campbellbarton): This is a can of worms.
* NOTE(@ideasman42): This is a can of worms.
*
* This really needs a rewrite/refactor its totally broken in anything other than basic cases
* Multiple Scenes + Set Scenes & mixing meta-ball basis _should_ work but fails to update the
@ -485,7 +485,7 @@ bool BKE_mball_minmax_ex(
copy_v3_v3(centroid, &ml->x);
}
/* TODO(@campbellbarton): non circle shapes cubes etc, probably nobody notices. */
/* TODO(@ideasman42): non circle shapes cubes etc, probably nobody notices. */
for (int i = -1; i != 3; i += 2) {
copy_v3_v3(vec, centroid);
add_v3_fl(vec, scale_mb * i);

View File

@ -107,10 +107,12 @@ static void mesh_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int
mesh_dst->runtime->wrapper_type_finalize = mesh_src->runtime->wrapper_type_finalize;
mesh_dst->runtime->subsurf_runtime_data = mesh_src->runtime->subsurf_runtime_data;
mesh_dst->runtime->cd_mask_extra = mesh_src->runtime->cd_mask_extra;
/* Copy face dot tags, since meshes may be duplicated after a subsurf modifier or node, but we
* still need to be able to draw face center vertices. The tags may be cleared explicitly when
* the topology is changed. */
/* Copy face dot tags and edge tags, since meshes may be duplicated after a subsurf modifier or
* node, but we still need to be able to draw face center vertices and "optimal edges"
* differently. The tags may be cleared explicitly when the topology is changed. */
mesh_dst->runtime->subsurf_face_dot_tags = mesh_src->runtime->subsurf_face_dot_tags;
mesh_dst->runtime->subsurf_optimal_display_edges =
mesh_src->runtime->subsurf_optimal_display_edges;
if ((mesh_src->id.tag & LIB_TAG_NO_MAIN) == 0) {
/* This is a direct copy of a main mesh, so for now it has the same topology. */
mesh_dst->runtime->deformed_only = true;

View File

@ -148,7 +148,6 @@ static void serialize_and_initialize_deduplicated_edges(MutableSpan<EdgeMap> edg
/* Initialize new edge. */
new_edge.v1 = item.key.v_low;
new_edge.v2 = item.key.v_high;
new_edge.flag = ME_EDGEDRAW;
}
item.value.index = new_edge_index;
new_edge_index++;

View File

@ -122,7 +122,7 @@ static void make_edges_mdata_extend(Mesh &mesh)
BLI_edgehashIterator_getKey(ehi, &medge->v1, &medge->v2);
BLI_edgehashIterator_setValue(ehi, POINTER_FROM_UINT(e_index));
medge->flag = ME_EDGEDRAW;
medge->flag = 0;
}
BLI_edgehashIterator_free(ehi);
@ -225,7 +225,6 @@ static Mesh *mesh_nurbs_displist_to_mesh(const Curve *cu, const ListBase *dispba
for (b = 1; b < dl->nr; b++) {
edges[dst_edge].v1 = startvert + ofs + b - 1;
edges[dst_edge].v2 = startvert + ofs + b;
edges[dst_edge].flag = ME_EDGEDRAW;
dst_edge++;
}
@ -252,7 +251,6 @@ static Mesh *mesh_nurbs_displist_to_mesh(const Curve *cu, const ListBase *dispba
else {
edges[dst_edge].v2 = startvert + ofs + b + 1;
}
edges[dst_edge].flag = ME_EDGEDRAW;
dst_edge++;
}
}
@ -663,14 +661,6 @@ void BKE_mesh_from_pointcloud(const PointCloud *pointcloud, Mesh *me)
&pointcloud->pdata, &me->vdata, CD_MASK_PROP_ALL, CD_DUPLICATE, pointcloud->totpoint);
}
void BKE_mesh_edges_set_draw_render(Mesh *mesh)
{
MutableSpan<MEdge> edges = mesh->edges_for_write();
for (int i = 0; i < mesh->totedge; i++) {
edges[i].flag |= ME_EDGEDRAW;
}
}
void BKE_pointcloud_to_mesh(Main *bmain, Depsgraph *depsgraph, Scene * /*scene*/, Object *ob)
{
BLI_assert(ob->type == OB_POINTCLOUD);

View File

@ -89,7 +89,6 @@ static void mesh_calc_edges_mdata(const MVert * /*allvert*/,
int totface,
int /*totloop*/,
int totpoly,
const bool use_old,
MEdge **r_medge,
int *r_totedge)
{
@ -156,9 +155,6 @@ static void mesh_calc_edges_mdata(const MVert * /*allvert*/,
if (ed->v1 != (ed + 1)->v1 || ed->v2 != (ed + 1)->v2) {
med->v1 = ed->v1;
med->v2 = ed->v2;
if (use_old == false || ed->is_draw) {
med->flag = ME_EDGEDRAW;
}
/* order is swapped so extruding this edge as a surface won't flip face normals
* with cyclic curves */
@ -175,7 +171,6 @@ static void mesh_calc_edges_mdata(const MVert * /*allvert*/,
/* last edge */
med->v1 = ed->v1;
med->v2 = ed->v2;
med->flag = ME_EDGEDRAW;
MEM_freeN(edsort);
@ -206,7 +201,7 @@ static void mesh_calc_edges_mdata(const MVert * /*allvert*/,
*r_totedge = totedge_final;
}
void BKE_mesh_calc_edges_legacy(Mesh *me, const bool use_old)
void BKE_mesh_calc_edges_legacy(Mesh *me)
{
using namespace blender;
MEdge *medge;
@ -224,7 +219,6 @@ void BKE_mesh_calc_edges_legacy(Mesh *me, const bool use_old)
me->totface,
me->totloop,
polys.size(),
use_old,
&medge,
&totedge);

View File

@ -603,8 +603,23 @@ Array<Vector<int>> build_edge_to_loop_map(const Span<int> corner_edges, const in
return map;
}
Array<Vector<int, 2>> build_edge_to_poly_map(const Span<MPoly> polys,
const Span<int> corner_edges,
const int edges_num)
{
Array<Vector<int, 2>> map(edges_num);
for (const int64_t i : polys.index_range()) {
const MPoly &poly = polys[i];
for (const int edge : corner_edges.slice(poly.loopstart, poly.totloop)) {
map[edge].append(int(i));
}
}
return map;
}
Vector<Vector<int>> build_edge_to_loop_map_resizable(const Span<int> corner_edges,
const int edges_num)
{
Vector<Vector<int>> map(edges_num);
for (const int64_t i : corner_edges.index_range()) {

View File

@ -34,7 +34,7 @@ static int compare_v2_classify(const float uv_a[2], const float uv_b[2])
if (uv_a[0] == uv_b[0] && uv_a[1] == uv_b[1]) {
return CMP_EQUAL;
}
/* NOTE(@campbellbarton): that the ULP value is the primary value used to compare relative
/* NOTE(@ideasman42): that the ULP value is the primary value used to compare relative
* values as the absolute value doesn't account for float precision at difference scales.
* - For subdivision-surface ULP of 3 is sufficient,
* although this value is extremely small.

View File

@ -230,6 +230,7 @@ void BKE_mesh_runtime_clear_geometry(Mesh *mesh)
mesh->runtime->loose_edges_cache.tag_dirty();
mesh->runtime->looptris_cache.tag_dirty();
mesh->runtime->subsurf_face_dot_tags.clear_and_shrink();
mesh->runtime->subsurf_optimal_display_edges.clear_and_shrink();
if (mesh->runtime->shrinkwrap_data) {
BKE_shrinkwrap_boundary_data_free(mesh->runtime->shrinkwrap_data);
}
@ -245,6 +246,7 @@ void BKE_mesh_tag_edges_split(struct Mesh *mesh)
free_subdiv_ccg(*mesh->runtime);
mesh->runtime->loose_edges_cache.tag_dirty();
mesh->runtime->subsurf_face_dot_tags.clear_and_shrink();
mesh->runtime->subsurf_optimal_display_edges.clear_and_shrink();
if (mesh->runtime->shrinkwrap_data) {
BKE_shrinkwrap_boundary_data_free(mesh->runtime->shrinkwrap_data);
}

View File

@ -573,7 +573,7 @@ void BKE_mesh_calc_loop_tangents(Mesh *me_eval,
const char (*tangent_names)[MAX_CUSTOMDATA_LAYER_NAME],
int tangent_names_len)
{
/* TODO(@campbellbarton): store in Mesh.runtime to avoid recalculation. */
/* TODO(@ideasman42): store in Mesh.runtime to avoid recalculation. */
short tangent_mask = 0;
BKE_mesh_calc_loop_tangent_ex(
BKE_mesh_vert_positions(me_eval),

View File

@ -1359,8 +1359,6 @@ void BKE_mesh_calc_edges_tessface(Mesh *mesh)
for (int i = 0; BLI_edgesetIterator_isDone(ehi) == false;
BLI_edgesetIterator_step(ehi), i++, med++, index++) {
BLI_edgesetIterator_getKey(ehi, &med->v1, &med->v2);
med->flag = ME_EDGEDRAW;
*index = ORIGINDEX_NONE;
}
BLI_edgesetIterator_free(ehi);

View File

@ -350,7 +350,7 @@ static Mesh *mesh_wrapper_ensure_subdivision(Mesh *me)
BKE_mesh_calc_normals_split(subdiv_mesh);
}
if (subdiv != runtime_data->subdiv) {
if (subdiv != runtime_data->subdiv_cpu && subdiv != runtime_data->subdiv_gpu) {
BKE_subdiv_free(subdiv);
}

View File

@ -2342,8 +2342,10 @@ bNode *node_copy_with_mapping(bNodeTree *dst_tree,
node_dst->typeinfo->copyfunc_api(&ptr, &node_src);
}
/* Reset the declaration of the new node. */
nodeDeclarationEnsure(dst_tree, node_dst);
/* Reset the declaration of the new node in real tree. */
if (dst_tree != nullptr) {
nodeDeclarationEnsure(dst_tree, node_dst);
}
return node_dst;
}
@ -3617,6 +3619,8 @@ bool nodeDeclarationEnsureOnOutdatedNode(bNodeTree *ntree, bNode *node)
return false;
}
if (node->typeinfo->declare_dynamic) {
BLI_assert(ntree != nullptr);
BLI_assert(node != nullptr);
node->runtime->declaration = new blender::nodes::NodeDeclaration();
blender::nodes::build_node_declaration_dynamic(*ntree, *node, *node->runtime->declaration);
return true;

View File

@ -2432,7 +2432,7 @@ ParticleSystem *BKE_object_copy_particlesystem(ParticleSystem *psys, const int f
psysn->pointcache = BKE_ptcache_copy_list(&psysn->ptcaches, &psys->ptcaches, flag);
}
/* XXX(@campbellbarton): from reading existing code this seems correct but intended usage of
/* XXX(@ideasman42): from reading existing code this seems correct but intended usage of
* point-cache should with cloth should be added in 'ParticleSystem'. */
if (psysn->clmd) {
psysn->clmd->point_cache = psysn->pointcache;

View File

@ -1382,7 +1382,7 @@ void BKE_ocean_bake(struct Ocean *o,
void (*update_cb)(void *, float progress, int *cancel),
void *update_cb_data)
{
/* NOTE(@campbellbarton): some of these values remain uninitialized unless certain options
/* NOTE(@ideasman42): some of these values remain uninitialized unless certain options
* are enabled, take care that #BKE_ocean_eval_ij() initializes a member before use. */
OceanResult ocr;
@ -1437,7 +1437,7 @@ void BKE_ocean_bake(struct Ocean *o,
rgb_to_rgba_unit_alpha(&ibuf_disp->rect_float[4 * (res_x * y + x)], ocr.disp);
if (o->_do_jacobian) {
/* TODO(@campbellbarton): cleanup unused code. */
/* TODO(@ideasman42): cleanup unused code. */
float /* r, */ /* UNUSED */ pr = 0.0f, foam_result;
float neg_disp, neg_eplus;

View File

@ -5470,7 +5470,7 @@ void BKE_particle_system_blend_read_lib(BlendLibReader *reader,
BLO_read_id_address(reader, id->lib, &psys->target_ob);
if (psys->clmd) {
/* XXX(@campbellbarton): from reading existing code this seems correct but intended usage
/* XXX(@ideasman42): from reading existing code this seems correct but intended usage
* of point-cache with cloth should be added in #ParticleSystem. */
psys->clmd->point_cache = psys->pointcache;
psys->clmd->ptcaches.first = psys->clmd->ptcaches.last = nullptr;

View File

@ -967,7 +967,7 @@ void psys_get_birth_coords(
float tmat[3][3];
/* NOTE: utan_local is not taken from 'utan', we calculate from rot_vec/vtan. */
/* NOTE(@campbellbarton): it looks like rotation phase may be applied twice
/* NOTE(@ideasman42): it looks like rotation phase may be applied twice
* (once with vtan, again below) however this isn't the case. */
float *rot_vec_local = tmat[0];
float *vtan_local = tmat[1];

View File

@ -2588,7 +2588,7 @@ static bool check_rendered_viewport_visible(Main *bmain)
return false;
}
/* TODO(@campbellbarton): shouldn't we be able to use 'DEG_get_view_layer' here?
/* TODO(@ideasman42): shouldn't we be able to use 'DEG_get_view_layer' here?
* Currently this is nullptr on load, so don't. */
static void prepare_mesh_for_viewport_render(Main *bmain,
const Scene *scene,

View File

@ -529,6 +529,10 @@ static bool subdiv_mesh_topology_info(const SubdivForeachContext *foreach_contex
subdiv_mesh_prepare_accumulator(subdiv_context, num_vertices);
subdiv_context->subdiv_mesh->runtime->subsurf_face_dot_tags.clear();
subdiv_context->subdiv_mesh->runtime->subsurf_face_dot_tags.resize(num_vertices);
if (subdiv_context->settings->use_optimal_display) {
subdiv_context->subdiv_mesh->runtime->subsurf_optimal_display_edges.clear();
subdiv_context->subdiv_mesh->runtime->subsurf_optimal_display_edges.resize(num_edges);
}
return true;
}
@ -777,15 +781,10 @@ static void subdiv_mesh_vertex_inner(const SubdivForeachContext *foreach_context
* \{ */
static void subdiv_copy_edge_data(SubdivMeshContext *ctx,
MEdge *subdiv_edge,
const int subdiv_edge_index,
const int coarse_edge_index)
{
const int subdiv_edge_index = subdiv_edge - ctx->subdiv_edges;
if (coarse_edge_index == ORIGINDEX_NONE) {
subdiv_edge->flag = 0;
if (!ctx->settings->use_optimal_display) {
subdiv_edge->flag |= ME_EDGEDRAW;
}
if (ctx->edge_origindex != nullptr) {
ctx->edge_origindex[subdiv_edge_index] = ORIGINDEX_NONE;
}
@ -793,7 +792,9 @@ static void subdiv_copy_edge_data(SubdivMeshContext *ctx,
}
CustomData_copy_data(
&ctx->coarse_mesh->edata, &ctx->subdiv_mesh->edata, coarse_edge_index, subdiv_edge_index, 1);
subdiv_edge->flag |= ME_EDGEDRAW;
if (ctx->settings->use_optimal_display) {
ctx->subdiv_mesh->runtime->subsurf_optimal_display_edges[subdiv_edge_index].set();
}
}
static void subdiv_mesh_edge(const SubdivForeachContext *foreach_context,
@ -807,7 +808,7 @@ static void subdiv_mesh_edge(const SubdivForeachContext *foreach_context,
SubdivMeshContext *ctx = static_cast<SubdivMeshContext *>(foreach_context->user_data);
MEdge *subdiv_medge = ctx->subdiv_edges;
MEdge *subdiv_edge = &subdiv_medge[subdiv_edge_index];
subdiv_copy_edge_data(ctx, subdiv_edge, coarse_edge_index);
subdiv_copy_edge_data(ctx, subdiv_edge_index, coarse_edge_index);
subdiv_edge->v1 = subdiv_v1;
subdiv_edge->v2 = subdiv_v2;
}

View File

@ -49,6 +49,8 @@ bool BKE_subsurf_modifier_runtime_init(SubsurfModifierData *smd, const bool use_
* was already allocated. */
if (runtime_data) {
runtime_data->settings = settings;
runtime_data->used_cpu = runtime_data->used_gpu = 0;
}
return false;
@ -162,15 +164,18 @@ Subdiv *BKE_subsurf_modifier_subdiv_descriptor_ensure(SubsurfRuntimeData *runtim
const Mesh *mesh,
const bool for_draw_code)
{
if (runtime_data->subdiv && runtime_data->set_by_draw_code != for_draw_code) {
BKE_subdiv_free(runtime_data->subdiv);
runtime_data->subdiv = nullptr;
if (for_draw_code) {
runtime_data->used_gpu = 2; /* countdown in frames */
return runtime_data->subdiv_gpu = BKE_subdiv_update_from_mesh(
runtime_data->subdiv_gpu, &runtime_data->settings, mesh);
}
else {
runtime_data->used_cpu = 2;
return runtime_data->subdiv_cpu = BKE_subdiv_update_from_mesh(
runtime_data->subdiv_cpu, &runtime_data->settings, mesh);
}
Subdiv *subdiv = BKE_subdiv_update_from_mesh(
runtime_data->subdiv, &runtime_data->settings, mesh);
runtime_data->subdiv = subdiv;
runtime_data->set_by_draw_code = for_draw_code;
return subdiv;
}
int BKE_subsurf_modifier_eval_required_mode(bool is_final_render, bool is_edit_mode)

View File

@ -891,7 +891,7 @@ static void ccgDM_copyFinalVertArray(DerivedMesh *dm, float (*r_positions)[3])
int x;
for (x = 1; x < edgeSize - 1; x++) {
/* NOTE(@campbellbarton): This gives errors with `--debug-fpe` the normals don't seem to be
/* NOTE(@ideasman42): This gives errors with `--debug-fpe` the normals don't seem to be
* unit length. This is most likely caused by edges with no faces which are now zeroed out,
* see comment in: `ccgSubSurf__calcVertNormals()`. */
vd = static_cast<CCGElem *>(ccgSubSurf_getEdgeData(ss, e, x));
@ -926,7 +926,6 @@ static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge)
int edgeSize = ccgSubSurf_getEdgeSize(ss);
uint i = 0;
short *edgeFlags = ccgdm->edgeFlags;
const short ed_interior_flag = ccgdm->drawInteriorEdges ? ME_EDGEDRAW : 0;
totface = ccgSubSurf_getNumFaces(ss);
for (index = 0; index < totface; index++) {
@ -938,7 +937,7 @@ static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge)
ccgDM_to_MEdge(&medge[i++],
getFaceIndex(ss, f, S, x, 0, edgeSize, gridSize),
getFaceIndex(ss, f, S, x + 1, 0, edgeSize, gridSize),
ed_interior_flag);
0);
}
for (x = 1; x < gridSize - 1; x++) {
@ -946,11 +945,11 @@ static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge)
ccgDM_to_MEdge(&medge[i++],
getFaceIndex(ss, f, S, x, y, edgeSize, gridSize),
getFaceIndex(ss, f, S, x, y + 1, edgeSize, gridSize),
ed_interior_flag);
0);
ccgDM_to_MEdge(&medge[i++],
getFaceIndex(ss, f, S, y, x, edgeSize, gridSize),
getFaceIndex(ss, f, S, y + 1, x, edgeSize, gridSize),
ed_interior_flag);
0);
}
}
}
@ -965,12 +964,9 @@ static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge)
if (edgeFlags) {
if (edgeIdx != -1) {
ed_flag |= ((edgeFlags[index] & ME_SEAM) | ME_EDGEDRAW);
ed_flag |= (edgeFlags[index] & ME_SEAM);
}
}
else {
ed_flag |= ME_EDGEDRAW;
}
for (x = 0; x < edgeSize - 1; x++) {
ccgDM_to_MEdge(&medge[i++],

View File

@ -757,7 +757,7 @@ template<typename T> detail::Quaternion<T> normalized_to_quat_fast(const MatBase
}
}
else {
/* NOTE(@campbellbarton): A zero matrix will fall through to this block,
/* NOTE(@ideasman42): A zero matrix will fall through to this block,
* needed so a zero scaled matrices to return a quaternion without rotation, see: T101848.
*/
const T trace = 1.0f + mat[0][0] + mat[1][1] + mat[2][2];

View File

@ -910,6 +910,27 @@ struct MutableMatView
unroll<NumCol>([&](auto i) { (*this)[i] *= b; });
return *this;
}
/** Vector operators. Need to be redefined to avoid operator priority issue. */
friend col_type operator*(MutableMatView &a, const row_type &b)
{
/* This is the reference implementation.
* Might be overloaded with vectorized / optimized code. */
col_type result(0);
unroll<NumCol>([&](auto c) { result += b[c] * a[c]; });
return result;
}
/** Multiply by the transposed. */
friend row_type operator*(const col_type &a, MutableMatView &b)
{
/* This is the reference implementation.
* Might be overloaded with vectorized / optimized code. */
row_type result(0);
unroll<NumCol>([&](auto c) { unroll<NumRow>([&](auto r) { result[c] += b[c][r] * a[r]; }); });
return result;
}
};
using float2x2 = MatBase<float, 2, 2>;

View File

@ -252,6 +252,16 @@ template<typename T, int Size>
return result;
}
template<typename T, int Size>
[[nodiscard]] inline VecBase<T, Size> round(const VecBase<T, Size> &a)
{
VecBase<T, Size> result;
for (int i = 0; i < Size; i++) {
result[i] = std::round(a[i]);
}
return result;
}
template<typename T, int Size>
[[nodiscard]] inline VecBase<T, Size> ceil(const VecBase<T, Size> &a)
{

View File

@ -82,7 +82,7 @@ struct ScanFillEdge *BLI_scanfill_edge_add(ScanFillContext *sf_ctx,
struct ScanFillVert *v2);
enum {
/* NOTE(@campbellbarton): using #BLI_SCANFILL_CALC_REMOVE_DOUBLES
/* NOTE(@ideasman42): using #BLI_SCANFILL_CALC_REMOVE_DOUBLES
* Assumes ordered edges, otherwise we risk an eternal loop
* removing double verts. */
BLI_SCANFILL_CALC_REMOVE_DOUBLES = (1 << 1),

View File

@ -9,7 +9,7 @@
*/
#ifdef __GNUC__
/* NOTE(@campbellbarton): CLANG behaves slightly differently to GCC,
/* NOTE(@ideasman42): CLANG behaves slightly differently to GCC,
* these can be enabled but do so carefully as they can introduce build-errors. */
# if !defined(__clang__)
# pragma GCC diagnostic error "-Wsign-compare"

View File

@ -1667,7 +1667,7 @@ bool isect_ray_tri_v3(const float ray_origin[3],
float *r_lambda,
float r_uv[2])
{
/* NOTE(@campbellbarton): these values were 0.000001 in 2.4x but for projection snapping on
/* NOTE(@ideasman42): these values were 0.000001 in 2.4x but for projection snapping on
* a human head `(1BU == 1m)`, subdivision-surface level 2, this gave many errors. */
const float epsilon = 0.00000001f;
float p[3], s[3], e1[3], e2[3], q[3];
@ -3773,7 +3773,7 @@ void barycentric_weights_v2_quad(const float v1[2],
const float co[2],
float w[4])
{
/* NOTE(@campbellbarton): fabsf() here is not needed for convex quads
/* NOTE(@ideasman42): fabsf() here is not needed for convex quads
* (and not used in #interp_weights_poly_v2).
* But in the case of concave/bow-tie quads for the mask rasterizer it
* gives unreliable results without adding `absf()`. If this becomes an issue for more general

View File

@ -334,7 +334,7 @@ void mat3_normalized_to_quat_fast(float q[4], const float mat[3][3])
}
}
else {
/* NOTE(@campbellbarton): A zero matrix will fall through to this block,
/* NOTE(@ideasman42): A zero matrix will fall through to this block,
* needed so a zero scaled matrices to return a quaternion without rotation, see: T101848. */
const float trace = 1.0f + mat[0][0] + mat[1][1] + mat[2][2];
float s = 2.0f * sqrtf(trace);

View File

@ -155,19 +155,18 @@ static PolyIndex *pf_ear_tip_find(PolyFill *pf
#endif
);
static bool pf_ear_tip_check(PolyFill *pf, PolyIndex *pi_ear_tip);
static bool pf_ear_tip_check(PolyFill *pf, PolyIndex *pi_ear_tip, const eSign sign_accept);
static void pf_ear_tip_cut(PolyFill *pf, PolyIndex *pi_ear_tip);
BLI_INLINE eSign signum_enum(float a)
{
if (UNLIKELY(a == 0.0f)) {
return 0;
}
if (a > 0.0f) {
return 1;
return CONVEX;
}
return -1;
if (UNLIKELY(a == 0.0f)) {
return TANGENTIAL;
}
return CONCAVE;
}
/**
@ -590,22 +589,44 @@ static PolyIndex *pf_ear_tip_find(PolyFill *pf
uint i;
/* Use two passes when looking for an ear.
*
* - The first pass only picks *good* (concave) choices.
* For polygons which aren't degenerate this works well
* since it avoids creating any zero area faces.
*
* - The second pass is only met if no concave choices are possible,
* so the cost of a second pass is only incurred for degenerate polygons.
* In this case accept zero area faces as better alternatives aren't available.
*
* See: #103913 for reference.
*
* NOTE: these passes draw a distinction between zero area faces and concave
* which is susceptible minor differences in float precision
* (since #TANGENTIAL compares with 0.0f).
*
* While it's possible to compute an error threshold and run a pass that picks
* ears which are more likely not to appear as zero area from a users perspective,
* this API prioritizes performance (for real-time updates).
* Higher quality tessellation can always be achieved using #BLI_polyfill_beautify.
*/
for (eSign sign_accept = CONVEX; sign_accept >= TANGENTIAL; sign_accept--) {
#ifdef USE_CLIP_EVEN
pi_ear = pi_ear_init;
pi_ear = pi_ear_init;
#else
pi_ear = pf->indices;
pi_ear = pf->indices;
#endif
i = coords_num;
while (i--) {
if (pf_ear_tip_check(pf, pi_ear)) {
return pi_ear;
}
i = coords_num;
while (i--) {
if (pf_ear_tip_check(pf, pi_ear, sign_accept)) {
return pi_ear;
}
#ifdef USE_CLIP_SWEEP
pi_ear = reverse ? pi_ear->prev : pi_ear->next;
pi_ear = reverse ? pi_ear->prev : pi_ear->next;
#else
pi_ear = pi_ear->next;
pi_ear = pi_ear->next;
#endif
}
}
/* Desperate mode: if no vertex is an ear tip,
@ -638,7 +659,7 @@ static PolyIndex *pf_ear_tip_find(PolyFill *pf
return pi_ear;
}
static bool pf_ear_tip_check(PolyFill *pf, PolyIndex *pi_ear_tip)
static bool pf_ear_tip_check(PolyFill *pf, PolyIndex *pi_ear_tip, const eSign sign_accept)
{
#ifndef USE_KDTREE
/* localize */
@ -674,7 +695,7 @@ static bool pf_ear_tip_check(PolyFill *pf, PolyIndex *pi_ear_tip)
}
#endif
if (UNLIKELY(pi_ear_tip->sign == CONCAVE)) {
if (UNLIKELY(pi_ear_tip->sign != sign_accept)) {
return false;
}

View File

@ -329,7 +329,7 @@ void **BLI_smallhash_iternew_p(const SmallHash *sh, SmallHashIter *iter, uintptr
/** \name Debugging & Introspection
* \{ */
/* NOTE(@campbellbarton): useful for debugging but may not be intended for general use. */
/* NOTE(@ideasman42): useful for debugging but may not be intended for general use. */
#if 0
void BLI_smallhash_print(SmallHash *sh)
{

View File

@ -402,7 +402,7 @@ bool BLI_str_quoted_substr_range(const char *__restrict str,
return true;
}
/* NOTE(@campbellbarton): in principal it should be possible to access a quoted string
/* NOTE(@ideasman42): in principal it should be possible to access a quoted string
* with an arbitrary size, currently all callers for this functionality
* happened to use a fixed size buffer, so only #BLI_str_quoted_substr is needed. */
#if 0

View File

@ -45,7 +45,7 @@ static const size_t utf8_skip_data[256] = {
ptrdiff_t BLI_str_utf8_invalid_byte(const char *str, size_t length)
{
/* NOTE(@campbellbarton): from libswish3, originally called u8_isvalid(),
/* NOTE(@ideasman42): from libswish3, originally called u8_isvalid(),
* modified to return the index of the bad character (byte index not UTF).
* http://svn.swish-e.org/libswish3/trunk/src/libswish3/utf8.c r3044.
*
@ -403,7 +403,7 @@ int BLI_str_utf8_char_width_safe(const char *p)
/* copied from glib's gutf8.c, added 'Err' arg */
/* NOTE(@campbellbarton): glib uses uint for unicode, best we do the same,
/* NOTE(@ideasman42): glib uses uint for unicode, best we do the same,
* though we don't typedef it. */
#define UTF8_COMPUTE(Char, Mask, Len, Err) \

View File

@ -388,6 +388,21 @@ TEST(math_matrix_types, ViewMatrixMultiplyOperator)
EXPECT_EQ(view[1][1], 46);
}
TEST(math_matrix_types, ViewVectorMultiplyOperator)
{
float4x4 mat = float4x4({1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}, {13, 14, 15, 16});
auto view = mat.view<2, 3, 1, 1>();
float3 result = view * float2(4, 5);
EXPECT_EQ(result[0], 74);
EXPECT_EQ(result[1], 83);
EXPECT_EQ(result[2], 92);
float2 result2 = float3(1, 2, 3) * view;
EXPECT_EQ(result2[0], 44);
EXPECT_EQ(result2[1], 68);
}
TEST(math_matrix_types, ViewMatrixNormalize)
{
float4x4 mat = float4x4({1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}, {13, 14, 15, 16});

View File

@ -288,7 +288,7 @@ void BLO_expand_id(BlendExpander *expander, struct ID *id);
* This function ensures that reports are printed,
* in the case of library linking errors this is important!
*
* NOTE(@campbellbarton) a kludge but better than doubling up on prints,
* NOTE(@ideasman42) a kludge but better than doubling up on prints,
* we could alternatively have a versions of a report function which forces printing.
*/
void BLO_reportf_wrap(struct BlendFileReadReport *reports,

View File

@ -3779,15 +3779,6 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain)
}
}
if (!MAIN_VERSION_ATLEAST(bmain, 305, 1)) {
/* Reset edge visibility flag, since the base is meant to be "true" for original meshes. */
LISTBASE_FOREACH (Mesh *, mesh, &bmain->meshes) {
for (MEdge &edge : mesh->edges_for_write()) {
edge.flag |= ME_EDGEDRAW;
}
}
}
if (!MAIN_VERSION_ATLEAST(bmain, 305, 2)) {
LISTBASE_FOREACH (MovieClip *, clip, &bmain->movieclips) {
MovieTracking *tracking = &clip->tracking;
@ -3911,6 +3902,15 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain)
* \note Keep this message at the bottom of the function.
*/
{
if (!DNA_struct_elem_find(fd->filesdna, "SceneEEVEE", "int", "shadow_pool_size")) {
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
scene->eevee.flag |= SCE_EEVEE_SHADOW_ENABLED;
scene->eevee.shadow_pool_size = 512;
scene->r.simplify_shadows = 1.0f;
scene->r.simplify_shadows_render = 1.0f;
}
}
/* Keep this block, even when empty. */
}
}

View File

@ -1467,7 +1467,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *bmain)
for (me = bmain->meshes.first; me; me = me->id.next) {
if (!me->medge) {
BKE_mesh_calc_edges_legacy(me, true); /* true = use #MFace.edcode. */
BKE_mesh_calc_edges_legacy(me);
}
else {
BKE_mesh_strip_loose_faces(me);

View File

@ -113,7 +113,7 @@ using blender::StringRef;
static char bm_edge_flag_from_mflag(const short mflag)
{
return ((mflag & ME_SEAM) ? BM_ELEM_SEAM : 0) | ((mflag & ME_EDGEDRAW) ? BM_ELEM_DRAW : 0);
return ((mflag & ME_SEAM) ? BM_ELEM_SEAM : 0) | BM_ELEM_DRAW;
}
static char bm_face_flag_from_mflag(const char mflag)
{
@ -124,7 +124,7 @@ static short bm_edge_flag_to_mflag(const BMEdge *e)
{
const char hflag = e->head.hflag;
return ((hflag & BM_ELEM_SEAM) ? ME_SEAM : 0) | ((hflag & BM_ELEM_DRAW) ? ME_EDGEDRAW : 0);
return (hflag & BM_ELEM_SEAM) ? ME_SEAM : 0;
}
static char bm_face_flag_to_mflag(const BMFace *f)
{
@ -865,7 +865,7 @@ static void bm_to_mesh_shape(BMesh *bm,
((keyi = BM_ELEM_CD_GET_INT(eve, cd_shape_keyindex_offset)) != ORIGINDEX_NONE) &&
(keyi < currkey->totelem)) {
/* Reconstruct keys via vertices original key indices.
* WARNING(@campbellbarton): `currkey->data` is known to be unreliable as the edit-mesh
* WARNING(@ideasman42): `currkey->data` is known to be unreliable as the edit-mesh
* coordinates may be flushed back to the shape-key when exporting or rendering.
* This is a last resort! If this branch is running as part of regular usage
* it can be considered a bug. */
@ -1432,15 +1432,6 @@ static void bm_to_mesh_edges(const BMesh &bm,
dst_edge.v1 = BM_elem_index_get(src_edge.v1);
dst_edge.v2 = BM_elem_index_get(src_edge.v2);
dst_edge.flag = bm_edge_flag_to_mflag(&src_edge);
/* Handle this differently to editmode switching; only enable draw for single user
* edges rather than calculating angle. */
if ((dst_edge.flag & ME_EDGEDRAW) == 0) {
if (src_edge.l && src_edge.l == src_edge.l->radial_next) {
dst_edge.flag |= ME_EDGEDRAW;
}
}
CustomData_from_bmesh_block(&bm.edata, &mesh.edata, src_edge.head.data, edge_i);
}
if (!select_edge.is_empty()) {

View File

@ -82,7 +82,6 @@ void BM_mesh_bm_to_me(struct Main *bmain,
* - Ignore shape-keys.
* - Ignore vertex-parents.
* - Ignore selection history.
* - Uses simpler method to calculate #ME_EDGEDRAW
* - Uses #CD_MASK_DERIVEDMESH instead of #CD_MASK_MESH.
*
* \note Was `cddm_from_bmesh_ex` in 2.7x, removed `MFace` support.

View File

@ -15,7 +15,7 @@
#include "intern/bmesh_operators_private.h" /* own include */
/**
* TODO(@campbellbarton): Many connected edge loops can cause an error attempting
* TODO(@ideasman42): Many connected edge loops can cause an error attempting
* to create faces with duplicate vertices. While this needs to be investigated,
* it's simple enough to check for this case, see: T102232.
*/

View File

@ -19,7 +19,7 @@
void bmo_contextual_create_exec(BMesh *bm, BMOperator *op)
{
/* NOTE(@campbellbarton): doing the best thing here isn't always easy create vs dissolve,
/* NOTE(@ideasman42): doing the best thing here isn't always easy create vs dissolve,
* its nice to support but it _really_ gives issues we might have to not call dissolve. */
BMOIter oiter;

View File

@ -7,7 +7,7 @@
namespace blender::compositor {
#define USE_FORCE_BILINEAR
/* XXX(@campbellbarton): ignore input and use default from old compositor,
/* XXX(@ideasman42): ignore input and use default from old compositor,
* could become an option like the transform node.
*
* NOTE: use bilinear because bicubic makes fuzzy even when not scaling at all (1:1)

View File

@ -151,6 +151,7 @@ set(SRC
engines/eevee_next/eevee_renderbuffers.cc
engines/eevee_next/eevee_sampling.cc
engines/eevee_next/eevee_shader.cc
engines/eevee_next/eevee_shadow.cc
engines/eevee_next/eevee_sync.cc
engines/eevee_next/eevee_velocity.cc
engines/eevee_next/eevee_view.cc
@ -281,6 +282,7 @@ set(SRC
engines/eevee_next/eevee_renderbuffers.hh
engines/eevee_next/eevee_sampling.hh
engines/eevee_next/eevee_shader.hh
engines/eevee_next/eevee_shadow.hh
engines/eevee_next/eevee_sync.hh
engines/eevee_next/eevee_velocity.hh
engines/eevee_next/eevee_view.hh
@ -422,6 +424,7 @@ set(GLSL_SRC
engines/eevee_next/shaders/eevee_camera_lib.glsl
engines/eevee_next/shaders/eevee_colorspace_lib.glsl
engines/eevee_next/shaders/eevee_cryptomatte_lib.glsl
engines/eevee_next/shaders/eevee_transparency_lib.glsl
engines/eevee_next/shaders/eevee_depth_of_field_accumulator_lib.glsl
engines/eevee_next/shaders/eevee_depth_of_field_bokeh_lut_comp.glsl
engines/eevee_next/shaders/eevee_depth_of_field_downsample_comp.glsl
@ -462,10 +465,29 @@ set(GLSL_SRC
engines/eevee_next/shaders/eevee_motion_blur_lib.glsl
engines/eevee_next/shaders/eevee_nodetree_lib.glsl
engines/eevee_next/shaders/eevee_sampling_lib.glsl
engines/eevee_next/shaders/eevee_shadow_debug_frag.glsl
engines/eevee_next/shaders/eevee_shadow_lib.glsl
engines/eevee_next/shaders/eevee_shadow_page_allocate_comp.glsl
engines/eevee_next/shaders/eevee_shadow_page_clear_comp.glsl
engines/eevee_next/shaders/eevee_shadow_page_defrag_comp.glsl
engines/eevee_next/shaders/eevee_shadow_page_free_comp.glsl
engines/eevee_next/shaders/eevee_shadow_page_mask_comp.glsl
engines/eevee_next/shaders/eevee_shadow_page_ops_lib.glsl
engines/eevee_next/shaders/eevee_shadow_tag_update_comp.glsl
engines/eevee_next/shaders/eevee_shadow_tag_usage_comp.glsl
engines/eevee_next/shaders/eevee_shadow_tag_usage_frag.glsl
engines/eevee_next/shaders/eevee_shadow_tag_usage_lib.glsl
engines/eevee_next/shaders/eevee_shadow_tag_usage_vert.glsl
engines/eevee_next/shaders/eevee_shadow_test.glsl
engines/eevee_next/shaders/eevee_shadow_tilemap_bounds_comp.glsl
engines/eevee_next/shaders/eevee_shadow_tilemap_finalize_comp.glsl
engines/eevee_next/shaders/eevee_shadow_tilemap_init_comp.glsl
engines/eevee_next/shaders/eevee_shadow_tilemap_lib.glsl
engines/eevee_next/shaders/eevee_surf_deferred_frag.glsl
engines/eevee_next/shaders/eevee_surf_depth_frag.glsl
engines/eevee_next/shaders/eevee_surf_forward_frag.glsl
engines/eevee_next/shaders/eevee_surf_lib.glsl
engines/eevee_next/shaders/eevee_surf_shadow_frag.glsl
engines/eevee_next/shaders/eevee_surf_world_frag.glsl
engines/eevee_next/shaders/eevee_velocity_lib.glsl
@ -797,6 +819,7 @@ if(WITH_GTESTS)
set(TEST_SRC
tests/draw_pass_test.cc
tests/draw_testing.cc
tests/eevee_test.cc
tests/shaders_test.cc
tests/draw_testing.hh

View File

@ -507,7 +507,7 @@ void EEVEE_motion_blur_cache_finish(EEVEE_Data *vedata)
if (!GPU_batch_vertbuf_has(batch, vbo)) {
/* Currently, the code assumes that all objects that share the same mesh in the
* current frame also share the same mesh on other frames. */
GPU_batch_vertbuf_add_ex(batch, vbo, false);
GPU_batch_vertbuf_add(batch, vbo, false);
}
}
}

View File

@ -135,8 +135,9 @@ void Camera::sync()
#endif
}
else if (inst_.drw_view) {
data.clip_near = DRW_view_near_distance_get(inst_.drw_view);
data.clip_far = DRW_view_far_distance_get(inst_.drw_view);
/* \note: Follow camera parameters where distances are positive in front of the camera. */
data.clip_near = -DRW_view_near_distance_get(inst_.drw_view);
data.clip_far = -DRW_view_far_distance_get(inst_.drw_view);
data.fisheye_fov = data.fisheye_lens = -1.0f;
data.equirect_bias = float2(0.0f);
data.equirect_scale = float2(0.0f);
@ -144,6 +145,57 @@ void Camera::sync()
data_.initialized = true;
data_.push_update();
update_bounds();
}
void Camera::update_bounds()
{
float left, right, bottom, top, near, far;
projmat_dimensions(data_.winmat.ptr(), &left, &right, &bottom, &top, &near, &far);
BoundBox bbox;
bbox.vec[0][2] = bbox.vec[3][2] = bbox.vec[7][2] = bbox.vec[4][2] = -near;
bbox.vec[0][0] = bbox.vec[3][0] = left;
bbox.vec[4][0] = bbox.vec[7][0] = right;
bbox.vec[0][1] = bbox.vec[4][1] = bottom;
bbox.vec[7][1] = bbox.vec[3][1] = top;
/* Get the coordinates of the far plane. */
if (!this->is_orthographic()) {
float sca_far = far / near;
left *= sca_far;
right *= sca_far;
bottom *= sca_far;
top *= sca_far;
}
bbox.vec[1][2] = bbox.vec[2][2] = bbox.vec[6][2] = bbox.vec[5][2] = -far;
bbox.vec[1][0] = bbox.vec[2][0] = left;
bbox.vec[6][0] = bbox.vec[5][0] = right;
bbox.vec[1][1] = bbox.vec[5][1] = bottom;
bbox.vec[2][1] = bbox.vec[6][1] = top;
bound_sphere.center = {0.0f, 0.0f, 0.0f};
bound_sphere.radius = 0.0f;
for (auto i : IndexRange(8)) {
bound_sphere.center += float3(bbox.vec[i]);
}
bound_sphere.center /= 8.0f;
for (auto i : IndexRange(8)) {
float dist_sqr = math::distance_squared(bound_sphere.center, float3(bbox.vec[i]));
bound_sphere.radius = max_ff(bound_sphere.radius, dist_sqr);
}
bound_sphere.radius = sqrtf(bound_sphere.radius);
/* Transform into world space. */
bound_sphere.center = math::transform_point(data_.viewinv, bound_sphere.center);
/* Compute diagonal length. */
float2 p0 = float2(bbox.vec[0]) / (this->is_perspective() ? bbox.vec[0][2] : 1.0f);
float2 p1 = float2(bbox.vec[7]) / (this->is_perspective() ? bbox.vec[7][2] : 1.0f);
data_.screen_diagonal_length = math::distance(p0, p1);
}
/** \} */

View File

@ -94,6 +94,11 @@ class Camera {
CameraDataBuf data_;
struct {
float3 center;
float radius;
} bound_sphere;
public:
Camera(Instance &inst) : inst_(inst){};
~Camera(){};
@ -133,6 +138,17 @@ class Camera {
{
return data_.viewinv.z_axis();
}
const float3 &bound_center() const
{
return bound_sphere.center;
}
const float &bound_radius() const
{
return bound_sphere.radius;
}
private:
void update_bounds();
};
/** \} */

View File

@ -32,15 +32,29 @@
* SHADOW_TILEMAP_RES max is 32 because of the shared bitmaps used for LOD tagging.
* It is also limited by the maximum thread group size (1024).
*/
#define SHADOW_TILEMAP_RES 16
#define SHADOW_TILEMAP_LOD 4 /* LOG2(SHADOW_TILEMAP_RES) */
#define SHADOW_TILEMAP_RES 32
#define SHADOW_TILEMAP_LOD 5 /* LOG2(SHADOW_TILEMAP_RES) */
#define SHADOW_TILEMAP_LOD0_LEN ((SHADOW_TILEMAP_RES / 1) * (SHADOW_TILEMAP_RES / 1))
#define SHADOW_TILEMAP_LOD1_LEN ((SHADOW_TILEMAP_RES / 2) * (SHADOW_TILEMAP_RES / 2))
#define SHADOW_TILEMAP_LOD2_LEN ((SHADOW_TILEMAP_RES / 4) * (SHADOW_TILEMAP_RES / 4))
#define SHADOW_TILEMAP_LOD3_LEN ((SHADOW_TILEMAP_RES / 8) * (SHADOW_TILEMAP_RES / 8))
#define SHADOW_TILEMAP_LOD4_LEN ((SHADOW_TILEMAP_RES / 16) * (SHADOW_TILEMAP_RES / 16))
#define SHADOW_TILEMAP_LOD5_LEN ((SHADOW_TILEMAP_RES / 32) * (SHADOW_TILEMAP_RES / 32))
#define SHADOW_TILEMAP_PER_ROW 64
#define SHADOW_PAGE_COPY_GROUP_SIZE 32
#define SHADOW_DEPTH_SCAN_GROUP_SIZE 32
#define SHADOW_TILEDATA_PER_TILEMAP \
(SHADOW_TILEMAP_LOD0_LEN + SHADOW_TILEMAP_LOD1_LEN + SHADOW_TILEMAP_LOD2_LEN + \
SHADOW_TILEMAP_LOD3_LEN + SHADOW_TILEMAP_LOD4_LEN + SHADOW_TILEMAP_LOD5_LEN)
#define SHADOW_PAGE_CLEAR_GROUP_SIZE 32
#define SHADOW_PAGE_RES 256
#define SHADOW_DEPTH_SCAN_GROUP_SIZE 8
#define SHADOW_AABB_TAG_GROUP_SIZE 64
#define SHADOW_MAX_TILEMAP 4096
#define SHADOW_MAX_TILE (SHADOW_MAX_TILEMAP * SHADOW_TILEDATA_PER_TILEMAP)
#define SHADOW_MAX_PAGE 4096
#define SHADOW_PAGE_PER_ROW 64
#define SHADOW_ATLAS_SLOT 5
#define SHADOW_BOUNDS_GROUP_SIZE 64
#define SHADOW_VIEW_MAX 64 /* Must match DRW_VIEW_MAX. */
/* Ray-tracing. */
#define RAYTRACE_GROUP_SIZE 16
@ -74,6 +88,11 @@
/* Resource bindings. */
/* Texture. */
#define SHADOW_TILEMAPS_TEX_SLOT 12
/* Only during surface shading. */
#define SHADOW_ATLAS_TEX_SLOT 13
/* Only during shadow rendering. */
#define SHADOW_RENDER_MAP_SLOT 13
#define RBUFS_UTILITY_TEX_SLOT 14
/* Images. */
@ -99,7 +118,10 @@
#define LIGHT_BUF_SLOT 1
#define LIGHT_ZBIN_BUF_SLOT 2
#define LIGHT_TILE_BUF_SLOT 3
/* Only during surface shading. */
#define RBUFS_AOV_BUF_SLOT 5
/* Only during shadow rendering. */
#define SHADOW_PAGE_INFO_SLOT 5
#define SAMPLING_BUF_SLOT 6
#define CRYPTOMATTE_BUF_SLOT 7

View File

@ -67,6 +67,7 @@ void Instance::init(const int2 &output_res,
film.init(output_res, output_rect);
velocity.init();
depth_of_field.init();
shadows.init();
motion_blur.init();
main_view.init();
}
@ -102,6 +103,7 @@ void Instance::begin_sync()
materials.begin_sync();
velocity.begin_sync(); /* NOTE: Also syncs camera. */
lights.begin_sync();
shadows.begin_sync();
cryptomatte.begin_sync();
gpencil_engine_enabled = false;
@ -197,6 +199,7 @@ void Instance::object_sync_render(void *instance_,
void Instance::end_sync()
{
velocity.end_sync();
shadows.end_sync(); /** \note: Needs to be before lights. */
lights.end_sync();
sampling.end_sync();
film.end_sync();

View File

@ -27,6 +27,7 @@
#include "eevee_renderbuffers.hh"
#include "eevee_sampling.hh"
#include "eevee_shader.hh"
#include "eevee_shadow.hh"
#include "eevee_sync.hh"
#include "eevee_view.hh"
#include "eevee_world.hh"
@ -46,6 +47,7 @@ class Instance {
SyncModule sync;
MaterialModule materials;
PipelineModule pipelines;
ShadowModule shadows;
LightModule lights;
VelocityModule velocity;
MotionBlurModule motion_blur;
@ -89,6 +91,7 @@ class Instance {
sync(*this),
materials(*this),
pipelines(*this),
shadows(*this),
lights(*this),
velocity(*this),
motion_blur(*this),

View File

@ -41,7 +41,7 @@ static eLightType to_light_type(short blender_light_type, short blender_area_typ
/** \name Light Object
* \{ */
void Light::sync(/* ShadowModule &shadows , */ const Object *ob, float threshold)
void Light::sync(ShadowModule &shadows, const Object *ob, float threshold)
{
const ::Light *la = (const ::Light *)ob->data;
float scale[3];
@ -75,67 +75,49 @@ void Light::sync(/* ShadowModule &shadows , */ const Object *ob, float threshold
this->volume_power = la->volume_fac * point_power;
eLightType new_type = to_light_type(la->type, la->area_shape);
if (this->type != new_type) {
/* shadow_discard_safe(shadows); */
this->type = new_type;
if (assign_if_different(this->type, new_type)) {
shadow_discard_safe(shadows);
}
#if 0
if (la->mode & LA_SHADOW) {
if (la->type == LA_SUN) {
if (this->shadow_id == LIGHT_NO_SHADOW) {
this->shadow_id = shadows.directionals.alloc();
}
ShadowDirectional &shadow = shadows.directionals[this->shadow_id];
shadow.sync(this->object_mat, la->bias * 0.05f, 1.0f);
shadow_ensure(shadows);
if (is_sun_light(this->type)) {
this->directional->sync(this->object_mat, 1.0f);
}
else {
float cone_aperture = DEG2RAD(360.0);
if (la->type == LA_SPOT) {
cone_aperture = min_ff(DEG2RAD(179.9), la->spotsize);
}
else if (la->type == LA_AREA) {
cone_aperture = DEG2RAD(179.9);
}
if (this->shadow_id == LIGHT_NO_SHADOW) {
this->shadow_id = shadows.punctuals.alloc();
}
ShadowPunctual &shadow = shadows.punctuals[this->shadow_id];
shadow.sync(this->type,
this->object_mat,
cone_aperture,
la->clipsta,
this->influence_radius_max,
la->bias * 0.05f);
this->punctual->sync(
this->type, this->object_mat, la->spotsize, la->clipsta, this->influence_radius_max);
}
}
else {
shadow_discard_safe(shadows);
}
#endif
this->initialized = true;
}
#if 0
void Light::shadow_discard_safe(ShadowModule &shadows)
{
if (shadow_id != LIGHT_NO_SHADOW) {
if (this->type != LIGHT_SUN) {
shadows.punctuals.free(shadow_id);
}
else {
shadows.directionals.free(shadow_id);
}
shadow_id = LIGHT_NO_SHADOW;
if (this->directional != nullptr) {
shadows.directional_pool.destruct(*directional);
this->directional = nullptr;
}
if (this->punctual != nullptr) {
shadows.punctual_pool.destruct(*punctual);
this->punctual = nullptr;
}
}
void Light::shadow_ensure(ShadowModule &shadows)
{
if (is_sun_light(this->type) && this->directional == nullptr) {
this->directional = &shadows.directional_pool.construct(shadows);
}
else if (this->punctual == nullptr) {
this->punctual = &shadows.punctual_pool.construct(shadows);
}
}
#endif
/* Returns attenuation radius inverted & squared for easy bound checking inside the shader. */
float Light::attenuation_radius_get(const ::Light *la, float light_threshold, float light_power)
{
if (la->type == LA_SUN) {
@ -265,6 +247,14 @@ void Light::debug_draw()
/** \name LightModule
* \{ */
LightModule::~LightModule()
{
/* WATCH: Destructor order. Expect shadow module to be destructed later. */
for (Light &light : light_map_.values()) {
light.shadow_discard_safe(inst_.shadows);
}
};
void LightModule::begin_sync()
{
use_scene_lights_ = inst_.use_scene_lights();
@ -286,61 +276,44 @@ void LightModule::sync_light(const Object *ob, ObjectHandle &handle)
Light &light = light_map_.lookup_or_add_default(handle.object_key);
light.used = true;
if (handle.recalc != 0 || !light.initialized) {
light.sync(/* inst_.shadows, */ ob, light_threshold_);
light.initialized = true;
light.sync(inst_.shadows, ob, light_threshold_);
}
sun_lights_len_ += int(light.type == LIGHT_SUN);
local_lights_len_ += int(light.type != LIGHT_SUN);
sun_lights_len_ += int(is_sun_light(light.type));
local_lights_len_ += int(!is_sun_light(light.type));
}
void LightModule::end_sync()
{
// ShadowModule &shadows = inst_.shadows;
/* NOTE: We resize this buffer before removing deleted lights. */
int lights_allocated = ceil_to_multiple_u(max_ii(light_map_.size(), 1), LIGHT_CHUNK);
light_buf_.resize(lights_allocated);
/* Track light deletion. */
Vector<ObjectKey, 0> deleted_keys;
/* Indices inside GPU data array. */
int sun_lights_idx = 0;
int local_lights_idx = sun_lights_len_;
/* Fill GPU data with scene data. */
for (auto item : light_map_.items()) {
Light &light = item.value;
auto it_end = light_map_.items().end();
for (auto it = light_map_.items().begin(); it != it_end; ++it) {
Light &light = (*it).value;
if (!light.used) {
/* Deleted light. */
deleted_keys.append(item.key);
// light.shadow_discard_safe(shadows);
light_map_.remove(it);
continue;
}
int dst_idx = (light.type == LIGHT_SUN) ? sun_lights_idx++ : local_lights_idx++;
int dst_idx = is_sun_light(light.type) ? sun_lights_idx++ : local_lights_idx++;
/* Put all light data into global data SSBO. */
light_buf_[dst_idx] = light;
#if 0
if (light.shadow_id != LIGHT_NO_SHADOW) {
if (light.type == LIGHT_SUN) {
light_buf_[dst_idx].shadow_data = shadows.directionals[light.shadow_id];
}
else {
light_buf_[dst_idx].shadow_data = shadows.punctuals[light.shadow_id];
}
}
#endif
/* Untag for next sync. */
light.used = false;
}
/* This scene data buffer is then immutable after this point. */
light_buf_.push_update();
for (auto &key : deleted_keys) {
light_map_.remove(key);
}
/* Update sampling on deletion or un-hiding (use_scene_lights). */
if (assign_if_different(light_map_size_, light_map_.size())) {
inst_.sampling.reset();

View File

@ -34,25 +34,52 @@
namespace blender::eevee {
class Instance;
class ShadowModule;
/* -------------------------------------------------------------------- */
/** \name Light Object
* \{ */
struct Light : public LightData {
struct Light : public LightData, NonCopyable {
public:
bool initialized = false;
bool used = false;
/** Pointers to source Shadow. Type depends on `LightData::type`. */
ShadowDirectional *directional = nullptr;
ShadowPunctual *punctual = nullptr;
public:
Light()
{
shadow_id = LIGHT_NO_SHADOW;
/* Avoid valgrind warning. */
this->type = LIGHT_SUN;
}
void sync(/* ShadowModule &shadows, */ const Object *ob, float threshold);
/* Only used for debugging. */
#ifndef NDEBUG
Light(Light &&other)
{
*static_cast<LightData *>(this) = other;
this->initialized = other.initialized;
this->used = other.used;
this->directional = other.directional;
this->punctual = other.punctual;
other.directional = nullptr;
other.punctual = nullptr;
}
// void shadow_discard_safe(ShadowModule &shadows);
~Light()
{
BLI_assert(directional == nullptr);
BLI_assert(punctual == nullptr);
}
#endif
void sync(ShadowModule &shadows, const Object *ob, float threshold);
void shadow_ensure(ShadowModule &shadows);
void shadow_discard_safe(ShadowModule &shadows);
void debug_draw();
@ -73,7 +100,7 @@ struct Light : public LightData {
* The light module manages light data buffers and light culling system.
*/
class LightModule {
// friend ShadowModule;
friend ShadowModule;
private:
/* Keep tile count reasonable for memory usage and 2D culling performance. */
@ -125,7 +152,7 @@ class LightModule {
public:
LightModule(Instance &inst) : inst_(inst){};
~LightModule(){};
~LightModule();
void begin_sync();
void sync_light(const Object *ob, ObjectHandle &handle);
@ -138,21 +165,8 @@ class LightModule {
void debug_draw(View &view, GPUFrameBuffer *view_fb);
void bind_resources(DRWShadingGroup *grp)
{
DRW_shgroup_storage_block_ref(grp, "light_buf", &culling_light_buf_);
DRW_shgroup_storage_block_ref(grp, "light_cull_buf", &culling_data_buf_);
DRW_shgroup_storage_block_ref(grp, "light_zbin_buf", &culling_zbin_buf_);
DRW_shgroup_storage_block_ref(grp, "light_tile_buf", &culling_tile_buf_);
#if 0
DRW_shgroup_uniform_texture(grp, "shadow_atlas_tx", inst_.shadows.atlas_tx_get());
DRW_shgroup_uniform_texture(grp, "shadow_tilemaps_tx", inst_.shadows.tilemap_tx_get());
#endif
}
template<typename T> void bind_resources(draw::detail::PassBase<T> *pass)
{
/* Storage Buf. */
pass->bind_ssbo(LIGHT_CULL_BUF_SLOT, &culling_data_buf_);
pass->bind_ssbo(LIGHT_BUF_SLOT, &culling_light_buf_);
pass->bind_ssbo(LIGHT_ZBIN_BUF_SLOT, &culling_zbin_buf_);

View File

@ -300,7 +300,9 @@ MaterialArray &MaterialModule::material_array_get(Object *ob, bool has_motion)
for (auto i : IndexRange(materials_len)) {
::Material *blender_mat = material_from_slot(ob, i);
Material &mat = material_sync(ob, blender_mat, to_material_geometry(ob), has_motion);
material_array_.materials.append(&mat);
/* \note: Perform a whole copy since next material_sync() can move the Material memory location
* (i.e: because of its container growing) */
material_array_.materials.append(mat);
material_array_.gpu_materials.append(mat.shading.gpumat);
}
return material_array_;

View File

@ -213,7 +213,7 @@ struct Material {
};
struct MaterialArray {
Vector<Material *> materials;
Vector<Material> materials;
Vector<GPUMaterial *> gpu_materials;
};

View File

@ -46,6 +46,8 @@ void WorldPipeline::sync(GPUMaterial *gpumat)
world_ps_.bind_image("rp_emission_img", &rbufs.emission_tx);
world_ps_.bind_image("rp_cryptomatte_img", &rbufs.cryptomatte_tx);
world_ps_.bind_ubo(CAMERA_BUF_SLOT, inst_.camera.ubo_get());
world_ps_.draw(DRW_cache_fullscreen_quad_get(), handle);
/* To allow opaque pass rendering over it. */
world_ps_.barrier(GPU_BARRIER_SHADER_IMAGE_ACCESS);
@ -58,6 +60,39 @@ void WorldPipeline::render(View &view)
/** \} */
/* -------------------------------------------------------------------- */
/** \name Shadow Pipeline
*
* \{ */
void ShadowPipeline::sync()
{
surface_ps_.init();
/* TODO(fclem): Add state for rendering to empty framebuffer without depth test.
* For now this is only here for avoiding the rasterizer discard state. */
surface_ps_.state_set(DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
surface_ps_.bind_texture(RBUFS_UTILITY_TEX_SLOT, inst_.pipelines.utility_tx);
surface_ps_.bind_texture(SHADOW_RENDER_MAP_SLOT, &inst_.shadows.render_map_tx_);
surface_ps_.bind_image(SHADOW_ATLAS_SLOT, &inst_.shadows.atlas_tx_);
surface_ps_.bind_ubo(CAMERA_BUF_SLOT, inst_.camera.ubo_get());
surface_ps_.bind_ssbo(SHADOW_PAGE_INFO_SLOT, &inst_.shadows.pages_infos_data_);
inst_.sampling.bind_resources(&surface_ps_);
surface_ps_.framebuffer_set(&inst_.shadows.render_fb_);
}
PassMain::Sub *ShadowPipeline::surface_material_add(GPUMaterial *gpumat)
{
return &surface_ps_.sub(GPU_material_get_name(gpumat));
}
void ShadowPipeline::render(View &view)
{
inst_.manager->submit(surface_ps_, view);
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Forward Pass
*
@ -123,6 +158,7 @@ void ForwardPipeline::sync()
opaque_ps_.bind_ubo(CAMERA_BUF_SLOT, inst_.camera.ubo_get());
inst_.lights.bind_resources(&opaque_ps_);
inst_.shadows.bind_resources(&opaque_ps_);
inst_.sampling.bind_resources(&opaque_ps_);
inst_.cryptomatte.bind_resources(&opaque_ps_);
}
@ -145,9 +181,10 @@ void ForwardPipeline::sync()
/* Textures. */
sub.bind_texture(RBUFS_UTILITY_TEX_SLOT, inst_.pipelines.utility_tx);
/* Uniform Buf. */
opaque_ps_.bind_ubo(CAMERA_BUF_SLOT, inst_.camera.ubo_get());
sub.bind_ubo(CAMERA_BUF_SLOT, inst_.camera.ubo_get());
inst_.lights.bind_resources(&sub);
inst_.shadows.bind_resources(&sub);
inst_.sampling.bind_resources(&sub);
}
}
@ -225,7 +262,7 @@ void ForwardPipeline::render(View &view,
// inst_.hiz_buffer.update();
// }
// inst_.shadows.set_view(view, depth_tx);
inst_.shadows.set_view(view);
GPU_framebuffer_bind(combined_fb);
inst_.manager->submit(opaque_ps_, view);

View File

@ -43,6 +43,28 @@ class WorldPipeline {
/** \} */
/* -------------------------------------------------------------------- */
/** \name Shadow Pass
*
* \{ */
class ShadowPipeline {
private:
Instance &inst_;
PassMain surface_ps_ = {"Shadow.Surface"};
public:
ShadowPipeline(Instance &inst) : inst_(inst){};
PassMain::Sub *surface_material_add(GPUMaterial *gpumat);
void sync();
void render(View &view);
};
/** \} */
/* -------------------------------------------------------------------- */
/** \name Forward Pass
*
@ -177,19 +199,19 @@ class PipelineModule {
WorldPipeline world;
// DeferredPipeline deferred;
ForwardPipeline forward;
// ShadowPipeline shadow;
ShadowPipeline shadow;
// VelocityPipeline velocity;
UtilityTexture utility_tx;
public:
PipelineModule(Instance &inst) : world(inst), forward(inst){};
PipelineModule(Instance &inst) : world(inst), forward(inst), shadow(inst){};
void sync()
{
// deferred.sync();
forward.sync();
// shadow.sync();
shadow.sync();
// velocity.sync();
}
@ -227,8 +249,7 @@ class PipelineModule {
/* TODO(fclem) volume pass. */
return nullptr;
case MAT_PIPE_SHADOW:
// return shadow.material_add(blender_mat, gpumat);
break;
return shadow.surface_material_add(gpumat);
}
return nullptr;
}

Some files were not shown because too many files have changed in this diff Show More