Fix #100957: Dyntopo shows false positive data loss warnings #104535

Closed
Hans Goudey wants to merge 2 commits from HooglyBoogly:fix-dyntopo-error-false-positive into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
304 changed files with 8677 additions and 2487 deletions
Showing only changes of commit 3e3533e936 - 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

@ -1,41 +1,18 @@
This folder contains several scripts to smoothen the Blender LTS releases.
This folder contains a script to generate release notes and download URLs
for Blender LTS releases.
create_download_urls.py
=======================
Ensure required Python modules are installed before running:
This python script is used to generate the download urls which we can
copy-paste directly into the CMS of www.blender.org.
pip3 install -r ./requirements.txt
Usage: create_download_urls.py --version 2.83.7
Then run for example:
Arguments:
--version VERSION Version string in the form of {major}.{minor}.{build}
(eg 2.83.7)
./create_release_notes.py --version 3.3.2 --format=html
The resulting html will be printed to the console.
Available arguments:
create_release_notes.py
=======================
This python script is used to generate the release notes which we can
copy-paste directly into the CMS of www.blender.org and stores.
Usage: ./create_release_notes.py --task=T77348 --version=2.83.7
Arguments:
--version VERSION Version string in the form of {major}.{minor}.{build}
(e.g. 2.83.7)
--task TASK Phabricator ticket that is contains the release notes
information (e.g. T77348)
--format FORMAT Format the result in `text`, `steam`, `wiki` or `html`
Requirements
============
* Python 3.8 or later
* Python phabricator client version 0.7.0
https://pypi.org/project/phabricator/
For convenience the python modules can be installed using pip
pip3 install -r ./requirements.txt
--version VERSION Version string in the form of {major}.{minor}.{build}
(e.g. 3.3.2)
--issue ISSUE Gitea issue that is contains the release notes
information (e.g. #77348)
--format FORMAT Format the result in `text`, `steam`, `wiki` or `html`

View File

@ -1,169 +1,46 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-2.0-or-later
#!/usr/bin/env python3
import argparse
import phabricator
import lts_issue
import lts_download
DESCRIPTION = ("This python script is used to generate the release notes "
"which we can copy-paste directly into the CMS of "
DESCRIPTION = ("This python script is used to generate the release notes and "
"download URLs which we can copy-paste directly into the CMS of "
"www.blender.org and stores.")
USAGE = "./create_release_notes.py --task=T77348 --version=2.83.7"
# Parse arguments
parser = argparse.ArgumentParser(description=DESCRIPTION)
parser.add_argument(
"--version",
required=True,
help="Version string in the form of {major}.{minor}.{patch} (e.g. 3.3.2)")
parser.add_argument(
"--issue",
help="Task that is contains the release notes information (e.g. #77348)")
parser.add_argument(
"--format",
help="Format the result in `text`, `steam`, `wiki` or `html`",
default="text")
args = parser.parse_args()
class ReleaseLogLine:
"""
Class containing the information of a single line of the release log
# Determine issue number
version = args.version
issue = args.issue
if not issue:
if version.startswith("2.83."):
issue = "#77348"
elif version.startswith("2.93."):
issue = "#88449"
elif version.startswith("3.3."):
issue = "#100749"
else:
raise ValueError("Specify --issue or update script to include issue number for this version")
Instance attributes:
# Print
if args.format == "html":
lts_download.print_urls(version=version)
print("")
* line: (str) the original line used to create this log line
* task_id: (int or None) the extracted task id associated with this log
line. Can be None if the log line isn't associated with a task.
* commit_id: (str or None) the extracted commit id associated with this log
line. Only filled when no `task_id` could be found.
* ref: (str) `task_id` or `commit_id` of this line, including `T` for tasks
or `D` for diffs.
* title: (str) title of this log line. When constructed this attribute is
an empty string. The called needs to retrieve the title from the
backend.
* url: (str) url of the ticket task or commit.
"""
def __init__(self, line: str):
self.line = line
items = line.split("|")
self.task_id = None
self.commit_id = None
try:
task_id = int(items[1].strip()[1:])
self.task_id = task_id
self.ref = f"T{self.task_id}"
except ValueError:
# no task
commit_string = items[3].strip()
commits = commit_string.split(",")
commit_id = commits[0]
commit_id = commit_id.replace("{", "").replace("}", "")
if not commit_id.startswith("rB"):
commit_id = f"rB{commit_id}"
self.commit_id = commit_id
self.ref = f"{self.commit_id}"
self.title = ""
self.url = f"https://developer.blender.org/{self.ref}"
def __format_as_html(self) -> str:
return f" <li>{self.title} [<a href=\"{self.url}\">{self.ref}</a>]</li>"
def __format_as_text(self) -> str:
return f"* {self.title} [{self.ref}]"
def __format_as_steam(self) -> str:
return f"* {self.title} ([url={self.url}]{self.ref}[/url])"
def __format_as_wiki(self) -> str:
if self.task_id:
return f"* {self.title} [{{{{BugReport|{self.task_id}}}}}]"
else:
return f"* {self.title} [{{{{GitCommit|{self.commit_id[2:]}}}}}]"
def format(self, format: str) -> str:
"""
Format this line
:attr format: the desired format. Possible values are 'text', 'steam' or 'html'
:type string:
"""
if format == 'html':
return self.__format_as_html()
elif format == 'steam':
return self.__format_as_steam()
elif format == 'wiki':
return self.__format_as_wiki()
else:
return self.__format_as_text()
def format_title(title: str) -> str:
title = title.strip()
if not title.endswith("."):
title = title + "."
return title
def extract_release_notes(version: str, task_id: int):
"""
Extract all release notes logs
# Process
1. Retrieval of description of the given `task_id`.
2. Find rows for the given `version` and convert to `ReleaseLogLine`.
3. based on the associated task or commit retrieves the title of the log
line.
"""
phab = phabricator.Phabricator()
phab.update_interfaces()
task = phab.maniphest.info(task_id=task_id)
description = task["description"]
lines = description.split("\n")
start_index = lines.index(f"## Blender {version} ##")
lines = lines[start_index + 1:]
for line in lines:
if not line.strip():
continue
if line.startswith("| **Report**"):
continue
if line.startswith("## Blender"):
break
log_line = ReleaseLogLine(line)
if log_line.task_id:
issue_task = phab.maniphest.info(task_id=log_line.task_id)
log_line.title = format_title(issue_task.title)
yield log_line
elif log_line.commit_id:
commits = phab.diffusion.commit.search(constraints={"identifiers": [log_line.commit_id]})
commit = commits.data[0]
commit_message = commit['fields']['message']
commit_title = commit_message.split("\n")[0]
log_line.title = format_title(commit_title)
yield log_line
def print_release_notes(version: str, format: str, task_id: int):
"""
Generate and print the release notes to the console.
"""
if format == 'html':
print("<ul>")
if format == 'steam':
print("[ul]")
for log_item in extract_release_notes(version=version, task_id=task_id):
print(log_item.format(format=format))
if format == 'html':
print("</ul>")
if format == 'steam':
print("[/ul]")
if __name__ == "__main__":
parser = argparse.ArgumentParser(description=DESCRIPTION, usage=USAGE)
parser.add_argument(
"--version",
required=True,
help="Version string in the form of {major}.{minor}.{build} (e.g. 2.83.7)")
parser.add_argument(
"--task",
required=True,
help="Phabricator ticket that is contains the release notes information (e.g. T77348)")
parser.add_argument(
"--format",
help="Format the result in `text`, `steam`, `wiki` or `html`",
default="text")
args = parser.parse_args()
print_release_notes(version=args.version, format=args.format, task_id=int(args.task[1:]))
lts_issue.print_notes(version=version, format=args.format, issue=issue)

View File

@ -1,14 +1,9 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-2.0-or-later
import argparse
import datetime
DESCRIPTION = ("This python script is used to generate the download urls "
"which we can copy-paste directly into the CMS of "
"www.blender.org")
USAGE = "create_download_urls --version=2.83.7"
# Used date format: "September 30, 2020"
DATE_FORMAT = "%B %d, %Y"
@ -62,19 +57,8 @@ def generate_html(version: Version) -> str:
return "\n".join(lines)
def print_download_urls(version: Version):
def print_urls(version: str):
"""
Generate the download urls and print them to the console.
"""
print(generate_html(version))
if __name__ == "__main__":
parser = argparse.ArgumentParser(description=DESCRIPTION, usage=USAGE)
parser.add_argument("--version",
required=True,
help=("Version string in the form of {major}.{minor}."
"{build} (eg 2.83.7)"))
args = parser.parse_args()
print_download_urls(version=Version(args.version))
print(generate_html(Version(version)))

169
release/lts/lts_issue.py Normal file
View File

@ -0,0 +1,169 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-2.0-or-later
import requests
class ReleaseLogLine:
"""
Class containing the information of a single line of the release log
Instance attributes:
* line: (str) the original line used to create this log line
* issue_id: (int or None) the extracted issue id associated with this log
line. Can be None if the log line isn't associated with a issue.
* commit_id: (str or None) the extracted commit id associated with this log
line. Only filled when no `issue_id` could be found.
* ref: (str) `issue_id` or `commit_id` of this line, including `T` for issues
or `D` for diffs.
* title: (str) title of this log line. When constructed this attribute is
an empty string. The called needs to retrieve the title from the
backend.
* url: (str) url of the ticket issue or commit.
"""
def __init__(self, line: str):
self.line = line
items = line.split("|")
self.issue_id = None
self.issue_repo = None
self.commit_id = None
self.commit_repo = None
base_url = "https://projects.blender.org"
try:
issue_tokens = items[1].strip().split("#")
if len(issue_tokens[0]) > 0:
self.issue_repo = issue_tokens[0]
self.issue_id = issue_tokens[1]
else:
self.issue_repo = "blender/blender"
self.issue_id = issue_tokens[1]
self.ref = f"#{self.issue_id}"
self.url = f"{base_url}/{self.issue_repo}/issues/{self.issue_id}"
except IndexError:
# no issue
commit_string = items[3].strip()
commit_string = commit_string.split(",")[0]
commit_string = commit_string.split("]")[0]
commit_string = commit_string.replace("[", "")
commit_tokens = commit_string.split("@")
if len(commit_tokens) > 1:
self.commit_repo = commit_tokens[0]
self.commit_id = commit_tokens[1]
else:
self.commit_repo = "blender/blender"
self.commit_id = commit_tokens[0]
self.ref = f"{self.commit_id}"
self.url = f"{base_url}/{self.commit_repo}/commit/{self.commit_id}"
self.title = ""
def __format_as_html(self) -> str:
return f" <li>{self.title} [<a href=\"{self.url}\">{self.ref}</a>]</li>"
def __format_as_text(self) -> str:
return f"* {self.title} [{self.ref}]"
def __format_as_steam(self) -> str:
return f"* {self.title} ([url={self.url}]{self.ref}[/url])"
def __format_as_wiki(self) -> str:
if self.issue_id:
return f"* {self.title} [{{{{BugReport|{self.issue_id}}}}}]"
else:
return f"* {self.title} [{{{{GitCommit|{self.commit_id[2:]}}}}}]"
def format(self, format: str) -> str:
"""
Format this line
:attr format: the desired format. Possible values are 'text', 'steam' or 'html'
:type string:
"""
if format == 'html':
return self.__format_as_html()
elif format == 'steam':
return self.__format_as_steam()
elif format == 'wiki':
return self.__format_as_wiki()
else:
return self.__format_as_text()
def format_title(title: str) -> str:
title = title.strip()
if not title.endswith("."):
title = title + "."
return title
def extract_release_notes(version: str, issue: str):
"""
Extract all release notes logs
# Process
1. Retrieval of description of the given `issue_id`.
2. Find rows for the given `version` and convert to `ReleaseLogLine`.
3. based on the associated issue or commit retrieves the title of the log
line.
"""
base_url = "https://projects.blender.org/api/v1/repos"
issues_url = base_url + "/blender/blender/issues/"
headers = {'accept': 'application/json'}
response = requests.get(issues_url + issue[1:], headers=headers)
description = response.json()["body"]
lines = description.split("\n")
start_index = lines.index(f"## Blender {version}")
lines = lines[start_index + 1:]
for line in lines:
if not line.strip():
continue
if line.startswith("| **Report**"):
continue
if line.startswith("## Blender"):
break
if line.find("| -- |") != -1:
continue
log_line = ReleaseLogLine(line)
if log_line.issue_id:
issue_url = f"{base_url}/{log_line.issue_repo}/issues/{log_line.issue_id}"
response = requests.get(issue_url, headers=headers)
if response.status_code != 200:
raise ValueError("Issue not found: " + str(log_line.issue_id))
log_line.title = format_title(response.json()["title"])
yield log_line
elif log_line.commit_id:
commit_url = f"{base_url}/{log_line.commit_repo}/git/commits/{log_line.commit_id}"
response = requests.get(commit_url, headers=headers)
if response.status_code != 200:
raise ValueError("Commit not found: " + log_line.commit_id)
commit_message = response.json()['commit']['message']
commit_title = commit_message.split("\n")[0]
log_line.title = format_title(commit_title)
yield log_line
def print_notes(version: str, format: str, issue: str):
"""
Generate and print the release notes to the console.
"""
if format == 'html':
print("<ul>")
if format == 'steam':
print("[ul]")
for log_item in extract_release_notes(version=version, issue=issue):
print(log_item.format(format=format))
if format == 'html':
print("</ul>")
if format == 'steam':
print("[/ul]")

View File

@ -1 +1 @@
phabricator==0.7.0
requests

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

@ -2267,7 +2267,7 @@ class ExperimentalPanel:
bl_region_type = 'WINDOW'
bl_context = "experimental"
url_prefix = "https://developer.blender.org/"
url_prefix = "https://projects.blender.org/"
@classmethod
def poll(cls, _context):
@ -2308,8 +2308,8 @@ class USERPREF_PT_experimental_virtual_reality(ExperimentalPanel, Panel):
def draw(self, context):
self._draw_items(
context, (
({"property": "use_virtual_reality_scene_inspection"}, "T71347"),
({"property": "use_virtual_reality_immersive_drawing"}, "T71348"),
({"property": "use_virtual_reality_scene_inspection"}, ("blender/blender/issues/71347", "#71347")),
({"property": "use_virtual_reality_immersive_drawing"}, ("blender/blender/issues/71348", "#71348")),
),
)
"""
@ -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"}, "T82877"),
({"property": "use_extended_asset_browser"}, ("project/view/130/", "Project Page")),
({"property": "use_override_templates"}, ("T73318", "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):
@ -2334,12 +2339,12 @@ class USERPREF_PT_experimental_prototypes(ExperimentalPanel, Panel):
def draw(self, context):
self._draw_items(
context, (
({"property": "use_new_curves_tools"}, "T68981"),
({"property": "use_new_point_cloud_type"}, "T75717"),
({"property": "use_sculpt_texture_paint"}, "T96225"),
({"property": "use_full_frame_compositor"}, "T88150"),
({"property": "enable_eevee_next"}, "T93220"),
({"property": "enable_workbench_next"}, "T101619"),
({"property": "use_new_curves_tools"}, ("blender/blender/issues/68981", "#68981")),
({"property": "use_new_point_cloud_type"}, ("blender/blender/issues/75717", "#75717")),
({"property": "use_sculpt_texture_paint"}, ("blender/blender/issues/96225", "#96225")),
({"property": "use_full_frame_compositor"}, ("blender/blender/issues/88150", "#88150")),
({"property": "enable_eevee_next"}, ("blender/blender/issues/93220", "#93220")),
({"property": "enable_workbench_next"}, ("blender/blender/issues/101619", "#101619")),
),
)
@ -2352,7 +2357,7 @@ class USERPREF_PT_experimental_tweaks(ExperimentalPanel, Panel):
def draw(self, context):
self._draw_items(
context, (
({"property": "use_select_nearest_on_first_click"}, "T96752"),
({"property": "use_select_nearest_on_first_click"}, ("blender/blender/issues/96752", "#96752")),
),
)
@ -2371,8 +2376,8 @@ class USERPREF_PT_experimental_debugging(ExperimentalPanel, Panel):
def draw(self, context):
self._draw_items(
context, (
({"property": "use_undo_legacy"}, "T60695"),
({"property": "override_auto_resync"}, "T83811"),
({"property": "use_undo_legacy"}, ("blender/blender/issues/60695", "#60695")),
({"property": "override_auto_resync"}, ("blender/blender/issues/83811", "#83811")),
({"property": "use_cycles_debug"}, None),
({"property": "show_asset_debug_info"}, None),
({"property": "use_asset_indexing"}, None),

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

@ -145,10 +145,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

@ -353,6 +353,7 @@ Array<Vector<int>> build_vert_to_edge_map(Span<MEdge> edges, int verts_num);
Array<Vector<int>> build_vert_to_poly_map(Span<MPoly> polys, Span<MLoop> loops, int verts_num);
Array<Vector<int>> build_vert_to_loop_map(Span<MLoop> loops, int verts_num);
Array<Vector<int>> build_edge_to_loop_map(Span<MLoop> loops, int edges_num);
Array<Vector<int, 2>> build_edge_to_poly_map(Span<MPoly> polys, Span<MLoop> loops, int edges_num);
Vector<Vector<int>> build_edge_to_loop_map_resizable(Span<MLoop> loops, 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

@ -120,7 +120,7 @@ void shrinkwrapGpencilModifier_deform(struct ShrinkwrapGpencilModifierData *mmd,
int numVerts);
/**
* Used in `editmesh_mask_extract.c` to shrink-wrap the extracted mesh to the sculpt.
* Used in `editmesh_mask_extract.cc` to shrink-wrap the extracted mesh to the sculpt.
*/
void BKE_shrinkwrap_mesh_nearest_surface_deform(struct bContext *C,
struct Object *ob_source,

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

@ -1467,7 +1467,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

@ -1598,7 +1598,7 @@ struct Brush *BKE_brush_first_search(struct Main *bmain, const eObjectMode ob_mo
void BKE_brush_debug_print_state(Brush *br)
{
/* create a fake brush and set it to the defaults */
Brush def = {{nullptr}};
Brush def = blender::dna::shallow_zero_initialize();
brush_defaults(&def);
#define BR_TEST(field, t) \

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

@ -62,7 +62,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;
}
}
@ -78,7 +77,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

@ -146,7 +146,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

@ -121,7 +121,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);
@ -223,7 +223,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++;
}
@ -250,7 +249,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++;
}
}
@ -662,14 +660,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,
loops.size(),
polys.size(),
use_old,
&medge,
&totedge);

View File

@ -610,6 +610,20 @@ Array<Vector<int>> build_edge_to_loop_map(const Span<MLoop> loops, const int edg
return map;
}
Array<Vector<int, 2>> build_edge_to_poly_map(const Span<MPoly> polys,
const Span<MLoop> loops,
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 MLoop &loop : loops.slice(poly.loopstart, poly.totloop)) {
map[loop.e].append(int(i));
}
}
return map;
}
Vector<Vector<int>> build_edge_to_loop_map_resizable(const Span<MLoop> loops, const int edges_num)
{
Vector<Vector<int>> map(edges_num);

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

@ -1356,8 +1356,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

@ -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

@ -536,6 +536,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;
}
@ -784,15 +788,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;
}
@ -800,7 +799,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,
@ -814,7 +815,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

@ -893,7 +893,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));
@ -928,7 +928,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++) {
@ -940,7 +939,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++) {
@ -948,11 +947,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);
}
}
}
@ -967,12 +966,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)
{
@ -873,7 +873,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. */
@ -1434,15 +1434,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

@ -92,7 +92,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

@ -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_);

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