Undo: support implicit-sharing in memfile undo step #106903

Merged
Jacques Lucke merged 78 commits from JacquesLucke/blender:implicit-sharing-undo into main 2024-02-29 17:15:09 +01:00
33 changed files with 263 additions and 202 deletions
Showing only changes of commit 91dc77283e - Show all commits

View File

@ -99,7 +99,12 @@ static bool use_xwayland_hack = false;
using namespace std;
GHOST_SystemX11::GHOST_SystemX11() : GHOST_System(), m_xkb_descr(nullptr), m_start_time(0)
GHOST_SystemX11::GHOST_SystemX11()
: GHOST_System(),
m_xkb_descr(nullptr),
m_start_time(0),
m_keyboard_vector{0},
m_keycode_last_repeat_key(uint(-1))
{
XInitThreads();
m_display = XOpenDisplay(nullptr);
@ -897,7 +902,7 @@ void GHOST_SystemX11::processEvent(XEvent *xe)
#endif /* WITH_X11_XINPUT */
switch (xe->type) {
case Expose: {
XExposeEvent &xee = xe->xexpose;
const XExposeEvent &xee = xe->xexpose;
if (xee.count == 0) {
/* Only generate a single expose event
@ -909,7 +914,7 @@ void GHOST_SystemX11::processEvent(XEvent *xe)
}
case MotionNotify: {
XMotionEvent &xme = xe->xmotion;
const XMotionEvent &xme = xe->xmotion;
bool is_tablet = window->GetTabletData().Active != GHOST_kTabletModeNone;
@ -1235,7 +1240,7 @@ void GHOST_SystemX11::processEvent(XEvent *xe)
case ButtonPress:
case ButtonRelease: {
XButtonEvent &xbe = xe->xbutton;
const XButtonEvent &xbe = xe->xbutton;
GHOST_TButton gbmask = GHOST_kButtonMaskLeft;
GHOST_TEventType type = (xbe.type == ButtonPress) ? GHOST_kEventButtonDown :
GHOST_kEventButtonUp;
@ -1290,14 +1295,14 @@ void GHOST_SystemX11::processEvent(XEvent *xe)
/* change of size, border, layer etc. */
case ConfigureNotify: {
// XConfigureEvent & xce = xe->xconfigure;
// const XConfigureEvent & xce = xe->xconfigure;
g_event = new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window);
break;
}
case FocusIn:
case FocusOut: {
XFocusChangeEvent &xfe = xe->xfocus;
const XFocusChangeEvent &xfe = xe->xfocus;
/* TODO: make sure this is the correct place for activate/deactivate */
// printf("X: focus %s for window %d\n",
@ -1385,7 +1390,7 @@ void GHOST_SystemX11::processEvent(XEvent *xe)
* (really crossing between windows) since some window-managers
* also send grab/un-grab crossings for mouse-wheel events.
*/
XCrossingEvent &xce = xe->xcrossing;
const XCrossingEvent &xce = xe->xcrossing;
if (xce.mode == NotifyNormal) {
g_event = new GHOST_EventCursor(getMilliSeconds(),
GHOST_kEventCursorMove,
@ -2376,7 +2381,7 @@ class DialogData {
}
/* Is the mouse inside the given button */
bool isInsideButton(XEvent &e, uint button_num)
bool isInsideButton(const XEvent &e, uint button_num)
{
return (
(e.xmotion.y > int(height - padding_y - button_height)) &&

View File

@ -21,22 +21,21 @@ GHOST_Window::GHOST_Window(uint32_t width,
const bool wantStereoVisual,
const bool /*exclusive*/)
: m_drawingContextType(GHOST_kDrawingContextTypeNone),
m_userData(nullptr),
m_cursorVisible(true),
m_cursorGrab(GHOST_kGrabDisable),
m_cursorGrabAxis(GHOST_kAxisNone),
m_cursorGrabInitPos{0, 0},
m_cursorGrabAccumPos{0, 0},
m_cursorShape(GHOST_kStandardCursorDefault),
m_progressBarVisible(false),
m_canAcceptDragOperation(false),
m_isUnsavedChanges(false),
m_wantStereoVisual(wantStereoVisual),
m_nativePixelSize(1.0f),
m_context(new GHOST_ContextNone(false))
{
m_isUnsavedChanges = false;
m_canAcceptDragOperation = false;
m_progressBarVisible = false;
m_cursorGrabAccumPos[0] = 0;
m_cursorGrabAccumPos[1] = 0;
m_nativePixelSize = 1.0f;
m_fullScreen = state == GHOST_kWindowStateFullScreen;
if (m_fullScreen) {

View File

@ -63,20 +63,10 @@ BLI_INLINE void mesh_calc_tessellation_for_face_impl(const Span<int> corner_vert
MLoopTri *mlt_a = mlt++;
create_tri(0, 2, 3);
MLoopTri *mlt_b = mlt;
if (UNLIKELY(face_normal ? is_quad_flip_v3_first_third_fast_with_normal(
/* Simpler calculation (using the normal). */
positions[corner_verts[mlt_a->tri[0]]],
positions[corner_verts[mlt_a->tri[1]]],
positions[corner_verts[mlt_a->tri[2]]],
positions[corner_verts[mlt_b->tri[2]]],
normal_precalc) :
is_quad_flip_v3_first_third_fast(
/* Expensive calculation (no normal). */
positions[corner_verts[mlt_a->tri[0]]],
positions[corner_verts[mlt_a->tri[1]]],
positions[corner_verts[mlt_a->tri[2]]],
positions[corner_verts[mlt_b->tri[2]]]))) {
if (UNLIKELY(is_quad_flip_v3_first_third_fast(positions[corner_verts[mlt_a->tri[0]]],
positions[corner_verts[mlt_a->tri[1]]],
positions[corner_verts[mlt_a->tri[2]]],
positions[corner_verts[mlt_b->tri[2]]]))) {
/* Flip out of degenerate 0-2 state. */
mlt_a->tri[2] = mlt_b->tri[2];
mlt_b->tri[0] = mlt_a->tri[1];

View File

@ -145,11 +145,6 @@ bool is_quad_flip_v3_first_third_fast(const float v1[3],
const float v2[3],
const float v3[3],
const float v4[3]);
bool is_quad_flip_v3_first_third_fast_with_normal(const float v1[3],
const float v2[3],
const float v3[3],
const float v4[3],
const float normal[3]);
/** \} */

View File

@ -5889,6 +5889,9 @@ bool is_quad_flip_v3_first_third_fast(const float v1[3],
const float v3[3],
const float v4[3])
{
/* NOTE: if the faces normal has been calculated it's possible to simplify the following checks,
* however this means the solution may be different depending on the existence of normals
* causing tessellation to be "unstable" depending on the existence of normals, see #106469. */
float d_12[3], d_13[3], d_14[3];
float cross_a[3], cross_b[3];
sub_v3_v3v3(d_12, v2, v1);
@ -5899,19 +5902,6 @@ bool is_quad_flip_v3_first_third_fast(const float v1[3],
return dot_v3v3(cross_a, cross_b) > 0.0f;
}
bool is_quad_flip_v3_first_third_fast_with_normal(const float v1[3],
const float v2[3],
const float v3[3],
const float v4[3],
const float normal[3])
{
float dir_v3v1[3], tangent[3];
sub_v3_v3v3(dir_v3v1, v3, v1);
cross_v3_v3v3(tangent, dir_v3v1, normal);
const float dot = dot_v3v3(v1, tangent);
return (dot_v3v3(v4, tangent) >= dot) || (dot_v3v3(v2, tangent) <= dot);
}
float cubic_tangent_factor_circle_v3(const float tan_l[3], const float tan_r[3])
{
BLI_ASSERT_UNIT_V3(tan_l);

View File

@ -2728,7 +2728,7 @@ void svd_m4(float U[4][4], float s[4], float V[4][4], float A_[4][4])
e[k + 1] += 1.0f;
}
e[k] = -e[k];
if ((k + 1 < m) & (e[k] != 0.0f)) {
if ((k + 1 < m) && (e[k] != 0.0f)) {
float invek1;
/* Apply the transformation. */
@ -2812,7 +2812,7 @@ void svd_m4(float U[4][4], float s[4], float V[4][4], float A_[4][4])
/* If required, generate V. */
for (k = n - 1; k >= 0; k--) {
if ((k < nrt) & (e[k] != 0.0f)) {
if ((k < nrt) && (e[k] != 0.0f)) {
for (j = k + 1; j < nu; j++) {
float t = 0;
for (i = k + 1; i < n; i++) {

View File

@ -1962,17 +1962,19 @@ static Face *cdt_tri_as_imesh_face(
return facep;
}
/* Like BLI_math's is_quad_flip_v3_first_third_fast_with_normal, with const double3's. */
/* Like BLI_math's is_quad_flip_v3_first_third_fast, with const double3's. */
static bool is_quad_flip_first_third(const double3 &v1,
const double3 &v2,
const double3 &v3,
const double3 &v4,
const double3 &normal)
const double3 &v4)
{
double3 dir_v3v1 = v3 - v1;
double3 tangent = math::cross(dir_v3v1, normal);
double dot = math::dot(v1, tangent);
return (math::dot(v4, tangent) >= dot) || (math::dot(v2, tangent) <= dot);
const double3 d_12 = v2 - v1;
const double3 d_13 = v3 - v1;
const double3 d_14 = v4 - v1;
const double3 cross_a = math::cross(d_12, d_13);
const double3 cross_b = math::cross(d_14, d_13);
return math::dot(cross_a, cross_b) > 0.0f;
}
/**
@ -2008,7 +2010,7 @@ static Array<Face *> polyfill_triangulate_poly(Face *f, IMeshArena *arena)
int eo_23 = f->edge_orig[2];
int eo_30 = f->edge_orig[3];
Face *f0, *f1;
if (UNLIKELY(is_quad_flip_first_third(v0->co, v1->co, v2->co, v3->co, f->plane->norm))) {
if (UNLIKELY(is_quad_flip_first_third(v0->co, v1->co, v2->co, v3->co))) {
f0 = arena->add_face({v0, v1, v3}, f->orig, {eo_01, -1, eo_30}, {false, false, false});
f1 = arena->add_face({v1, v2, v3}, f->orig, {eo_12, eo_23, -1}, {false, false, false});
}

View File

@ -37,22 +37,16 @@
#include "MEM_guardedalloc.h"
/* Declarations */
/* Declarations. */
static int BLI_path_unc_prefix_len(const char *path);
#ifdef WIN32
/**
* Return true if the path is absolute ie starts with a drive specifier
* (eg A:\) or is a UNC path.
*/
static bool BLI_path_is_abs(const char *name);
static bool BLI_path_is_abs_win32(const char *name);
#endif /* WIN32 */
// #define DEBUG_STRSIZE
/* implementation */
int BLI_path_sequence_decode(const char *string, char *head, char *tail, ushort *r_digits_len)
{
uint nums = 0, nume = 0;
@ -102,9 +96,8 @@ int BLI_path_sequence_decode(const char *string, char *head, char *tail, ushort
strcpy(tail, string + name_end);
}
if (head) {
/* name_end points to last character of head,
* make it +1 so null-terminator is nicely placed
*/
/* Name_end points to last character of head,
* make it +1 so null-terminator is nicely placed. */
BLI_strncpy(head, string, name_end + 1);
}
if (r_digits_len) {
@ -119,8 +112,6 @@ void BLI_path_sequence_encode(
BLI_sprintf(string, "%s%.*d%s", head, numlen, MAX2(0, pic), tail);
}
static int BLI_path_unc_prefix_len(const char *path); /* defined below in same file */
void BLI_path_normalize(const char *relabase, char *path)
{
ptrdiff_t a;
@ -131,19 +122,18 @@ void BLI_path_normalize(const char *relabase, char *path)
else {
if (path[0] == '/' && path[1] == '/') {
if (path[2] == '\0') {
return; /* path is "//" - can't clean it */
return; /* Path is `//` - can't clean it. */
}
path = path + 2; /* leave the initial "//" untouched */
path = path + 2; /* Leave the initial `//` untouched. */
}
}
/* Note
* memmove(start, eind, strlen(eind) + 1);
/* NOTE(@ideasman42):
* `memmove(start, eind, strlen(eind) + 1);`
* is the same as
* strcpy(start, eind);
* except strcpy should not be used because there is overlap,
* so use memmove's slightly more obscure syntax - Campbell
*/
* `strcpy(start, eind);`
* except `strcpy` should not be used because there is overlap,
* so use `memmove` 's slightly more obscure syntax. */
#ifdef WIN32
@ -152,8 +142,8 @@ void BLI_path_normalize(const char *relabase, char *path)
memmove(start, eind, strlen(eind) + 1);
}
/* remove two consecutive backslashes, but skip the UNC prefix,
* which needs to be preserved */
/* Remove two consecutive backslashes, but skip the UNC prefix,
* which needs to be preserved. */
while ((start = strstr(path + BLI_path_unc_prefix_len(path), "\\\\"))) {
eind = start + strlen("\\\\") - 1;
memmove(start, eind, strlen(eind) + 1);
@ -179,21 +169,21 @@ void BLI_path_normalize(const char *relabase, char *path)
#else
while ((start = strstr(path, "/./"))) {
eind = start + (3 - 1) /* strlen("/./") - 1 */;
eind = start + (3 - 1) /* `strlen("/./") - 1` */;
memmove(start, eind, strlen(eind) + 1);
}
while ((start = strstr(path, "//"))) {
eind = start + (2 - 1) /* strlen("//") - 1 */;
eind = start + (2 - 1) /* `strlen("//") - 1` */;
memmove(start, eind, strlen(eind) + 1);
}
while ((start = strstr(path, "/../"))) {
a = start - path - 1;
if (a > 0) {
/* <prefix>/<parent>/../<postfix> => <prefix>/<postfix> */
eind = start + (4 - 1) /* strlen("/../") - 1 */; /* strip "/.." and keep last "/" */
while (a > 0 && path[a] != '/') { /* find start of <parent> */
/* `<prefix>/<parent>/../<postfix> => <prefix>/<postfix>`. */
eind = start + (4 - 1) /* `strlen("/../") - 1` */; /* Strip "/.." and keep last "/". */
while (a > 0 && path[a] != '/') { /* Find start of `<parent>`. */
a--;
}
memmove(path + a, eind, strlen(eind) + 1);
@ -253,7 +243,7 @@ bool BLI_filename_make_safe_ex(char *fname, bool allow_tokens)
/* Forbid only dots. */
for (fn = fname; *fn == '.'; fn++) {
/* pass */
/* Pass. */
}
if (*fn == '\0') {
*fname = '_';
@ -279,15 +269,14 @@ bool BLI_filename_make_safe_ex(char *fname, bool allow_tokens)
/* Check for forbidden names - not we have to check all combination
* of upper and lower cases, hence the usage of lower_fname
* (more efficient than using BLI_strcasestr repeatedly). */
* (more efficient than using #BLI_strcasestr repeatedly). */
BLI_str_tolower_ascii(lower_fname, len);
for (iname = invalid_names; *iname; iname++) {
if (strstr(lower_fname, *iname) == lower_fname) {
const size_t iname_len = strlen(*iname);
/* Only invalid if the whole name is made of the invalid chunk, or it has an
* (assumed extension) dot just after. This means it will also catch 'valid'
* names like 'aux.foo.bar', but should be
* good enough for us! */
* (assumed extension) dot just after. This means it will also catch *valid*
* names like `aux.foo.bar`, but should be good enough for us! */
if ((iname_len == len) || (lower_fname[iname_len] == '.')) {
*fname = '_';
changed = true;
@ -311,14 +300,14 @@ bool BLI_filename_make_safe(char *fname)
bool BLI_path_make_safe(char *path)
{
/* Simply apply #BLI_filename_make_safe() over each component of the path.
* Luckily enough, same 'safe' rules applies to file & directory names. */
* Luckily enough, same *safe* rules applies to file & directory names. */
char *curr_slash, *curr_path = path;
bool changed = false;
bool skip_first = false;
#ifdef WIN32
if (BLI_path_is_abs(path)) {
/* Do not make safe 'C:' in 'C:\foo\bar'... */
if (BLI_path_is_abs_win32(path)) {
/* Do not make safe `C:` in `C:\foo\bar`. */
skip_first = true;
}
#endif
@ -361,7 +350,7 @@ static int BLI_path_unc_prefix_len(const char *path)
{
if (BLI_path_is_unc(path)) {
if ((path[2] == '?') && (path[3] == '\\')) {
/* we assume long UNC path like \\?\server\share\folder etc... */
/* We assume long UNC path like `\\?\server\share\folder` etc. */
return 4;
}
@ -374,10 +363,14 @@ static int BLI_path_unc_prefix_len(const char *path)
#if defined(WIN32)
/**
* Return true if the path is absolute ie starts with a drive specifier
* (eg A:\) or is a UNC path.
* Return true if the path is an absolute path on a WIN32 file-system, it either:
* - Starts with a drive specifier* (eg `A:\`).
* - Is a UNC path.
*
* \note Not to be confused with the opposite of #BLI_path_is_rel which checks for the
* Blender specific convention of using `//` prefix for blend-file relative paths.
*/
static bool BLI_path_is_abs(const char *name)
static bool BLI_path_is_abs_win32(const char *name)
{
return (name[1] == ':' && ELEM(name[2], '\\', '/')) || BLI_path_is_unc(name);
}
@ -409,9 +402,10 @@ static void BLI_path_unc_to_short(wchar_t *unc)
wchar_t tmp[PATH_MAX];
int len = wcslen(unc);
/* convert:
* \\?\UNC\server\share\folder\... to \\server\share\folder\...
* \\?\C:\ to C:\ and \\?\C:\folder\... to C:\folder\...
/* Convert:
* - `\\?\UNC\server\share\folder\...` to `\\server\share\folder\...`
* - `\\?\C:\` to `C:\`
* - `\\?\C:\folder\...` to `C:\folder\...`
*/
if ((len > 3) && (unc[0] == L'\\') && (unc[1] == L'\\') && (unc[2] == L'?') &&
ELEM(unc[3], L'\\', L'/')) {
@ -450,18 +444,18 @@ void BLI_path_rel(char *file, const char *relfile)
char temp[FILE_MAX];
char res[FILE_MAX];
/* if file is already relative, bail out */
/* If file is already relative, bail out. */
if (BLI_path_is_rel(file)) {
return;
}
/* also bail out if relative path is not set */
/* Also bail out if relative path is not set. */
if (relfile[0] == '\0') {
return;
}
#ifdef WIN32
if (BLI_strnlen(relfile, 3) > 2 && !BLI_path_is_abs(relfile)) {
if (BLI_strnlen(relfile, 3) > 2 && !BLI_path_is_abs_win32(relfile)) {
char *ptemp;
/* Fix missing volume name in relative base,
* can happen with old `recent-files.txt` files. */
@ -479,12 +473,12 @@ void BLI_path_rel(char *file, const char *relfile)
if (BLI_strnlen(file, 3) > 2) {
bool is_unc = BLI_path_is_unc(file);
/* Ensure paths are both UNC paths or are both drives */
/* Ensure paths are both UNC paths or are both drives. */
if (BLI_path_is_unc(temp) != is_unc) {
return;
}
/* Ensure both UNC paths are on the same share */
/* Ensure both UNC paths are on the same share. */
if (is_unc) {
int off;
int slash = 0;
@ -509,16 +503,16 @@ void BLI_path_rel(char *file, const char *relfile)
BLI_str_replace_char(temp + BLI_path_unc_prefix_len(temp), '\\', '/');
BLI_str_replace_char(file + BLI_path_unc_prefix_len(file), '\\', '/');
/* remove /./ which confuse the following slash counting... */
/* Remove `/./` which confuse the following slash counting. */
BLI_path_normalize(NULL, file);
BLI_path_normalize(NULL, temp);
/* the last slash in the file indicates where the path part ends */
/* The last slash in the file indicates where the path part ends. */
lslash = BLI_path_slash_rfind(temp);
if (lslash) {
/* find the prefix of the filename that is equal for both filenames.
* This is replaced by the two slashes at the beginning */
/* Find the prefix of the filename that is equal for both filenames.
* This is replaced by the two slashes at the beginning. */
const char *p = temp;
const char *q = file;
char *r = res;
@ -532,16 +526,14 @@ void BLI_path_rel(char *file, const char *relfile)
p++;
q++;
/* don't search beyond the end of the string
* in the rare case they match */
/* Don't search beyond the end of the string in the rare case they match. */
if ((*p == '\0') || (*q == '\0')) {
break;
}
}
/* we might have passed the slash when the beginning of a dir matches
* so we rewind. Only check on the actual filename
*/
/* We might have passed the slash when the beginning of a dir matches
* so we rewind. Only check on the actual filename. */
if (*q != '/') {
while ((q >= file) && (*q != '/')) {
q--;
@ -557,11 +549,10 @@ void BLI_path_rel(char *file, const char *relfile)
r += BLI_strcpy_rlen(r, "//");
/* p now points to the slash that is at the beginning of the part
/* `p` now points to the slash that is at the beginning of the part
* where the path is different from the relative path.
* We count the number of directories we need to go up in the
* hierarchy to arrive at the common 'prefix' of the path
*/
* hierarchy to arrive at the common prefix of the path. */
if (p < temp) {
p = temp;
}
@ -572,7 +563,7 @@ void BLI_path_rel(char *file, const char *relfile)
p++;
}
/* don't copy the slash at the beginning */
/* Don't copy the slash at the beginning. */
r += BLI_strncpy_rlen(r, q + 1, FILE_MAX - (r - res));
#ifdef WIN32
@ -627,7 +618,7 @@ bool BLI_path_parent_dir(char *path)
return false;
}
if (tail_len == 1) {
/* Last path is ".", as normalize should remove this, it's safe to assume failure.
/* Last path is `.`, as normalize should remove this, it's safe to assume failure.
* This happens when the input a single period (possibly with slashes before or after). */
if (path[tail_ofs] == '.') {
return false;
@ -646,7 +637,7 @@ bool BLI_path_parent_dir_until_exists(char *dir)
/* Loop as long as cur path is not a dir, and we can get a parent path. */
while ((BLI_access(dir, R_OK) != 0) && (valid_path = BLI_path_parent_dir(dir))) {
/* pass */
/* Pass. */
}
return (valid_path && dir[0]);
}
@ -659,11 +650,11 @@ bool BLI_path_parent_dir_until_exists(char *dir)
static bool stringframe_chars(const char *path, int *char_start, int *char_end)
{
uint ch_sta, ch_end, i;
/* Insert current frame: file### -> file001 */
/* Insert current frame: `file###` -> `file001`. */
ch_sta = ch_end = 0;
for (i = 0; path[i] != '\0'; i++) {
if (ELEM(path[i], '\\', '/')) {
ch_end = 0; /* this is a directory name, don't use any hashes we found */
ch_end = 0; /* This is a directory name, don't use any hashes we found. */
}
else if (path[i] == '#') {
ch_sta = i;
@ -671,9 +662,9 @@ static bool stringframe_chars(const char *path, int *char_start, int *char_end)
while (path[ch_end] == '#') {
ch_end++;
}
i = ch_end - 1; /* keep searching */
i = ch_end - 1; /* Keep searching. */
/* don't break, there may be a slash after this that invalidates the previous #'s */
/* Don't break, there may be a slash after this that invalidates the previous #'s. */
}
}
@ -718,7 +709,7 @@ bool BLI_path_frame(char *path, int frame, int digits)
ensure_digits(path, digits);
}
if (stringframe_chars(path, &ch_sta, &ch_end)) { /* warning, ch_end is the last # +1 */
if (stringframe_chars(path, &ch_sta, &ch_end)) { /* Warning: `ch_end` is the last # +1. */
char tmp[FILE_MAX];
BLI_snprintf(
tmp, sizeof(tmp), "%.*s%.*d%s", ch_sta, path, ch_end - ch_sta, frame, path + ch_end);
@ -736,7 +727,7 @@ bool BLI_path_frame_range(char *path, int sta, int end, int digits)
ensure_digits(path, digits);
}
if (stringframe_chars(path, &ch_sta, &ch_end)) { /* warning, ch_end is the last # +1 */
if (stringframe_chars(path, &ch_sta, &ch_end)) { /* Warning: `ch_end` is the last # +1. */
char tmp[FILE_MAX];
BLI_snprintf(tmp,
sizeof(tmp),
@ -812,8 +803,8 @@ void BLI_path_frame_strip(char *path, char *r_ext, const size_t ext_maxlen)
bool BLI_path_frame_check_chars(const char *path)
{
int ch_sta, ch_end; /* dummy args */
return stringframe_chars(path, &ch_sta, &ch_end);
int ch_sta_dummy, ch_end_dummy;
return stringframe_chars(path, &ch_sta_dummy, &ch_end_dummy);
}
void BLI_path_to_display_name(char *display_name, int maxlen, const char *name)
@ -860,16 +851,14 @@ bool BLI_path_abs(char *path, const char *basepath)
char base[FILE_MAX];
#ifdef WIN32
/* without this: "" --> "C:\" */
/* Without this, an empty string converts to: `C:\` */
if (*path == '\0') {
return wasrelative;
}
/* we are checking here if we have an absolute path that is not in the current
* blend file as a lib main - we are basically checking for the case that a
* UNIX root '/' is passed.
*/
if (!wasrelative && !BLI_path_is_abs(path)) {
/* We are checking here if we have an absolute path that is not in the current `.blend` file
* as a lib main - we are basically checking for the case that a UNIX root `/` is passed. */
if (!wasrelative && !BLI_path_is_abs_win32(path)) {
char *p = path;
BLI_windows_get_default_root_dir(tmp);
/* Get rid of the slashes at the beginning of the path. */
@ -892,7 +881,7 @@ bool BLI_path_abs(char *path, const char *basepath)
* `C:\foo.JPG` -> `/c/foo.JPG` */
if (isalpha(tmp[0]) && (tmp[1] == ':') && ELEM(tmp[2], '\\', '/')) {
tmp[1] = tolower(tmp[0]); /* Replace ':' with drive-letter. */
tmp[1] = tolower(tmp[0]); /* Replace `:` with drive-letter. */
tmp[0] = '/';
/* `\` the slash will be converted later. */
}
@ -916,28 +905,28 @@ bool BLI_path_abs(char *path, const char *basepath)
const char *lslash;
BLI_strncpy(base, basepath, sizeof(base));
/* file component is ignored, so don't bother with the trailing slash */
/* File component is ignored, so don't bother with the trailing slash. */
BLI_path_normalize(NULL, base);
lslash = BLI_path_slash_rfind(base);
BLI_str_replace_char(base + BLI_path_unc_prefix_len(base), '\\', '/');
if (lslash) {
/* length up to and including last "/" */
/* Length up to and including last `/`. */
const int baselen = (int)(lslash - base) + 1;
/* use path for temp storage here, we copy back over it right away */
BLI_strncpy(path, tmp + 2, FILE_MAX); /* strip "//" */
/* Use path for temp storage here, we copy back over it right away. */
BLI_strncpy(path, tmp + 2, FILE_MAX); /* Strip `//` prefix. */
memcpy(tmp, base, baselen); /* prefix with base up to last "/" */
BLI_strncpy(tmp + baselen, path, sizeof(tmp) - baselen); /* append path after "//" */
BLI_strncpy(path, tmp, FILE_MAX); /* return as result */
memcpy(tmp, base, baselen); /* Prefix with base up to last `/`. */
BLI_strncpy(tmp + baselen, path, sizeof(tmp) - baselen); /* Append path after `//`. */
BLI_strncpy(path, tmp, FILE_MAX); /* Return as result. */
}
else {
/* base doesn't seem to be a directory--ignore it and just strip "//" prefix on path */
/* Base doesn't seem to be a directory, ignore it and just strip `//` prefix on path. */
BLI_strncpy(path, tmp + 2, FILE_MAX);
}
}
else {
/* base ignored */
/* Base ignored. */
BLI_strncpy(path, tmp, FILE_MAX);
}
@ -948,7 +937,7 @@ bool BLI_path_abs(char *path, const char *basepath)
BLI_str_replace_char(path + 2, '/', '\\');
#endif
/* ensure this is after correcting for path switch */
/* Ensure this is after correcting for path switch. */
BLI_path_normalize(NULL, path);
return wasrelative;
@ -960,7 +949,7 @@ bool BLI_path_is_abs_from_cwd(const char *path)
const int path_len_clamp = BLI_strnlen(path, 3);
#ifdef WIN32
if ((path_len_clamp >= 3 && BLI_path_is_abs(path)) || BLI_path_is_unc(path)) {
if ((path_len_clamp >= 3 && BLI_path_is_abs_win32(path)) || BLI_path_is_unc(path)) {
is_abs = true;
}
#else
@ -979,7 +968,7 @@ bool BLI_path_abs_from_cwd(char *path, const size_t maxlen)
if (!BLI_path_is_abs_from_cwd(path)) {
char cwd[FILE_MAX];
/* in case the full path to the blend isn't used */
/* In case the full path to the blend isn't used. */
if (BLI_current_working_dir(cwd, sizeof(cwd))) {
char origpath[FILE_MAX];
BLI_strncpy(origpath, path, FILE_MAX);
@ -996,7 +985,7 @@ bool BLI_path_abs_from_cwd(char *path, const size_t maxlen)
#ifdef _WIN32
/**
* Tries appending each of the semicolon-separated extensions in the PATHEXT
* Tries appending each of the semicolon-separated extensions in the `PATHEXT`
* environment variable (Windows-only) onto `name` in turn until such a file is found.
* Returns success/failure.
*/
@ -1007,7 +996,7 @@ bool BLI_path_program_extensions_add_win32(char *name, const size_t maxlen)
type = BLI_exists(name);
if ((type == 0) || S_ISDIR(type)) {
/* typically 3-5, ".EXE", ".BAT"... etc */
/* Typically 3-5, ".EXE", ".BAT"... etc. */
const int ext_max = 12;
const char *ext = BLI_getenv("PATHEXT");
if (ext) {
@ -1016,7 +1005,7 @@ bool BLI_path_program_extensions_add_win32(char *name, const size_t maxlen)
char *filename_ext;
const char *ext_next;
/* null terminated in the loop */
/* Null terminated in the loop. */
memcpy(filename, name, name_len);
filename_ext = filename + name_len;
@ -1101,11 +1090,9 @@ bool BLI_path_program_search(char *fullname, const size_t maxlen, const char *na
void BLI_setenv(const char *env, const char *val)
{
/* free windows */
#if (defined(_WIN32) || defined(_WIN64))
/* MS-Windows. */
uputenv(env, val);
#else
/* Linux/macOS/BSD */
if (val) {
@ -1158,7 +1145,7 @@ bool BLI_make_existing_file(const char *name)
char di[FILE_MAX];
BLI_split_dir_part(name, di, sizeof(di));
/* make if the dir doesn't exist */
/* Make if the dir doesn't exist. */
return BLI_dir_create_recursive(di);
}
@ -1260,7 +1247,7 @@ bool BLI_path_extension_glob_validate(char *ext_fnmatch)
/* Non-wildcard char, we can break here and consider the pattern valid. */
return false;
}
/* So far, only wildcards in last group of the pattern... */
/* So far, only wildcards in last group of the pattern. */
only_wildcards = true;
}
/* Only one group in the pattern, so even if its only made of wildcard(s),
@ -1352,7 +1339,7 @@ void BLI_split_dirfile(
if (dir) {
if (lslash) {
/* +1 to include the slash and the last char */
/* +1 to include the slash and the last char. */
BLI_strncpy(dir, string, MIN2(dirlen, lslash + 1));
}
else {
@ -1429,7 +1416,7 @@ size_t BLI_path_append(char *__restrict dst, const size_t maxlen, const char *__
}
if (dirlen >= maxlen) {
return dirlen; /* fills the path */
return dirlen; /* Fills the path. */
}
return dirlen + BLI_strncpy_rlen(dst + dirlen, file, maxlen - dirlen);
@ -1470,7 +1457,7 @@ size_t BLI_path_join_array(char *__restrict dst,
}
#ifdef WIN32
/* Special case "//" for relative paths, don't use separator #SEP
/* Special case `//` for relative paths, don't use separator #SEP
* as this has a special meaning on both WIN32 & UNIX.
* Without this check joining `"//", "path"`. results in `"//\path"`. */
if (ofs != 0) {
@ -1519,7 +1506,7 @@ size_t BLI_path_join_array(char *__restrict dst,
}
if (len != 0) {
/* the very first path may have a slash at the end */
/* The very first path may have a slash at the end. */
if (ofs && !BLI_path_slash_is_native_compat(dst[ofs - 1])) {
dst[ofs++] = SEP;
if (ofs == dst_last) {
@ -1574,7 +1561,7 @@ static bool path_name_at_index_forward(const char *__restrict path,
if ((c == '\0') || BLI_path_slash_is_native_compat(c)) {
if (prev + 1 != i) {
prev += 1;
/* Skip '/./' (behave as if they don't exist). */
/* Skip `/./` (behave as if they don't exist). */
if (!((i - prev == 1) && (prev != 0) && (path[prev] == '.'))) {
if (index_step == index) {
*r_offset = prev;
@ -1609,7 +1596,7 @@ static bool path_name_at_index_backward(const char *__restrict path,
if ((c == '\0') || BLI_path_slash_is_native_compat(c)) {
if (prev - 1 != i) {
i += 1;
/* Skip '/./' (behave as if they don't exist). */
/* Skip `/./` (behave as if they don't exist). */
if (!((prev - i == 1) && (i != 0) && (path[i] == '.'))) {
if (index_step == index) {
*r_offset = i;
@ -1644,7 +1631,7 @@ bool BLI_path_contains(const char *container_path, const char *containee_path)
char containee_native[PATH_MAX];
/* Keep space for a trailing slash. If the path is truncated by this, the containee path is
* longer than PATH_MAX and the result is ill-defined. */
* longer than #PATH_MAX and the result is ill-defined. */
BLI_strncpy(container_native, container_path, PATH_MAX - 1);
BLI_strncpy(containee_native, containee_path, PATH_MAX);

View File

@ -81,11 +81,8 @@ BLI_INLINE void bmesh_calc_tessellation_for_face_impl(BMLoop *(*looptris)[3],
efa->no, l_ptr_a[0]->v->co, l_ptr_a[1]->v->co, l_ptr_a[2]->v->co, l_ptr_b[2]->v->co);
}
if (UNLIKELY(is_quad_flip_v3_first_third_fast_with_normal(l_ptr_a[0]->v->co,
l_ptr_a[1]->v->co,
l_ptr_a[2]->v->co,
l_ptr_b[2]->v->co,
efa->no))) {
if (UNLIKELY(is_quad_flip_v3_first_third_fast(
l_ptr_a[0]->v->co, l_ptr_a[1]->v->co, l_ptr_a[2]->v->co, l_ptr_b[2]->v->co))) {
/* Flip out of degenerate 0-2 state. */
l_ptr_a[2] = l_ptr_b[2];
l_ptr_b[0] = l_ptr_a[1];

View File

@ -166,7 +166,8 @@ void DepthOfField::sync()
/* Now that we know the maximum render resolution of every view, using depth of field, allocate
* the reduced buffers. Color needs to be signed format here. See note in shader for
* explanation. Do not use texture pool because of needs mipmaps. */
eGPUTextureUsage usage = GPU_TEXTURE_USAGE_SHADER_READ | GPU_TEXTURE_USAGE_ATTACHMENT;
eGPUTextureUsage usage = GPU_TEXTURE_USAGE_SHADER_READ | GPU_TEXTURE_USAGE_ATTACHMENT |
GPU_TEXTURE_USAGE_MIP_SWIZZLE_VIEW;
reduced_color_tx_.ensure_2d(GPU_RGBA16F, reduce_size, usage, nullptr, DOF_MIP_COUNT);
reduced_coc_tx_.ensure_2d(GPU_R16F, reduce_size, usage, nullptr, DOF_MIP_COUNT);
reduced_color_tx_.ensure_mip_views();

View File

@ -24,7 +24,8 @@ void HiZBuffer::sync()
int2 hiz_extent = math::ceil_to_multiple(render_extent, int2(1u << (HIZ_MIP_COUNT - 1)));
int2 dispatch_size = math::divide_ceil(hiz_extent, int2(HIZ_GROUP_SIZE));
eGPUTextureUsage usage = GPU_TEXTURE_USAGE_SHADER_READ | GPU_TEXTURE_USAGE_SHADER_WRITE;
eGPUTextureUsage usage = GPU_TEXTURE_USAGE_SHADER_READ | GPU_TEXTURE_USAGE_SHADER_WRITE |
GPU_TEXTURE_USAGE_MIP_SWIZZLE_VIEW;
hiz_tx_.ensure_2d(GPU_R32F, hiz_extent, usage, nullptr, HIZ_MIP_COUNT);
hiz_tx_.ensure_mip_views();
GPU_texture_mipmap_mode(hiz_tx_, true, false);

View File

@ -628,7 +628,7 @@ struct LightData {
float radius_squared;
/** NOTE: It is ok to use float3 here. A float is declared right after it.
* float3 is also aligned to 16 bytes. */
float3 color;
packed_float3 color;
/** Light Type. */
eLightType type;
/** Spot size. Aligned to size of float2. */

View File

@ -257,7 +257,8 @@ class ShadowModule {
/** Tile to physical page mapping. This is an array texture with one layer per view. */
Texture render_map_tx_ = {"ShadowRenderMap",
GPU_R32UI,
GPU_TEXTURE_USAGE_SHADER_READ | GPU_TEXTURE_USAGE_SHADER_WRITE,
GPU_TEXTURE_USAGE_SHADER_READ | GPU_TEXTURE_USAGE_SHADER_WRITE |
GPU_TEXTURE_USAGE_MIP_SWIZZLE_VIEW,
int2(SHADOW_TILEMAP_RES),
64,
nullptr,

View File

@ -12,7 +12,7 @@ void main()
/* Display backfacing surfels with a transparent checkerboard grid. */
if (!gl_FrontFacing) {
ivec2 grid_uv = ivec2(gl_FragCoord) / 5;
ivec2 grid_uv = ivec2(gl_FragCoord.xy) / 5;
if ((grid_uv.x + grid_uv.y) % 2 == 0) {
discard;
return;

View File

@ -45,7 +45,8 @@ void main()
case LIGHT_RECT:
case LIGHT_ELLIPSE:
case LIGHT_POINT:
sphere = Sphere(light._position, light.influence_radius_max);
sphere.center = light._position;
sphere.radius = light.influence_radius_max;
break;
}

View File

@ -110,7 +110,7 @@ bool debug_tilemaps(vec3 P, LightData light)
out_color_add = vec4(debug_tile_state_color(tile), 0.0);
out_color_mul = vec4(0.0);
if (ivec2(gl_FragCoord.xy) == ivec2(0)) {
if (all(equal(ivec2(gl_FragCoord.xy), ivec2(0)))) {
drw_print(light.object_mat);
}
return true;

View File

@ -25,7 +25,9 @@
#pragma BLENDER_REQUIRE(eevee_shadow_tilemap_lib.glsl)
/* TODO(@fclem): Implement. */
#define assert(check)
#ifndef GPU_METAL
# define assert(check)
#endif
/* Remove page ownership from the tile and append it to the cache. */
void shadow_page_free(inout ShadowTileData tile)

View File

@ -45,7 +45,7 @@ float pixel_size_at(float linear_depth)
if (is_persp) {
pixel_size *= max(0.01, linear_depth);
}
return pixel_size * exp2(fb_lod);
return pixel_size * exp2(float(fb_lod));
}
void step_bounding_sphere(vec3 vs_near_plane,
@ -117,6 +117,7 @@ void main()
step_bounding_sphere(vs_near_plane, vs_view_direction, t, t + step_size, P, step_radius);
vec3 vP = point_world_to_view(P);
shadow_tag_usage(vP, P, ws_view_direction, step_radius, t, gl_FragCoord.xy * exp2(fb_lod));
shadow_tag_usage(
vP, P, ws_view_direction, step_radius, t, gl_FragCoord.xy * exp2(float(fb_lod)));
}
}

View File

@ -17,7 +17,7 @@ void inflate_bounds(vec3 ls_center, inout vec3 P, inout vec3 lP)
{
vec3 vP = point_world_to_view(P);
float inflate_scale = pixel_world_radius * exp2(fb_lod);
float inflate_scale = pixel_world_radius * exp2(float(fb_lod));
bool is_persp = (ProjectionMatrix[3][3] == 0.0);
if (is_persp) {
inflate_scale *= -vP.z;

View File

@ -45,6 +45,8 @@ void write_depth(ivec2 texel_co, const int lod, ivec2 tile_co, float depth)
/* Quantization bias. Equivalent to nextafter in C without all the safety. 1 is not enough. */
u_depth += 2;
/* TOOD(Metal): For Metal, textures will need to be viewed as buffers to workaround missing image
* atomics support. */
imageAtomicMin(shadow_atlas_img, out_texel, u_depth);
}

View File

@ -8,6 +8,11 @@
/** \name Shadow pipeline
* \{ */
/* NOTE(Metal): As this is implemented using a fundamental data type, this needs to be specified
* explicitly as uint for code generation, as the MSLShaderGenerator needs to be able to
* distinguish between classes and fundamental types during code generation. */
#define SHADOW_TILE_DATA_PACKED "uint"
GPU_SHADER_CREATE_INFO(eevee_shadow_clipmap_clear)
.do_static_compilation(true)
.local_group_size(SHADOW_CLIPMAP_GROUP_SIZE)
@ -34,7 +39,7 @@ GPU_SHADER_CREATE_INFO(eevee_shadow_tilemap_init)
.do_static_compilation(true)
.local_group_size(SHADOW_TILEMAP_RES, SHADOW_TILEMAP_RES)
.storage_buf(0, Qualifier::READ_WRITE, "ShadowTileMapData", "tilemaps_buf[]")
.storage_buf(1, Qualifier::READ_WRITE, "ShadowTileDataPacked", "tiles_buf[]")
.storage_buf(1, Qualifier::READ_WRITE, SHADOW_TILE_DATA_PACKED, "tiles_buf[]")
.storage_buf(2, Qualifier::READ_WRITE, "ShadowTileMapClip", "tilemaps_clip_buf[]")
.storage_buf(4, Qualifier::READ_WRITE, "uvec2", "pages_cached_buf[]")
.additional_info("eevee_shared")
@ -44,7 +49,7 @@ GPU_SHADER_CREATE_INFO(eevee_shadow_tag_update)
.do_static_compilation(true)
.local_group_size(1, 1, 1)
.storage_buf(0, Qualifier::READ_WRITE, "ShadowTileMapData", "tilemaps_buf[]")
.storage_buf(1, Qualifier::READ_WRITE, "ShadowTileDataPacked", "tiles_buf[]")
.storage_buf(1, Qualifier::READ_WRITE, SHADOW_TILE_DATA_PACKED, "tiles_buf[]")
.storage_buf(5, Qualifier::READ, "ObjectBounds", "bounds_buf[]")
.storage_buf(6, Qualifier::READ, "uint", "resource_ids_buf[]")
.additional_info("eevee_shared", "draw_view", "draw_view_culling")
@ -55,7 +60,7 @@ GPU_SHADER_CREATE_INFO(eevee_shadow_tag_usage_opaque)
.local_group_size(SHADOW_DEPTH_SCAN_GROUP_SIZE, SHADOW_DEPTH_SCAN_GROUP_SIZE)
.sampler(0, ImageType::DEPTH_2D, "depth_tx")
.storage_buf(5, Qualifier::READ_WRITE, "ShadowTileMapData", "tilemaps_buf[]")
.storage_buf(6, Qualifier::READ_WRITE, "ShadowTileDataPacked", "tiles_buf[]")
.storage_buf(6, Qualifier::READ_WRITE, SHADOW_TILE_DATA_PACKED, "tiles_buf[]")
.push_constant(Type::FLOAT, "tilemap_projection_ratio")
.additional_info("eevee_shared", "draw_view", "draw_view_culling", "eevee_light_data")
.compute_source("eevee_shadow_tag_usage_comp.glsl");
@ -71,7 +76,7 @@ GPU_SHADER_CREATE_INFO(eevee_shadow_tag_usage_transparent)
.vertex_in(0, Type::VEC3, "pos")
.storage_buf(4, Qualifier::READ, "ObjectBounds", "bounds_buf[]")
.storage_buf(5, Qualifier::READ_WRITE, "ShadowTileMapData", "tilemaps_buf[]")
.storage_buf(6, Qualifier::READ_WRITE, "ShadowTileDataPacked", "tiles_buf[]")
.storage_buf(6, Qualifier::READ_WRITE, SHADOW_TILE_DATA_PACKED, "tiles_buf[]")
.push_constant(Type::FLOAT, "tilemap_projection_ratio")
.push_constant(Type::FLOAT, "pixel_world_radius")
.push_constant(Type::IVEC2, "fb_resolution")
@ -91,7 +96,7 @@ GPU_SHADER_CREATE_INFO(eevee_shadow_page_mask)
.do_static_compilation(true)
.local_group_size(SHADOW_TILEMAP_RES, SHADOW_TILEMAP_RES)
.storage_buf(0, Qualifier::READ, "ShadowTileMapData", "tilemaps_buf[]")
.storage_buf(1, Qualifier::READ_WRITE, "ShadowTileDataPacked", "tiles_buf[]")
.storage_buf(1, Qualifier::READ_WRITE, SHADOW_TILE_DATA_PACKED, "tiles_buf[]")
.additional_info("eevee_shared")
.compute_source("eevee_shadow_page_mask_comp.glsl");
@ -99,7 +104,7 @@ GPU_SHADER_CREATE_INFO(eevee_shadow_page_free)
.do_static_compilation(true)
.local_group_size(SHADOW_TILEMAP_LOD0_LEN)
.storage_buf(0, Qualifier::READ_WRITE, "ShadowTileMapData", "tilemaps_buf[]")
.storage_buf(1, Qualifier::READ_WRITE, "ShadowTileDataPacked", "tiles_buf[]")
.storage_buf(1, Qualifier::READ_WRITE, SHADOW_TILE_DATA_PACKED, "tiles_buf[]")
.storage_buf(2, Qualifier::READ_WRITE, "ShadowPagesInfoData", "pages_infos_buf")
.storage_buf(3, Qualifier::READ_WRITE, "uint", "pages_free_buf[]")
.storage_buf(4, Qualifier::READ_WRITE, "uvec2", "pages_cached_buf[]")
@ -110,7 +115,7 @@ GPU_SHADER_CREATE_INFO(eevee_shadow_page_defrag)
.do_static_compilation(true)
.local_group_size(1)
.typedef_source("draw_shader_shared.h")
.storage_buf(1, Qualifier::READ_WRITE, "ShadowTileDataPacked", "tiles_buf[]")
.storage_buf(1, Qualifier::READ_WRITE, SHADOW_TILE_DATA_PACKED, "tiles_buf[]")
.storage_buf(2, Qualifier::READ_WRITE, "ShadowPagesInfoData", "pages_infos_buf")
.storage_buf(3, Qualifier::READ_WRITE, "uint", "pages_free_buf[]")
.storage_buf(4, Qualifier::READ_WRITE, "uvec2", "pages_cached_buf[]")
@ -124,7 +129,7 @@ GPU_SHADER_CREATE_INFO(eevee_shadow_page_allocate)
.local_group_size(SHADOW_TILEMAP_LOD0_LEN)
.typedef_source("draw_shader_shared.h")
.storage_buf(0, Qualifier::READ_WRITE, "ShadowTileMapData", "tilemaps_buf[]")
.storage_buf(1, Qualifier::READ_WRITE, "ShadowTileDataPacked", "tiles_buf[]")
.storage_buf(1, Qualifier::READ_WRITE, SHADOW_TILE_DATA_PACKED, "tiles_buf[]")
.storage_buf(2, Qualifier::READ_WRITE, "ShadowPagesInfoData", "pages_infos_buf")
.storage_buf(3, Qualifier::READ_WRITE, "uint", "pages_free_buf[]")
.storage_buf(4, Qualifier::READ_WRITE, "uvec2", "pages_cached_buf[]")
@ -137,7 +142,7 @@ GPU_SHADER_CREATE_INFO(eevee_shadow_tilemap_finalize)
.typedef_source("draw_shader_shared.h")
.local_group_size(SHADOW_TILEMAP_RES, SHADOW_TILEMAP_RES)
.storage_buf(0, Qualifier::READ_WRITE, "ShadowTileMapData", "tilemaps_buf[]")
.storage_buf(1, Qualifier::READ_WRITE, "ShadowTileDataPacked", "tiles_buf[]")
.storage_buf(1, Qualifier::READ_WRITE, SHADOW_TILE_DATA_PACKED, "tiles_buf[]")
.storage_buf(2, Qualifier::READ_WRITE, "ShadowPagesInfoData", "pages_infos_buf")
.storage_buf(3, Qualifier::WRITE, "ViewMatrices", "view_infos_buf[64]")
.storage_buf(4, Qualifier::READ_WRITE, "ShadowStatistics", "statistics_buf")
@ -183,11 +188,12 @@ GPU_SHADER_CREATE_INFO(eevee_shadow_debug)
.do_static_compilation(true)
.additional_info("eevee_shared")
.storage_buf(5, Qualifier::READ, "ShadowTileMapData", "tilemaps_buf[]")
.storage_buf(6, Qualifier::READ, "ShadowTileDataPacked", "tiles_buf[]")
.storage_buf(6, Qualifier::READ, SHADOW_TILE_DATA_PACKED, "tiles_buf[]")
.fragment_out(0, Type::VEC4, "out_color_add", DualBlend::SRC_0)
.fragment_out(0, Type::VEC4, "out_color_mul", DualBlend::SRC_1)
.push_constant(Type::INT, "debug_mode")
.push_constant(Type::INT, "debug_tilemap_index")
.depth_write(DepthWrite::ANY)
.fragment_source("eevee_shadow_debug_frag.glsl")
.additional_info(
"draw_fullscreen", "draw_view", "eevee_hiz_data", "eevee_light_data", "eevee_shadow_data");

View File

@ -350,6 +350,16 @@ struct DRWDebugVert {
};
BLI_STATIC_ASSERT_ALIGN(DRWDebugVert, 16)
inline DRWDebugVert debug_vert_make(uint in_pos0, uint in_pos1, uint in_pos2, uint in_vert_color)
{
DRWDebugVert debug_vert;
debug_vert.pos0 = in_pos0;
debug_vert.pos1 = in_pos1;
debug_vert.pos2 = in_pos2;
debug_vert.vert_color = in_vert_color;
return debug_vert;
}
/* Take the header (DrawCommand) into account. */
#define DRW_DEBUG_DRAW_VERT_MAX (64 * 8192) - 1

View File

@ -34,9 +34,9 @@ uint drw_debug_color_pack(vec4 v_color)
void drw_debug_line(inout uint vertid, vec3 v1, vec3 v2, uint v_color)
{
drw_debug_verts_buf[vertid++] = DRWDebugVert(
drw_debug_verts_buf[vertid++] = debug_vert_make(
floatBitsToUint(v1.x), floatBitsToUint(v1.y), floatBitsToUint(v1.z), v_color);
drw_debug_verts_buf[vertid++] = DRWDebugVert(
drw_debug_verts_buf[vertid++] = debug_vert_make(
floatBitsToUint(v2.x), floatBitsToUint(v2.y), floatBitsToUint(v2.z), v_color);
}

View File

@ -510,7 +510,7 @@ GeometrySet spreadsheet_get_display_geometry_set(const SpaceSpreadsheet *sspread
}
}
else {
if (BLI_listbase_count(&sspreadsheet->viewer_path.path) == 1) {
if (BLI_listbase_is_single(&sspreadsheet->viewer_path.path)) {
if (const GeometrySet *geometry_eval = object_eval->runtime.geometry_set_eval) {
geometry_set = *geometry_eval;
}

View File

@ -3181,7 +3181,7 @@ static float uv_sphere_project(const Scene *scene,
const float branch_init)
{
float max_u = 0.0f;
if (BM_elem_flag_test(efa_init, BM_ELEM_TAG)) {
if (use_seams && BM_elem_flag_test(efa_init, BM_ELEM_TAG)) {
return max_u;
}
@ -3358,7 +3358,7 @@ static float uv_cylinder_project(const Scene *scene,
const float branch_init)
{
float max_u = 0.0f;
if (BM_elem_flag_test(efa_init, BM_ELEM_TAG)) {
if (use_seams && BM_elem_flag_test(efa_init, BM_ELEM_TAG)) {
return max_u;
}

View File

@ -458,6 +458,9 @@ GPUTexture *GPU_texture_create_view(const char *name,
{
BLI_assert(mip_len > 0);
BLI_assert(layer_len > 0);
BLI_assert_msg(
GPU_texture_usage(src) & GPU_TEXTURE_USAGE_MIP_SWIZZLE_VIEW,
"Source texture of TextureView must have GPU_TEXTURE_USAGE_MIP_SWIZZLE_VIEW usage flag.");
Texture *view = GPUBackend::get()->texture_alloc(name);
view->init_view(src,
format,

View File

@ -189,6 +189,16 @@ MTLContext::MTLContext(void *ghost_window, void *ghost_context)
[this->queue retain];
[this->device retain];
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-method-access"
/* Enable increased concurrent shader compiler limit.
* Note: Disable warning for missing method when building on older OS's, as compiled code will
* still work correctly when run on a system with the API available. */
if (@available(macOS 13.3, *)) {
[this->device setShouldMaximizeConcurrentCompilation:YES];
}
#pragma clang diagnostic pop
/* Register present callback. */
this->ghost_context_->metalRegisterPresentCallback(&present);

View File

@ -83,9 +83,7 @@ struct constexp_uvec3 {
uint3 xyz;
};
constexpr constexp_uvec3(uint _x, uint _y, uint _z) : x(_x), y(_y), z(_z)
{
}
constexpr constexp_uvec3(uint _x, uint _y, uint _z) : x(_x), y(_y), z(_z) {}
constexpr uint operator[](int i)
{
/* Note: Need to switch on each elem value as array accessor triggers
@ -294,6 +292,8 @@ struct SStruct {
#define textureGather3(__tex, __uv, __comp) _texture_gather_internal(__tex, __uv, __comp)
#define textureGatherOffset(__tex, __offset, __uv, __comp) \
_texture_gather_internal(__tex, __uv, __comp, __offset)
#define textureGrad(__tex, __uv, __dpdx, __dpdy) \
_texture_grad_internal(__tex, __uv, __dpdx, __dpdy)
#define TEXURE_MACRO(_1, _2, _3, TEXNAME, ...) TEXNAME
#define texture(...) TEXURE_MACRO(__VA_ARGS__, texture3, texture2)(__VA_ARGS__)
@ -849,6 +849,34 @@ inline vec<T, 4> _texture_gather_internal(
return tex.texture->gather(*tex.samp, uva.xy, uint(uva.z), offset);
}
/* Texture Grad. */
inline float4 _texture_grad_internal(
thread _mtl_combined_image_sampler_2d<float, access::sample> tex,
float2 uv,
float2 dpdx,
float2 dpdy)
{
return tex.texture->sample(*tex.samp, uv, gradient2d(dpdx, dpdy));
}
inline float4 _texture_grad_internal(
thread _mtl_combined_image_sampler_2d_array<float, access::sample> tex,
float3 uva,
float2 dpdx,
float2 dpdy)
{
return tex.texture->sample(*tex.samp, uva.xy, uint(uva.z), gradient2d(dpdx, dpdy));
}
inline float4 _texture_grad_internal(
thread _mtl_combined_image_sampler_3d<float, access::sample> tex,
float3 uvw,
float3 dpdx,
float3 dpdy)
{
return tex.texture->sample(*tex.samp, uvw, gradient3d(dpdx, dpdy));
}
/* Texture write support. */
template<typename S, typename T, access A>
inline void _texture_write_internal(thread _mtl_combined_image_sampler_1d<S, A> tex,

View File

@ -230,7 +230,7 @@ static void FlipDXTCImage(ImBuf *ibuf)
const uint8_t *data_end = data + data_size;
for (uint i = 0; i < levels; i++) {
for (uint level = 0; level < levels; level++) {
uint blocks_per_row = (mip_width + 3) / 4;
uint blocks_per_col = (mip_height + 3) / 4;
uint blocks = blocks_per_row * blocks_per_col;
@ -238,7 +238,7 @@ static void FlipDXTCImage(ImBuf *ibuf)
if (data + block_bytes * blocks > data_end) {
/* Stop flipping when running out of data to be modified, avoiding possible buffer overrun
* on a malformed files. */
*num_valid_levels = i;
*num_valid_levels = level;
break;
}

View File

@ -753,6 +753,7 @@ static void rna_def_attribute_float(BlenderRNA *brna)
prop = RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "FloatAttributeValue");
RNA_def_property_override_flag(prop, PROPOVERRIDE_IGNORE);
RNA_def_property_collection_funcs(prop,
"rna_Attribute_data_begin",
"rna_iterator_array_next",
@ -785,6 +786,7 @@ static void rna_def_attribute_float_vector(BlenderRNA *brna)
prop = RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "FloatVectorAttributeValue");
RNA_def_property_override_flag(prop, PROPOVERRIDE_IGNORE);
RNA_def_property_collection_funcs(prop,
"rna_Attribute_data_begin",
"rna_iterator_array_next",
@ -823,6 +825,7 @@ static void rna_def_attribute_float_color(BlenderRNA *brna)
prop = RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "FloatColorAttributeValue");
RNA_def_property_override_flag(prop, PROPOVERRIDE_IGNORE);
RNA_def_property_collection_funcs(prop,
"rna_Attribute_data_begin",
"rna_iterator_array_next",
@ -870,6 +873,7 @@ static void rna_def_attribute_byte_color(BlenderRNA *brna)
prop = RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "ByteColorAttributeValue");
RNA_def_property_override_flag(prop, PROPOVERRIDE_IGNORE);
RNA_def_property_collection_funcs(prop,
"rna_Attribute_data_begin",
"rna_iterator_array_next",
@ -918,6 +922,7 @@ static void rna_def_attribute_int(BlenderRNA *brna)
prop = RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "IntAttributeValue");
RNA_def_property_override_flag(prop, PROPOVERRIDE_IGNORE);
RNA_def_property_collection_funcs(prop,
"rna_Attribute_data_begin",
"rna_iterator_array_next",
@ -947,6 +952,7 @@ static void rna_def_attribute_string(BlenderRNA *brna)
prop = RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "StringAttributeValue");
RNA_def_property_override_flag(prop, PROPOVERRIDE_IGNORE);
RNA_def_property_collection_funcs(prop,
"rna_Attribute_data_begin",
"rna_iterator_array_next",
@ -976,6 +982,7 @@ static void rna_def_attribute_bool(BlenderRNA *brna)
prop = RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "BoolAttributeValue");
RNA_def_property_override_flag(prop, PROPOVERRIDE_IGNORE);
RNA_def_property_collection_funcs(prop,
"rna_Attribute_data_begin",
"rna_iterator_array_next",
@ -1005,6 +1012,7 @@ static void rna_def_attribute_int8(BlenderRNA *brna)
prop = RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "ByteIntAttributeValue");
RNA_def_property_override_flag(prop, PROPOVERRIDE_IGNORE);
RNA_def_property_collection_funcs(prop,
"rna_Attribute_data_begin",
"rna_iterator_array_next",
@ -1036,6 +1044,7 @@ static void rna_def_attribute_int2(BlenderRNA *brna)
prop = RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "Int2AttributeValue");
RNA_def_property_override_flag(prop, PROPOVERRIDE_IGNORE);
RNA_def_property_collection_funcs(prop,
"rna_Attribute_data_begin",
"rna_iterator_array_next",
@ -1071,6 +1080,7 @@ static void rna_def_attribute_float2(BlenderRNA *brna)
prop = RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "Float2AttributeValue");
RNA_def_property_override_flag(prop, PROPOVERRIDE_IGNORE);
RNA_def_property_collection_funcs(prop,
"rna_Attribute_data_begin",
"rna_iterator_array_next",

View File

@ -345,6 +345,7 @@ static void rna_def_curves_curve(BlenderRNA *brna)
prop = RNA_def_property(srna, "points", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "CurvePoint");
RNA_def_property_ui_text(prop, "Points", "Control points of the curve");
RNA_def_property_override_flag(prop, PROPOVERRIDE_IGNORE);
RNA_def_property_collection_funcs(prop,
"rna_CurveSlice_points_begin",
"rna_iterator_array_next",
@ -384,6 +385,7 @@ static void rna_def_curves(BlenderRNA *brna)
/* Point and Curve RNA API helpers. */
prop = RNA_def_property(srna, "curves", PROP_COLLECTION, PROP_NONE);
RNA_def_property_override_flag(prop, PROPOVERRIDE_IGNORE);
RNA_def_property_collection_funcs(prop,
"rna_Curves_curves_begin",
"rna_iterator_array_next",
@ -398,6 +400,7 @@ static void rna_def_curves(BlenderRNA *brna)
prop = RNA_def_property(srna, "points", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "CurvePoint");
RNA_def_property_override_flag(prop, PROPOVERRIDE_IGNORE);
RNA_def_property_collection_funcs(prop,
"rna_Curves_position_data_begin",
"rna_iterator_array_next",
@ -412,6 +415,7 @@ static void rna_def_curves(BlenderRNA *brna)
/* Direct access to built-in attributes. */
prop = RNA_def_property(srna, "position_data", PROP_COLLECTION, PROP_NONE);
RNA_def_property_override_flag(prop, PROPOVERRIDE_IGNORE);
RNA_def_property_collection_funcs(prop,
"rna_Curves_position_data_begin",
"rna_iterator_array_next",
@ -426,6 +430,7 @@ static void rna_def_curves(BlenderRNA *brna)
prop = RNA_def_property(srna, "curve_offset_data", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "IntAttributeValue");
RNA_def_property_override_flag(prop, PROPOVERRIDE_IGNORE);
RNA_def_property_collection_funcs(prop,
"rna_Curves_curve_offset_data_begin",
"rna_iterator_array_next",
@ -440,6 +445,7 @@ static void rna_def_curves(BlenderRNA *brna)
rna_def_read_only_float_vector(brna);
prop = RNA_def_property(srna, "normals", PROP_COLLECTION, PROP_NONE);
RNA_def_property_override_flag(prop, PROPOVERRIDE_IGNORE);
RNA_def_property_struct_type(prop, "FloatVectorValueReadOnly");
/* `lookup_int` isn't provided since the entire normals array is allocated and calculated when
* it's accessed. */

View File

@ -3107,6 +3107,7 @@ static void rna_def_mloopuv(BlenderRNA *brna)
prop,
"MeshUVLoop (Deprecated)",
"Deprecated, use 'uv', 'vertex_select', 'edge_select' or 'pin' properties instead");
RNA_def_property_override_flag(prop, PROPOVERRIDE_IGNORE);
RNA_def_property_collection_funcs(prop,
"rna_MeshUVLoopLayer_data_begin",
"rna_iterator_array_next",
@ -3147,6 +3148,7 @@ static void rna_def_mloopuv(BlenderRNA *brna)
prop = RNA_def_property(srna, "uv", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "Float2AttributeValue");
RNA_def_property_ui_text(prop, "UV", "UV coordinates on face corners");
RNA_def_property_override_flag(prop, PROPOVERRIDE_IGNORE);
RNA_def_property_collection_funcs(prop,
"rna_MeshUVLoopLayer_uv_begin",
"rna_iterator_array_next",
@ -3161,6 +3163,7 @@ static void rna_def_mloopuv(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "BoolAttributeValue");
RNA_def_property_ui_text(
prop, "UV Vertex Selection", "Selection state of the face corner the UV editor");
RNA_def_property_override_flag(prop, PROPOVERRIDE_IGNORE);
RNA_def_property_collection_funcs(prop,
"rna_MeshUVLoopLayer_vert_select_begin",
"rna_iterator_array_next",
@ -3175,6 +3178,7 @@ static void rna_def_mloopuv(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "BoolAttributeValue");
RNA_def_property_ui_text(
prop, "UV Edge Selection", "Selection state of the edge in the UV editor");
RNA_def_property_override_flag(prop, PROPOVERRIDE_IGNORE);
RNA_def_property_collection_funcs(prop,
"rna_MeshUVLoopLayer_edge_select_begin",
"rna_iterator_array_next",
@ -3188,6 +3192,7 @@ static void rna_def_mloopuv(BlenderRNA *brna)
prop = RNA_def_property(srna, "pin", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "BoolAttributeValue");
RNA_def_property_ui_text(prop, "UV Pin", "UV pinned state in the UV editor");
RNA_def_property_override_flag(prop, PROPOVERRIDE_IGNORE);
RNA_def_property_collection_funcs(prop,
"rna_MeshUVLoopLayer_pin_begin",
"rna_iterator_array_next",
@ -3256,6 +3261,7 @@ static void rna_def_mloopcol(BlenderRNA *brna)
prop = RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "MeshLoopColor");
RNA_def_property_ui_text(prop, "Data", "");
RNA_def_property_override_flag(prop, PROPOVERRIDE_IGNORE);
RNA_def_property_collection_funcs(prop,
"rna_MeshLoopColorLayer_data_begin",
"rna_iterator_array_next",
@ -3317,6 +3323,7 @@ static void rna_def_MPropCol(BlenderRNA *brna)
prop = RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "MeshVertColor");
RNA_def_property_ui_text(prop, "Data", "");
RNA_def_property_override_flag(prop, PROPOVERRIDE_IGNORE);
RNA_def_property_collection_funcs(prop,
"rna_MeshVertColorLayer_data_begin",
"rna_iterator_array_next",
@ -3362,6 +3369,7 @@ static void rna_def_mproperties(BlenderRNA *brna)
prop = RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE); \
RNA_def_property_struct_type(prop, "Mesh" elemname "FloatProperty"); \
RNA_def_property_ui_text(prop, "Data", ""); \
RNA_def_property_override_flag(prop, PROPOVERRIDE_IGNORE); \
RNA_def_property_collection_funcs(prop, \
"rna_Mesh" elemname "FloatPropertyLayer_data_begin", \
"rna_iterator_array_next", \
@ -3405,6 +3413,7 @@ static void rna_def_mproperties(BlenderRNA *brna)
prop = RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE); \
RNA_def_property_struct_type(prop, "Mesh" elemname "IntProperty"); \
RNA_def_property_ui_text(prop, "Data", ""); \
RNA_def_property_override_flag(prop, PROPOVERRIDE_IGNORE); \
RNA_def_property_collection_funcs(prop, \
"rna_Mesh" elemname "IntPropertyLayer_data_begin", \
"rna_iterator_array_next", \
@ -3447,6 +3456,7 @@ static void rna_def_mproperties(BlenderRNA *brna)
prop = RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE); \
RNA_def_property_struct_type(prop, "Mesh" elemname "StringProperty"); \
RNA_def_property_ui_text(prop, "Data", ""); \
RNA_def_property_override_flag(prop, PROPOVERRIDE_IGNORE); \
RNA_def_property_collection_funcs(prop, \
"rna_Mesh" elemname "StringPropertyLayer_data_begin", \
"rna_iterator_array_next", \
@ -3955,6 +3965,7 @@ static void rna_def_skin_vertices(BlenderRNA *brna, PropertyRNA *UNUSED(cprop))
prop = RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "MeshSkinVertex");
RNA_def_property_ui_text(prop, "Data", "");
RNA_def_property_override_flag(prop, PROPOVERRIDE_IGNORE);
RNA_def_property_collection_funcs(prop,
"rna_MeshSkinVertexLayer_data_begin",
"rna_iterator_array_next",
@ -4008,6 +4019,7 @@ static void rna_def_vertex_creases(BlenderRNA *brna)
prop = RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "MeshVertexCrease");
RNA_def_property_ui_text(prop, "Data", "");
RNA_def_property_override_flag(prop, PROPOVERRIDE_IGNORE);
RNA_def_property_collection_funcs(prop,
"rna_MeshVertexCreaseLayer_data_begin",
"rna_iterator_array_next",
@ -4042,6 +4054,7 @@ static void rna_def_edge_creases(BlenderRNA *brna)
prop = RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "MeshEdgeCrease");
RNA_def_property_ui_text(prop, "Data", "");
RNA_def_property_override_flag(prop, PROPOVERRIDE_IGNORE);
RNA_def_property_collection_funcs(prop,
"rna_MeshEdgeCreaseLayer_data_begin",
"rna_iterator_array_next",

View File

@ -177,6 +177,7 @@ static void rna_def_pointcloud(BlenderRNA *brna)
/* geometry */
prop = RNA_def_property(srna, "points", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "Point");
RNA_def_property_override_flag(prop, PROPOVERRIDE_IGNORE);
RNA_def_property_collection_funcs(prop,
"rna_PointCloud_points_begin",
"rna_iterator_array_next",