Vulkan: Clearing Framebuffer + Scissors #106044

Merged
Jeroen Bakker merged 49 commits from Jeroen-Bakker/blender:vulkan-framebuffer-clear into main 2023-03-28 11:51:45 +02:00
96 changed files with 916 additions and 284 deletions
Showing only changes of commit 245d5452df - Show all commits

View File

@ -309,7 +309,7 @@ class Device {
static uint devices_initialized_mask;
};
/* Device, which is GPU, with some common functionality for GPU backends */
/* Device, which is GPU, with some common functionality for GPU back-ends. */
class GPUDevice : public Device {
protected:
GPUDevice(const DeviceInfo &info_, Stats &stats_, Profiler &profiler_)

View File

@ -924,19 +924,9 @@ extern bool GHOST_setConsoleWindowState(GHOST_TConsoleWindowState action);
extern bool GHOST_UseNativePixels(void);
/**
* Warp the cursor, if supported.
* Return features which are supported by the GHOST back-end.
*/
extern bool GHOST_SupportsCursorWarp(void);
/**
* Support positioning windows (when false `wmWindow.x,y` are meaningless).
*/
extern bool GHOST_SupportsWindowPosition(void);
/**
* Support a separate primary clipboard.
*/
extern bool GHOST_SupportsPrimaryClipboard(void);
extern GHOST_TCapabilityFlag GHOST_GetCapabilities(void);
/**
* Assign the callback which generates a back-trace (may be NULL).

View File

@ -318,19 +318,11 @@ class GHOST_ISystem {
virtual bool useNativePixel(void) = 0;
/**
* Return true when warping the cursor is supported.
* Return features supported by the system back-end.
*
* The resulting value doesn't change at run-time.
*/
virtual bool supportsCursorWarp() = 0;
/**
* Return true getting/setting the window position is supported.
*/
virtual bool supportsWindowPosition() = 0;
/**
* Return true when a separate primary clipboard is supported.
*/
virtual bool supportsPrimaryClipboard() = 0;
virtual GHOST_TCapabilityFlag getCapabilities() const = 0;
/**
* Focus window after opening, or put them in the background.

View File

@ -9,6 +9,9 @@
#include <stdint.h>
/* This is used by `GHOST_C-api.h` too, cannot use C++ conventions. */
// NOLINTBEGIN: modernize-use-using
#ifdef WITH_CXX_GUARDEDALLOC
# include "MEM_guardedalloc.h"
#else
@ -74,6 +77,37 @@ typedef void *GHOST_TUserDataPtr;
typedef enum { GHOST_kFailure = 0, GHOST_kSuccess } GHOST_TSuccess;
/**
* Static flag (relating to the back-ends support for features).
*
* \note When adding new capabilities, add to #GHOST_CAPABILITY_FLAG_ALL,
* then mask out of from the `getCapabilities(..)` callback with an explanation for why
* the feature is not supported.
*/
typedef enum {
/**
* Set when warping the cursor is supported (re-positioning the users cursor).
*/
GHOST_kCapabilityCursorWarp = (1 << 0),
/**
* Set when getting/setting the window position is supported.
*/
GHOST_kCapabilityWindowPosition = (1 << 1),
/**
* Set when a separate primary clipboard is supported.
* This is a convention for X11/WAYLAND, select text & MMB to paste (without an explicit copy).
*/
GHOST_kCapabilityPrimaryClipboard = (1 << 2),
} GHOST_TCapabilityFlag;
/**
* Back-ends should use this, masking out features which are not supported
* with notes as to why those features cannot be supported.
*/
#define GHOST_CAPABILITY_FLAG_ALL \
(GHOST_kCapabilityCursorWarp | GHOST_kCapabilityWindowPosition | \
GHOST_kCapabilityPrimaryClipboard)
/* Xtilt and Ytilt represent how much the pen is tilted away from
* vertically upright in either the X or Y direction, with X and Y the
* axes of the tablet surface.
@ -848,3 +882,5 @@ typedef struct GHOST_XrControllerModelData {
} GHOST_XrControllerModelData;
#endif /* WITH_XR_OPENXR */
// NOLINTEND: modernize-use-using

View File

@ -895,22 +895,10 @@ bool GHOST_UseNativePixels(void)
return system->useNativePixel();
}
bool GHOST_SupportsCursorWarp(void)
GHOST_TCapabilityFlag GHOST_GetCapabilities(void)
{
GHOST_ISystem *system = GHOST_ISystem::getSystem();
return system->supportsCursorWarp();
}
bool GHOST_SupportsWindowPosition(void)
{
GHOST_ISystem *system = GHOST_ISystem::getSystem();
return system->supportsWindowPosition();
}
bool GHOST_SupportsPrimaryClipboard(void)
{
GHOST_ISystem *system = GHOST_ISystem::getSystem();
return system->supportsPrimaryClipboard();
return system->getCapabilities();
}
void GHOST_SetBacktraceHandler(GHOST_TBacktraceFn backtrace_fn)

View File

@ -418,21 +418,6 @@ void GHOST_System::setAutoFocus(const bool auto_focus)
m_autoFocus = auto_focus;
}
bool GHOST_System::supportsCursorWarp()
{
return true;
}
bool GHOST_System::supportsWindowPosition()
{
return true;
}
bool GHOST_System::supportsPrimaryClipboard()
{
return false;
}
void GHOST_System::initDebug(GHOST_Debug debug)
{
m_is_debug_enabled = debug.flags & GHOST_kDebugDefault;

View File

@ -150,10 +150,6 @@ class GHOST_System : public GHOST_ISystem {
bool useNativePixel(void);
bool m_nativePixel;
bool supportsCursorWarp(void);
bool supportsWindowPosition(void);
bool supportsPrimaryClipboard(void);
/**
* Focus window after opening, or put them in the background.
*/

View File

@ -193,6 +193,8 @@ class GHOST_SystemCocoa : public GHOST_System {
*/
GHOST_TSuccess getButtons(GHOST_Buttons &buttons) const;
GHOST_TCapabilityFlag getCapabilities() const;
/**
* Returns Clipboard data
* \param selection: Indicate which buffer to return.

View File

@ -900,6 +900,14 @@ GHOST_TSuccess GHOST_SystemCocoa::getButtons(GHOST_Buttons &buttons) const
return GHOST_kSuccess;
}
GHOST_TCapabilityFlag GHOST_SystemCocoa::getCapabilities() const
{
return GHOST_TCapabilityFlag(GHOST_CAPABILITY_FLAG_ALL &
~(
/* Cocoa has no support for a primary selection clipboard. */
GHOST_kCapabilityPrimaryClipboard));
}
#pragma mark Event handlers
/**

View File

@ -42,6 +42,13 @@ class GHOST_SystemHeadless : public GHOST_System {
{
return GHOST_kSuccess;
}
GHOST_TCapabilityFlag getCapabilities() const override
{
return GHOST_TCapabilityFlag(GHOST_CAPABILITY_FLAG_ALL &
/* No windowing functionality supported. */
~(GHOST_kCapabilityWindowPosition | GHOST_kCapabilityCursorWarp |
GHOST_kCapabilityPrimaryClipboard));
}
char *getClipboard(bool /*selection*/) const override
{
return nullptr;

View File

@ -715,7 +715,7 @@ GHOST_WindowSDL *GHOST_SystemSDL::findGhostWindow(SDL_Window *sdl_win)
if (sdl_win == nullptr) {
return nullptr;
}
/* It is not entirely safe to do this as the backptr may point
/* It is not entirely safe to do this as the back-pointer may point
* to a window that has recently been removed.
* We should always check the window manager's list of windows
* and only process events on these windows. */
@ -751,6 +751,15 @@ GHOST_TSuccess GHOST_SystemSDL::getButtons(GHOST_Buttons &buttons) const
return GHOST_kSuccess;
}
GHOST_TCapabilityFlag GHOST_SystemSDL::getCapabilities() const
{
return GHOST_TCapabilityFlag(
GHOST_CAPABILITY_FLAG_ALL &
~(
/* This SDL back-end has not yet implemented primary clipboard. */
GHOST_kCapabilityPrimaryClipboard));
}
char *GHOST_SystemSDL::getClipboard(bool /*selection*/) const
{
return (char *)SDL_GetClipboardText();

View File

@ -42,6 +42,8 @@ class GHOST_SystemSDL : public GHOST_System {
GHOST_TSuccess getButtons(GHOST_Buttons &buttons) const;
GHOST_TCapabilityFlag getCapabilities() const;
char *getClipboard(bool selection) const;
void putClipboard(const char *buffer, bool selection) const;

View File

@ -6675,22 +6675,16 @@ GHOST_TSuccess GHOST_SystemWayland::cursor_visibility_set(const bool visible)
return GHOST_kSuccess;
}
bool GHOST_SystemWayland::supportsCursorWarp()
GHOST_TCapabilityFlag GHOST_SystemWayland::getCapabilities() const
{
/* WAYLAND doesn't support setting the cursor position directly,
* this is an intentional choice, forcing us to use a software cursor in this case. */
return false;
}
bool GHOST_SystemWayland::supportsWindowPosition()
{
/* WAYLAND doesn't support accessing the window position. */
return false;
}
bool GHOST_SystemWayland::supportsPrimaryClipboard()
{
return true;
return GHOST_TCapabilityFlag(
GHOST_CAPABILITY_FLAG_ALL &
~(
/* WAYLAND doesn't support accessing the window position. */
GHOST_kCapabilityWindowPosition |
/* WAYLAND doesn't support setting the cursor position directly,
* this is an intentional choice, forcing us to use a software cursor in this case. */
GHOST_kCapabilityCursorWarp));
}
bool GHOST_SystemWayland::cursor_grab_use_software_display_get(const GHOST_TGrabCursorMode mode)
@ -7038,7 +7032,7 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod
const struct GWL_SeatStateGrab grab_state_next = seat_grab_state_from_mode(mode,
use_software_confine);
/* Check for wrap as #supportsCursorWarp isn't supported. */
/* Check for wrap as #GHOST_kCapabilityCursorWarp isn't supported. */
const bool use_visible = !(ELEM(mode, GHOST_kGrabHide, GHOST_kGrabWrap) || use_software_confine);
const bool is_hardware_cursor = !cursor_is_software(mode, use_software_confine);

View File

@ -142,9 +142,7 @@ class GHOST_SystemWayland : public GHOST_System {
const bool is_dialog,
const GHOST_IWindow *parentWindow) override;
bool supportsCursorWarp() override;
bool supportsWindowPosition() override;
bool supportsPrimaryClipboard() override;
GHOST_TCapabilityFlag getCapabilities() const override;
/* WAYLAND utility functions (share window/system logic). */

View File

@ -496,6 +496,14 @@ GHOST_TSuccess GHOST_SystemWin32::getButtons(GHOST_Buttons &buttons) const
return GHOST_kSuccess;
}
GHOST_TCapabilityFlag GHOST_SystemWin32::getCapabilities() const
{
return GHOST_TCapabilityFlag(GHOST_CAPABILITY_FLAG_ALL &
~(
/* WIN32 has no support for a primary selection clipboard. */
GHOST_kCapabilityPrimaryClipboard));
}
GHOST_TSuccess GHOST_SystemWin32::init()
{
GHOST_TSuccess success = GHOST_System::init();

View File

@ -199,6 +199,8 @@ class GHOST_SystemWin32 : public GHOST_System {
*/
GHOST_TSuccess getButtons(GHOST_Buttons &buttons) const;
GHOST_TCapabilityFlag getCapabilities() const;
/**
* Returns unsigned char from CUT_BUFFER0
* \param selection: Used by X11 only.

View File

@ -497,7 +497,7 @@ GHOST_WindowX11 *GHOST_SystemX11::findGhostWindow(Window xwind) const
return nullptr;
}
/* It is not entirely safe to do this as the backptr may point
/* It is not entirely safe to do this as the back-pointer may point
* to a window that has recently been removed.
* We should always check the window manager's list of windows
* and only process events on these windows. */
@ -1740,9 +1740,9 @@ GHOST_TSuccess GHOST_SystemX11::setCursorPosition(int32_t x, int32_t y)
return GHOST_kSuccess;
}
bool GHOST_SystemX11::supportsPrimaryClipboard()
GHOST_TCapabilityFlag GHOST_SystemX11::getCapabilities() const
{
return true;
return GHOST_TCapabilityFlag(GHOST_CAPABILITY_FLAG_ALL);
}
void GHOST_SystemX11::addDirtyWindow(GHOST_WindowX11 *bad_wind)

View File

@ -168,7 +168,7 @@ class GHOST_SystemX11 : public GHOST_System {
*/
GHOST_TSuccess getButtons(GHOST_Buttons &buttons) const;
bool supportsPrimaryClipboard() override;
GHOST_TCapabilityFlag getCapabilities() const;
/**
* Flag a window as dirty. This will

View File

@ -1479,7 +1479,7 @@ struct FaceDetails {
/* Details about the fallback fonts we ship, so that we can load only when needed. */
static const struct FaceDetails static_face_details[] = {
{"lastresort.woff2", UINT32_MAX, UINT32_MAX, UINT32_MAX, UINT32_MAX},
{"Noto Sans CJK Regular.woff2", 0x30000083L, 0x2BDF3C10L, 0x16L, 0},
{"Noto Sans CJK Regular.woff2", 0x30000083L, 0x29DF3C10L, 0x16L, 0},
{"NotoEmoji-VariableFont_wght.woff2", 0x80000003L, 0x241E4ACL, 0x14000000L, 0x4000000L},
{"NotoSansArabic-VariableFont_wdth,wght.woff2",
TT_UCR_ARABIC,

View File

@ -631,20 +631,53 @@ static FT_UInt blf_glyph_index_from_charcode(FontBLF **font, const uint charcode
return 0;
}
/* Not found in main font, so look in the others. */
FontBLF *last_resort = NULL;
/* First look in currently-loaded cached fonts that match the coverage bit. Super fast. */
int coverage_bit = blf_charcode_to_coverage_bit(charcode);
for (int i = 0; i < BLF_MAX_FONT; i++) {
FontBLF *f = global_font[i];
if (!f || f == *font || !(f->face) || !(f->flags & BLF_DEFAULT) ||
(!((*font)->flags & BLF_MONOSPACED) && (f->flags & BLF_MONOSPACED)) ||
f->flags & BLF_LAST_RESORT) {
continue;
}
if (coverage_bit < 0 || blf_font_has_coverage_bit(f, coverage_bit)) {
glyph_index = blf_get_char_index(f, charcode);
if (glyph_index) {
*font = f;
return glyph_index;
}
}
}
/* Next look only in unloaded fonts that match the coverage bit. */
for (int i = 0; i < BLF_MAX_FONT; i++) {
FontBLF *f = global_font[i];
if (!f || f == *font || (f->face) || !(f->flags & BLF_DEFAULT) ||
(!((*font)->flags & BLF_MONOSPACED) && (f->flags & BLF_MONOSPACED)) ||
f->flags & BLF_LAST_RESORT) {
continue;
}
if (coverage_bit < 0 || blf_font_has_coverage_bit(f, coverage_bit)) {
glyph_index = blf_get_char_index(f, charcode);
if (glyph_index) {
*font = f;
return glyph_index;
}
}
}
/* Last look in anything else. Also check if we have a last-resort font. */
FontBLF *last_resort = NULL;
for (int i = 0; i < BLF_MAX_FONT; i++) {
FontBLF *f = global_font[i];
if (!f || f == *font || !(f->flags & BLF_DEFAULT)) {
continue;
}
if (f->flags & BLF_LAST_RESORT) {
last_resort = f;
continue;
}
if (coverage_bit < 0 || blf_font_has_coverage_bit(f, coverage_bit)) {
if (coverage_bit >= 0 && !blf_font_has_coverage_bit(f, coverage_bit)) {
glyph_index = blf_get_char_index(f, charcode);
if (glyph_index) {
*font = f;

View File

@ -132,22 +132,22 @@ bool CustomData_bmesh_has_free(const struct CustomData *data);
bool CustomData_has_referenced(const struct CustomData *data);
/**
* Copies the "value" (e.g. mloopuv uv or mloopcol colors) from one block to
* Copies the "value" (e.g. `mloopuv` UV or `mloopcol` colors) from one block to
* another, while not overwriting anything else (e.g. flags). probably only
* implemented for mloopuv/mloopcol, for now.
* implemented for `mloopuv/mloopcol`, for now.
*/
void CustomData_data_copy_value(int type, const void *source, void *dest);
void CustomData_data_set_default_value(int type, void *elem);
/**
* Mixes the "value" (e.g. mloopuv uv or mloopcol colors) from one block into
* Mixes the "value" (e.g. `mloopuv` UV or `mloopcol` colors) from one block into
* another, while not overwriting anything else (e.g. flags).
*/
void CustomData_data_mix_value(
int type, const void *source, void *dest, int mixmode, float mixfactor);
/**
* Compares if data1 is equal to data2. type is a valid CustomData type
* Compares if data1 is equal to data2. type is a valid #CustomData type
* enum (e.g. #CD_PROP_FLOAT). the layer type's equal function is used to compare
* the data, if it exists, otherwise #memcmp is used.
*/

View File

@ -501,7 +501,7 @@ struct GPUTexture *BKE_image_create_gpu_texture_from_ibuf(struct Image *image, s
*
* This is provided as a separate function and not implemented as part of the GPU texture retrieval
* functions because the current cache system only allows a single pass, layer, and stereo view to
* be cached, so possible frequent invalidations of the cache can have performance implications,
* be cached, so possible frequent cache invalidation can have performance implications,
* and making invalidation explicit by calling this function will help make that clear and pave the
* way for a more complete cache system in the future.
*/

View File

@ -17,6 +17,7 @@
#include "BLI_string.h"
#include "BLI_string_utf8.h"
#include "BLI_string_utils.h"
#include "BLI_tempfile.h"
#include "BLI_utildefines.h"
#include "BKE_appdir.h" /* own include */
@ -1089,7 +1090,7 @@ void BKE_appdir_app_templates(ListBase *templates)
* Also make sure the temp dir has a trailing slash
*
* \param tempdir: The full path to the temporary temp directory.
* \param tempdir_len: The size of the \a tempdir buffer.
* \param tempdir_maxlen: The size of the \a tempdir buffer.
* \param userdir: Directory specified in user preferences (may be NULL).
* note that by default this is an empty string, only use when non-empty.
*/
@ -1098,37 +1099,14 @@ static void where_is_temp(char *tempdir, const size_t tempdir_maxlen, const char
tempdir[0] = '\0';
if (userdir && BLI_is_dir(userdir)) {
if (userdir && userdir[0] != '\0' && BLI_is_dir(userdir)) {
BLI_strncpy(tempdir, userdir, tempdir_maxlen);
}
if (tempdir[0] == '\0') {
const char *env_vars[] = {
#ifdef WIN32
"TEMP",
#else
/* Non standard (could be removed). */
"TMP",
/* Posix standard. */
"TMPDIR",
#endif
};
for (int i = 0; i < ARRAY_SIZE(env_vars); i++) {
const char *tmp = BLI_getenv(env_vars[i]);
if (tmp && (tmp[0] != '\0') && BLI_is_dir(tmp)) {
BLI_strncpy(tempdir, tmp, tempdir_maxlen);
break;
}
}
}
if (tempdir[0] == '\0') {
BLI_strncpy(tempdir, "/tmp/", tempdir_maxlen);
}
else {
/* add a trailing slash if needed */
/* Add a trailing slash if needed. */
BLI_path_slash_ensure(tempdir, tempdir_maxlen);
return;
}
BLI_temp_directory_path_get(tempdir, tempdir_maxlen);
}
static void tempdir_session_create(char *tempdir_session,

View File

@ -1015,7 +1015,7 @@ static void layerInterp_mloopcol(const void **sources,
/** \name Callbacks for #OrigSpaceLoop
* \{ */
/* origspace is almost exact copy of mloopuv's, keep in sync */
/* origspace is almost exact copy of #MLoopUV, keep in sync. */
static void layerCopyValue_mloop_origspace(const void *source,
void *dest,
const int /*mixmode*/,

View File

@ -1847,6 +1847,13 @@ static void sculpt_update_object(
}
if (is_paint_tool) {
if (ss->vcol_domain == ATTR_DOMAIN_CORNER) {
/* Ensure pbvh nodes have loop indices; the sculpt undo system
* needs them for color attributes.
*/
BKE_pbvh_ensure_node_loops(ss->pbvh);
}
/*
* We should rebuild the PBVH_pixels when painting canvas changes.
*

View File

@ -15,6 +15,8 @@
* This design allows some function overloads to be more efficient with certain types.
*/
#include <iostream>
#include "BLI_math_base.hh"
namespace blender::math {

View File

@ -18,6 +18,8 @@
* the fastest and more correct option.
*/
#include <iostream>
#include "BLI_math_angle_types.hh"
#include "BLI_math_base.hh"
#include "BLI_math_basis_types.hh"

View File

@ -21,6 +21,8 @@
* - Curve Tangent-Space: X-left, Y-up, Z-forward
*/
#include <iostream>
#include "BLI_math_base.hh"
#include "BLI_math_vector_types.hh"

View File

@ -24,6 +24,8 @@
* eg: `Euler3 my_euler(EulerOrder::XYZ); my_euler = my_quaternion:`
*/
#include <iostream>
#include "BLI_math_angle_types.hh"
#include "BLI_math_base.hh"
#include "BLI_math_basis_types.hh"

View File

@ -6,6 +6,8 @@
* \ingroup bli
*/
#include <iostream>
#include "BLI_math_angle_types.hh"
#include "BLI_math_base.hh"
#include "BLI_math_basis_types.hh"

View File

@ -19,6 +19,7 @@ extern "C" {
/**
* Stored in R8G8 format. Load it in the following format:
* - DX10: DXGI_FORMAT_R8G8_UNORM
* - GPU: GPU_RG8 texture format and GPU_DATA_UBYTE data format.
*/
extern const unsigned char areaTexBytes[];
@ -30,6 +31,7 @@ extern const unsigned char areaTexBytes[];
/**
* Stored in R8 format. Load it in the following format:
* - DX10: DXGI_FORMAT_R8_UNORM
* - GPU: GPU_R8 texture format and GPU_DATA_UBYTE data format.
*/
extern const unsigned char searchTexBytes[];

View File

@ -0,0 +1,27 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2023 Blender Foundation. */
/** \file
* \ingroup bli
*/
#pragma once
#include "BLI_sys_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Get the path to a directory suitable for temporary files.
*
* The return path is guaranteed to exist and to be a directory, as well as to contain a trailing
* directory separator.
*
* At maximum the buffer_size number of characters is written to the temp_directory. The directory
* path is always null-terminated. */
void BLI_temp_directory_path_get(char *temp_directory, const size_t buffer_size);
#ifdef __cplusplus
}
#endif

View File

@ -24,7 +24,7 @@ struct ProjCameraInfo *BLI_uvproject_camera_info(struct Object *ob,
float winy);
/**
* Apply UV from uvinfo (camera).
* Apply UV from #ProjCameraInfo (camera).
*/
void BLI_uvproject_from_camera(float target[2], float source[3], struct ProjCameraInfo *uci);

View File

@ -131,6 +131,7 @@ set(SRC
intern/scanfill_utils.c
intern/serialize.cc
intern/session_uuid.c
intern/smaa_textures.c
intern/smallhash.c
intern/sort.c
intern/sort_utils.c
@ -147,6 +148,7 @@ set(SRC
intern/task_pool.cc
intern/task_range.cc
intern/task_scheduler.cc
intern/tempfile.c
intern/threads.cc
intern/time.c
intern/timecode.c
@ -329,6 +331,7 @@ set(SRC
BLI_set_slots.hh
BLI_shared_cache.hh
BLI_simd.h
BLI_smaa_textures.h
BLI_smallhash.h
BLI_sort.h
BLI_sort.hh
@ -347,6 +350,7 @@ set(SRC
BLI_system.h
BLI_task.h
BLI_task.hh
BLI_tempfile.h
BLI_threads.h
BLI_timecode.h
BLI_timeit.hh
@ -533,6 +537,7 @@ if(WITH_GTESTS)
tests/BLI_string_utf8_test.cc
tests/BLI_task_graph_test.cc
tests/BLI_task_test.cc
tests/BLI_tempfile_test.cc
tests/BLI_uuid_test.cc
tests/BLI_vector_set_test.cc
tests/BLI_vector_test.cc

View File

@ -5,7 +5,7 @@
* 2013 Fernando Navarro <fernandn@microsoft.com>
* 2013 Diego Gutierrez <diegog@unizar.es> */
#include "smaa_textures.h"
#include "BLI_smaa_textures.h"
/* Don't re-wrap large data definitions. */
/* clang-format off */
@ -13,6 +13,7 @@
/**
* Stored in R8G8 format. Load it in the following format:
* - DX10: DXGI_FORMAT_R8G8_UNORM
* - GPU: GPU_RG8 texture format and GPU_DATA_UBYTE data format.
*/
const unsigned char areaTexBytes[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@ -14954,6 +14955,7 @@ const unsigned char areaTexBytes[] = {
/**
* Stored in R8 format. Load it in the following format:
* - DX10: DXGI_FORMAT_R8_UNORM
* - GPU: GPU_R8 texture format and GPU_DATA_UBYTE data format.
*/
const unsigned char searchTexBytes[] = {
0xfe, 0xfe, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0xfe, 0xfe, 0x00, 0x7f, 0x7f,

View File

@ -0,0 +1,42 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2023 Blender Foundation. */
#include "BLI_tempfile.h"
#include "BLI_fileops.h"
#include "BLI_path_util.h"
#include "BLI_string.h"
void BLI_temp_directory_path_get(char *temp_directory, const size_t buffer_size)
{
temp_directory[0] = '\0';
const char *env_vars[] = {
#ifdef WIN32
"TEMP",
#else
/* Non standard (could be removed). */
"TMP",
/* Posix standard. */
"TMPDIR",
#endif
};
for (int i = 0; i < ARRAY_SIZE(env_vars); i++) {
const char *tmp = BLI_getenv(env_vars[i]);
if (tmp && (tmp[0] != '\0') && BLI_is_dir(tmp)) {
BLI_strncpy(temp_directory, tmp, buffer_size);
break;
}
}
if (temp_directory[0] == '\0') {
BLI_strncpy(temp_directory, "/tmp/", buffer_size);
}
else {
/* Add a trailing slash if needed. */
BLI_path_slash_ensure(temp_directory, buffer_size);
}
BLI_dir_create_recursive(temp_directory);
}

View File

@ -1,11 +1,16 @@
/* SPDX-License-Identifier: Apache-2.0 */
#include "testing/testing.h"
#include "BLI_fileops.hh"
#include "BLI_path_util.h"
#include "BLI_string.h"
#include "BLI_system.h"
#include "BLI_tempfile.h"
#include "BLI_threads.h"
#include BLI_SYSTEM_PID_H
namespace blender::tests {
class ChangeWorkingDirectoryTest : public testing::Test {
@ -26,6 +31,20 @@ class ChangeWorkingDirectoryTest : public testing::Test {
BLI_threadapi_exit();
}
/* Make a pseudo-unique file name file within the temp directory in a cross-platform manner. */
static std::string make_pseudo_unique_temp_filename()
{
char temp_dir[FILE_MAX];
BLI_temp_directory_path_get(temp_dir, sizeof(temp_dir));
const std::string directory_name = "blender_test_" + std::to_string(getpid());
char filepath[FILE_MAX];
BLI_path_join(filepath, sizeof(filepath), temp_dir, directory_name.c_str());
return filepath;
}
};
TEST(fileops, fstream_open_string_filename)
@ -71,7 +90,7 @@ TEST_F(ChangeWorkingDirectoryTest, change_working_directory)
ASSERT_TRUE(original_cwd == original_cwd_buff)
<< "Returned CWD path unexpectedly different than given char buffer.";
std::string temp_file_name(std::tmpnam(nullptr));
std::string temp_file_name = make_pseudo_unique_temp_filename();
test_temp_dir = temp_file_name + "овый";
if (BLI_exists(test_temp_dir.c_str())) {
@ -94,7 +113,7 @@ TEST_F(ChangeWorkingDirectoryTest, change_working_directory)
<< "Returned CWD path unexpectedly different than given char buffer.";
#ifdef __APPLE__
/* The name returned by std::tmpnam is fine but the Apple OS method
/* The name returned by `std::tmpnam` is fine but the Apple OS method
* picks the true var folder, not the alias, meaning the below
* comparison always fails unless we prepend with the correct value. */
test_temp_dir = "/private" + test_temp_dir;

View File

@ -0,0 +1,27 @@
/* SPDX-License-Identifier: Apache-2.0 */
#include "BLI_tempfile.h"
#include "BLI_fileops.h"
#include "BLI_path_util.h"
#include "testing/testing.h"
namespace blender::tests {
TEST(BLI_tempfile, BLI_temp_directory_path_get)
{
char temp_dir[FILE_MAX];
BLI_temp_directory_path_get(temp_dir, sizeof(temp_dir));
ASSERT_STRNE(temp_dir, "");
EXPECT_EQ(temp_dir[strlen(temp_dir) - 1], SEP);
EXPECT_TRUE(BLI_exists(temp_dir));
EXPECT_TRUE(BLI_is_dir(temp_dir));
EXPECT_TRUE(BLI_path_is_abs_from_cwd(temp_dir));
}
} // namespace blender::tests

View File

@ -91,7 +91,7 @@
* \subsection bm_ops Operators
*
* Operators are an integral part of BMesh. Unlike regular blender operators,
* BMesh operators **bmo's** are designed to be nested (e.g. call other operators).
* BMesh operators (abbreviated to `bmo`) are designed to be nested (e.g. call other operators).
*
* Each operator has a number of input/output "slots"
* which are used to pass settings & data into/out of the operator

View File

@ -269,7 +269,7 @@ static void convolve(float *dst, MemoryBuffer *in1, MemoryBuffer *in2)
data1 = (fREAL *)MEM_callocN(3 * w2 * h2 * sizeof(fREAL), "convolve_fast FHT data1");
data2 = (fREAL *)MEM_callocN(w2 * h2 * sizeof(fREAL), "convolve_fast FHT data2");
/* Normalize convolutor. */
/* Normalize convolution. */
wt[0] = wt[1] = wt[2] = 0.0f;
for (y = 0; y < kernel_height; y++) {
colp = (fRGB *)&kernel_buffer[y * kernel_width * COM_DATA_TYPE_COLOR_CHANNELS];

View File

@ -63,17 +63,21 @@ set(SRC
COM_utilities.hh
algorithms/intern/algorithm_parallel_reduction.cc
algorithms/intern/smaa.cc
algorithms/intern/symmetric_separable_blur.cc
algorithms/COM_algorithm_parallel_reduction.hh
algorithms/COM_algorithm_smaa.hh
algorithms/COM_algorithm_symmetric_separable_blur.hh
cached_resources/intern/morphological_distance_feather_weights.cc
cached_resources/intern/smaa_precomputed_textures.cc
cached_resources/intern/symmetric_blur_weights.cc
cached_resources/intern/symmetric_separable_blur_weights.cc
cached_resources/COM_cached_resource.hh
cached_resources/COM_morphological_distance_feather_weights.hh
cached_resources/COM_smaa_precomputed_textures.hh
cached_resources/COM_symmetric_blur_weights.hh
cached_resources/COM_symmetric_separable_blur_weights.hh
)
@ -122,6 +126,9 @@ set(GLSL_SRC
shaders/compositor_read_pass.glsl
shaders/compositor_realize_on_domain.glsl
shaders/compositor_screen_lens_distortion.glsl
shaders/compositor_smaa_blending_weight_calculation.glsl
shaders/compositor_smaa_edge_detection.glsl
shaders/compositor_smaa_neighborhood_blending.glsl
shaders/compositor_split_viewer.glsl
shaders/compositor_symmetric_blur.glsl
shaders/compositor_symmetric_blur_variable_size.glsl
@ -211,6 +218,7 @@ set(SRC_SHADER_CREATE_INFOS
shaders/infos/compositor_read_pass_info.hh
shaders/infos/compositor_realize_on_domain_info.hh
shaders/infos/compositor_screen_lens_distortion_info.hh
shaders/infos/compositor_smaa_info.hh
shaders/infos/compositor_split_viewer_info.hh
shaders/infos/compositor_symmetric_blur_info.hh
shaders/infos/compositor_symmetric_blur_variable_size_info.hh

View File

@ -8,6 +8,7 @@
#include "BLI_math_vector_types.hh"
#include "COM_morphological_distance_feather_weights.hh"
#include "COM_smaa_precomputed_textures.hh"
#include "COM_symmetric_blur_weights.hh"
#include "COM_symmetric_separable_blur_weights.hh"
@ -47,6 +48,9 @@ class StaticCacheManager {
Map<MorphologicalDistanceFeatherWeightsKey, std::unique_ptr<MorphologicalDistanceFeatherWeights>>
morphological_distance_feather_weights_;
/* A unique pointers that stores the cached SMAAPrecomputedTextures, if one is cached. */
std::unique_ptr<SMAAPrecomputedTextures> smaa_precomputed_textures_;
public:
/* Reset the cache manager by deleting the cached resources that are no longer needed because
* they weren't used in the last evaluation and prepare the remaining cached resources to track
@ -72,6 +76,11 @@ class StaticCacheManager {
* cached for the next evaluation. */
MorphologicalDistanceFeatherWeights &get_morphological_distance_feather_weights(int type,
int radius);
/* Check if a cached SMAA precomputed texture exists, if it does, return it, otherwise, return
* a newly created one and store it in the manager. In both cases, tag the cached resource as
* needed to keep it cached for the next evaluation. */
SMAAPrecomputedTextures &get_smaa_precomputed_textures();
};
} // namespace blender::realtime_compositor

View File

@ -0,0 +1,20 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
#include "COM_context.hh"
#include "COM_result.hh"
namespace blender::realtime_compositor {
/* Anti-alias the given input using the SMAA algorithm and write the result into the given output.
* See the SMAA_THRESHOLD, SMAA_LOCAL_CONTRAST_ADAPTATION_FACTOR, and SMAA_CORNER_ROUNDING defines
* in gpu_shader_smaa_lib.glsl for information on the parameters. */
void smaa(Context &context,
Result &input,
Result &output,
float threshold,
float local_contrast_adaptation_factor,
int corner_rounding);
} // namespace blender::realtime_compositor

View File

@ -0,0 +1,115 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "IMB_colormanagement.h"
#include "GPU_shader.h"
#include "GPU_texture.h"
#include "COM_context.hh"
#include "COM_utilities.hh"
#include "COM_algorithm_smaa.hh"
#include "COM_smaa_precomputed_textures.hh"
namespace blender::realtime_compositor {
static Result detect_edges(Context &context,
Result &input,
float threshold,
float local_contrast_adaptation_factor)
{
GPUShader *shader = context.shader_manager().get("compositor_smaa_edge_detection");
GPU_shader_bind(shader);
float luminance_coefficients[3];
IMB_colormanagement_get_luminance_coefficients(luminance_coefficients);
GPU_shader_uniform_3fv(shader, "luminance_coefficients", luminance_coefficients);
GPU_shader_uniform_1f(shader, "smaa_threshold", threshold);
GPU_shader_uniform_1f(
shader, "smaa_local_contrast_adaptation_factor", local_contrast_adaptation_factor);
GPU_texture_filter_mode(input.texture(), true);
input.bind_as_texture(shader, "input_tx");
Result edges = Result::Temporary(ResultType::Color, context.texture_pool());
edges.allocate_texture(input.domain());
edges.bind_as_image(shader, "edges_img");
compute_dispatch_threads_at_least(shader, input.domain().size);
GPU_shader_unbind();
input.unbind_as_texture();
edges.unbind_as_image();
return edges;
}
static Result calculate_blending_weights(Context &context, Result &edges, int corner_rounding)
{
GPUShader *shader = context.shader_manager().get("compositor_smaa_blending_weight_calculation");
GPU_shader_bind(shader);
GPU_shader_uniform_1i(shader, "smaa_corner_rounding", corner_rounding);
GPU_texture_filter_mode(edges.texture(), true);
edges.bind_as_texture(shader, "edges_tx");
const SMAAPrecomputedTextures &smaa_precomputed_textures =
context.cache_manager().get_smaa_precomputed_textures();
smaa_precomputed_textures.bind_area_texture(shader, "area_tx");
smaa_precomputed_textures.bind_search_texture(shader, "search_tx");
Result weights = Result::Temporary(ResultType::Color, context.texture_pool());
weights.allocate_texture(edges.domain());
weights.bind_as_image(shader, "weights_img");
compute_dispatch_threads_at_least(shader, edges.domain().size);
GPU_shader_unbind();
edges.unbind_as_texture();
smaa_precomputed_textures.unbind_area_texture();
smaa_precomputed_textures.unbind_search_texture();
weights.unbind_as_image();
return weights;
}
static void blend_neighborhood(Context &context, Result &input, Result &weights, Result &output)
{
GPUShader *shader = context.shader_manager().get("compositor_smaa_neighborhood_blending");
GPU_shader_bind(shader);
GPU_texture_filter_mode(input.texture(), true);
input.bind_as_texture(shader, "input_tx");
GPU_texture_filter_mode(weights.texture(), true);
weights.bind_as_texture(shader, "weights_tx");
output.allocate_texture(input.domain());
output.bind_as_image(shader, "output_img");
compute_dispatch_threads_at_least(shader, input.domain().size);
GPU_shader_unbind();
input.unbind_as_texture();
weights.unbind_as_texture();
output.unbind_as_image();
}
void smaa(Context &context,
Result &input,
Result &output,
float threshold,
float local_contrast_adaptation_factor,
int corner_rounding)
{
Result edges = detect_edges(context, input, threshold, local_contrast_adaptation_factor);
Result weights = calculate_blending_weights(context, edges, corner_rounding);
edges.release();
blend_neighborhood(context, input, weights, output);
weights.release();
}
} // namespace blender::realtime_compositor

View File

@ -0,0 +1,36 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
#include "GPU_shader.h"
#include "GPU_texture.h"
#include "COM_cached_resource.hh"
namespace blender::realtime_compositor {
/* -------------------------------------------------------------------------------------------------
* SMAA Precomputed Textures.
*
* A cached resource that caches the precomputed textures needed by the SMAA algorithm. The
* precomputed textures are constants, so this is a parameterless cached resource. */
class SMAAPrecomputedTextures : public CachedResource {
private:
GPUTexture *search_texture_ = nullptr;
GPUTexture *area_texture_ = nullptr;
public:
SMAAPrecomputedTextures();
~SMAAPrecomputedTextures();
void bind_search_texture(GPUShader *shader, const char *sampler_name) const;
void unbind_search_texture() const;
void bind_area_texture(GPUShader *shader, const char *sampler_name) const;
void unbind_area_texture() const;
};
} // namespace blender::realtime_compositor

View File

@ -0,0 +1,64 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BLI_smaa_textures.h"
#include "GPU_shader.h"
#include "GPU_texture.h"
#include "COM_smaa_precomputed_textures.hh"
namespace blender::realtime_compositor {
SMAAPrecomputedTextures::SMAAPrecomputedTextures()
{
search_texture_ = GPU_texture_create_2d("SMAA Search",
SEARCHTEX_WIDTH,
SEARCHTEX_HEIGHT,
1,
GPU_R8,
GPU_TEXTURE_USAGE_SHADER_READ,
nullptr);
GPU_texture_update(search_texture_, GPU_DATA_UBYTE, searchTexBytes);
GPU_texture_filter_mode(search_texture_, true);
area_texture_ = GPU_texture_create_2d("SMAA Area",
AREATEX_WIDTH,
AREATEX_HEIGHT,
1,
GPU_RG8,
GPU_TEXTURE_USAGE_SHADER_READ,
nullptr);
GPU_texture_update(area_texture_, GPU_DATA_UBYTE, areaTexBytes);
GPU_texture_filter_mode(area_texture_, true);
}
SMAAPrecomputedTextures::~SMAAPrecomputedTextures()
{
GPU_texture_free(search_texture_);
GPU_texture_free(area_texture_);
}
void SMAAPrecomputedTextures::bind_search_texture(GPUShader *shader,
const char *sampler_name) const
{
const int texture_image_unit = GPU_shader_get_sampler_binding(shader, sampler_name);
GPU_texture_bind(search_texture_, texture_image_unit);
}
void SMAAPrecomputedTextures::unbind_search_texture() const
{
GPU_texture_unbind(search_texture_);
}
void SMAAPrecomputedTextures::bind_area_texture(GPUShader *shader, const char *sampler_name) const
{
const int texture_image_unit = GPU_shader_get_sampler_binding(shader, sampler_name);
GPU_texture_bind(area_texture_, texture_image_unit);
}
void SMAAPrecomputedTextures::unbind_area_texture() const
{
GPU_texture_unbind(area_texture_);
}
} // namespace blender::realtime_compositor

View File

@ -5,6 +5,7 @@
#include "BLI_math_vector_types.hh"
#include "COM_morphological_distance_feather_weights.hh"
#include "COM_smaa_precomputed_textures.hh"
#include "COM_symmetric_blur_weights.hh"
#include "COM_symmetric_separable_blur_weights.hh"
@ -22,6 +23,9 @@ void StaticCacheManager::reset()
symmetric_blur_weights_.remove_if([](auto item) { return !item.value->needed; });
symmetric_separable_blur_weights_.remove_if([](auto item) { return !item.value->needed; });
morphological_distance_feather_weights_.remove_if([](auto item) { return !item.value->needed; });
if (smaa_precomputed_textures_ && !smaa_precomputed_textures_->needed) {
smaa_precomputed_textures_.reset();
}
/* Second, reset the needed status of the remaining resources to false to ready them to track
* their needed status for the next evaluation. */
@ -34,6 +38,9 @@ void StaticCacheManager::reset()
for (auto &value : morphological_distance_feather_weights_.values()) {
value->needed = false;
}
if (smaa_precomputed_textures_) {
smaa_precomputed_textures_->needed = false;
}
}
SymmetricBlurWeights &StaticCacheManager::get_symmetric_blur_weights(int type, float2 radius)
@ -71,4 +78,14 @@ MorphologicalDistanceFeatherWeights &StaticCacheManager::
return weights;
}
SMAAPrecomputedTextures &StaticCacheManager::get_smaa_precomputed_textures()
{
if (!smaa_precomputed_textures_) {
smaa_precomputed_textures_ = std::make_unique<SMAAPrecomputedTextures>();
}
smaa_precomputed_textures_->needed = true;
return *smaa_precomputed_textures_;
}
} // namespace blender::realtime_compositor

View File

@ -1,5 +1,3 @@
#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl)
void main()
{
/* The dispatch domain covers the output image size, which might be a fraction of the input image
@ -7,16 +5,9 @@ void main()
* one. */
ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
/* Since the output image might be a fraction of the input image size, and since we want to
* evaluate the input sampler at the center of the output pixel, we add an offset equal to half
* the number of input pixels that covers a single output pixel. In case the input and output
* have the same size, this will be 0.5, which is the offset required to evaluate the sampler at
* the center of the pixel. */
vec2 offset = vec2(texture_size(input_tx) / imageSize(output_img)) / 2.0;
/* Add the aforementioned offset and divide by the output image size to get the coordinates into
* the sampler's expected [0, 1] range. */
vec2 normalized_coordinates = (vec2(texel) + offset) / vec2(imageSize(output_img));
/* Add 0.5 to evaluate the input sampler at the center of the pixel and divide by the image size
* to get the coordinates into the sampler's expected [0, 1] range. */
vec2 normalized_coordinates = (vec2(texel) + vec2(0.5)) / vec2(imageSize(output_img));
vec4 input_color = texture(input_tx, normalized_coordinates);
float luminance = dot(input_color.rgb, luminance_coefficients);

View File

@ -0,0 +1,19 @@
#pragma BLENDER_REQUIRE(gpu_shader_smaa_lib.glsl)
#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl)
void main()
{
ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
/* Add 0.5 to evaluate the input sampler at the center of the pixel and divide by the image size
* to get the coordinates into the sampler's expected [0, 1] range. */
vec2 coordinates = (vec2(texel) + vec2(0.5)) / vec2(texture_size(edges_tx));
float4 offset[3];
vec2 pixel_coordinates;
SMAABlendingWeightCalculationVS(coordinates, pixel_coordinates, offset);
vec4 weights = SMAABlendingWeightCalculationPS(
coordinates, pixel_coordinates, offset, edges_tx, area_tx, search_tx, vec4(0.0));
imageStore(weights_img, texel, weights);
}

View File

@ -0,0 +1,17 @@
#pragma BLENDER_REQUIRE(gpu_shader_smaa_lib.glsl)
#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl)
void main()
{
ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
/* Add 0.5 to evaluate the input sampler at the center of the pixel and divide by the image size
* to get the coordinates into the sampler's expected [0, 1] range. */
vec2 coordinates = (vec2(texel) + vec2(0.5)) / vec2(texture_size(input_tx));
float4 offset[3];
SMAAEdgeDetectionVS(coordinates, offset);
vec2 edge = SMAALumaEdgeDetectionPS(coordinates, offset, input_tx);
imageStore(edges_img, texel, vec4(edge, vec2(0.0)));
}

View File

@ -0,0 +1,17 @@
#pragma BLENDER_REQUIRE(gpu_shader_smaa_lib.glsl)
#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl)
void main()
{
ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
/* Add 0.5 to evaluate the input sampler at the center of the pixel and divide by the image size
* to get the coordinates into the sampler's expected [0, 1] range. */
vec2 coordinates = (vec2(texel) + vec2(0.5)) / vec2(texture_size(input_tx));
vec4 offset;
SMAANeighborhoodBlendingVS(coordinates, offset);
vec4 result = SMAANeighborhoodBlendingPS(coordinates, offset, input_tx, weights_tx);
imageStore(output_img, texel, result);
}

View File

@ -0,0 +1,44 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "gpu_shader_create_info.hh"
GPU_SHADER_CREATE_INFO(compositor_smaa_edge_detection)
.local_group_size(16, 16)
.define("SMAA_GLSL_3")
.define("SMAA_RT_METRICS",
"vec4(1.0 / vec2(textureSize(input_tx, 0)), vec2(textureSize(input_tx, 0)))")
.define("SMAA_LUMA_WEIGHT", "vec4(luminance_coefficients, 0.0)")
.define("SMAA_THRESHOLD", "smaa_threshold")
.define("SMAA_LOCAL_CONTRAST_ADAPTATION_FACTOR", "smaa_local_contrast_adaptation_factor")
.push_constant(Type::VEC3, "luminance_coefficients")
.push_constant(Type::FLOAT, "smaa_threshold")
.push_constant(Type::FLOAT, "smaa_local_contrast_adaptation_factor")
.sampler(0, ImageType::FLOAT_2D, "input_tx")
.image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "edges_img")
.compute_source("compositor_smaa_edge_detection.glsl")
.do_static_compilation(true);
GPU_SHADER_CREATE_INFO(compositor_smaa_blending_weight_calculation)
.local_group_size(16, 16)
.define("SMAA_GLSL_3")
.define("SMAA_RT_METRICS",
"vec4(1.0 / vec2(textureSize(edges_tx, 0)), vec2(textureSize(edges_tx, 0)))")
.define("SMAA_CORNER_ROUNDING", "smaa_corner_rounding")
.push_constant(Type::INT, "smaa_corner_rounding")
.sampler(0, ImageType::FLOAT_2D, "edges_tx")
.sampler(1, ImageType::FLOAT_2D, "area_tx")
.sampler(2, ImageType::FLOAT_2D, "search_tx")
.image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "weights_img")
.compute_source("compositor_smaa_blending_weight_calculation.glsl")
.do_static_compilation(true);
GPU_SHADER_CREATE_INFO(compositor_smaa_neighborhood_blending)
.local_group_size(16, 16)
.define("SMAA_GLSL_3")
.define("SMAA_RT_METRICS",
"vec4(1.0 / vec2(textureSize(input_tx, 0)), vec2(textureSize(input_tx, 0)))")
.sampler(0, ImageType::FLOAT_2D, "input_tx")
.sampler(1, ImageType::FLOAT_2D, "weights_tx")
.image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img")
.compute_source("compositor_smaa_neighborhood_blending.glsl")
.do_static_compilation(true);

View File

@ -41,7 +41,7 @@ static inline bool is_removable_relation(const Relation *relation)
/* If the relation connects two different IDs there is a high risk that the removal of the
* relation will make it so visibility flushing is not possible at runtime. This happens with
* relations like the DoF on camera of custom shape on bines: such relation do not lead to an
* relations like the DoF on camera of custom shape on bones: such relation do not lead to an
* actual depsgraph evaluation operation as they are handled on render engine level.
*
* The indirectly linked objects could have some of their components invisible as well, so

View File

@ -103,7 +103,6 @@ set(SRC
intern/draw_view.c
intern/draw_view_data.cc
intern/draw_volume.cc
intern/smaa_textures.c
engines/basic/basic_engine.c
engines/basic/basic_shader.c
engines/compositor/compositor_engine.cc
@ -260,7 +259,6 @@ set(SRC
intern/draw_view.hh
intern/draw_view_data.h
intern/mesh_extractors/extract_mesh.hh
intern/smaa_textures.h
engines/basic/basic_engine.h
engines/basic/basic_private.h
engines/compositor/compositor_engine.h
@ -554,7 +552,6 @@ set(GLSL_SRC
intern/shaders/common_math_lib.glsl
intern/shaders/common_pointcloud_lib.glsl
intern/shaders/common_shape_lib.glsl
intern/shaders/common_smaa_lib.glsl
intern/shaders/common_subdiv_custom_data_interp_comp.glsl
intern/shaders/common_subdiv_ibo_lines_comp.glsl
intern/shaders/common_subdiv_ibo_tris_comp.glsl

View File

@ -85,7 +85,7 @@ void eevee_shader_material_create_info_amend(GPUMaterial *gpumat,
info.vertex_inputs_.clear();
}
else if (do_fragment_attrib_load && !info.vertex_out_interfaces_.is_empty()) {
/* Codegen outputs only one interface. */
/* Code-generation outputs only one interface. */
const StageInterfaceInfo &iface = *info.vertex_out_interfaces_.first();
/* Globals the attrib_load() can write to when it is in the fragment shader. */
attr_load << "struct " << iface.name << " {\n";

View File

@ -9,7 +9,7 @@
#include "gpencil_engine.h"
#include "smaa_textures.h"
#include "BLI_smaa_textures.h"
void GPENCIL_antialiasing_init(struct GPENCIL_Data *vedata)
{

View File

@ -21,7 +21,6 @@ extern char datatoc_gpencil_vfx_frag_glsl[];
extern char datatoc_common_colormanagement_lib_glsl[];
extern char datatoc_common_fullscreen_vert_glsl[];
extern char datatoc_common_smaa_lib_glsl[];
extern char datatoc_common_view_lib_glsl[];
static struct {

View File

@ -1,5 +1,5 @@
#pragma BLENDER_REQUIRE(common_smaa_lib.glsl)
#pragma BLENDER_REQUIRE(gpu_shader_smaa_lib.glsl)
void main()
{

View File

@ -1,5 +1,5 @@
#pragma BLENDER_REQUIRE(common_smaa_lib.glsl)
#pragma BLENDER_REQUIRE(gpu_shader_smaa_lib.glsl)
void main()
{

View File

@ -61,10 +61,8 @@ void OVERLAY_edit_mesh_cache_init(OVERLAY_Data *vedata)
bool show_face_dots = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FACE_DOT) != 0 ||
pd->edit_mesh.do_zbufclip;
bool show_retopology = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_RETOPOLOGY) != 0;
float retopology_offset = (show_retopology) ?
max_ff(v3d->overlay.retopology_offset, FLT_EPSILON) :
0.0f;
bool show_retopology = RETOPOLOGY_ENABLED(v3d);
float retopology_offset = RETOPOLOGY_OFFSET(v3d);
pd->edit_mesh.do_faces = true;
pd->edit_mesh.do_edges = true;

View File

@ -3,7 +3,7 @@
#include "gpu_shader_create_info.hh"
/* -------------------------------------------------------------------- */
/** \name Outline Prepass
/** \name Outline Pre-pass
* \{ */
GPU_SHADER_INTERFACE_INFO(overlay_outline_prepass_iface, "interp").flat(Type::UINT, "ob_id");

View File

@ -1,5 +1,5 @@
#pragma BLENDER_REQUIRE(common_smaa_lib.glsl)
#pragma BLENDER_REQUIRE(gpu_shader_smaa_lib.glsl)
void main()
{

View File

@ -1,5 +1,5 @@
#pragma BLENDER_REQUIRE(common_smaa_lib.glsl)
#pragma BLENDER_REQUIRE(gpu_shader_smaa_lib.glsl)
void main()
{

View File

@ -20,7 +20,7 @@
#include "BLI_jitter_2d.h"
#include "smaa_textures.h"
#include "BLI_smaa_textures.h"
#include "workbench_private.h"

View File

@ -3,7 +3,7 @@
#include "workbench_private.hh"
#include "BLI_jitter_2d.h"
#include "smaa_textures.h"
#include "BLI_smaa_textures.h"
namespace blender::workbench {

View File

@ -188,7 +188,7 @@ bool DRW_object_is_renderable(const Object *ob)
if (ob->type == OB_MESH) {
if ((ob == DST.draw_ctx.object_edit) || DRW_object_is_in_edit_mode(ob)) {
View3D *v3d = DST.draw_ctx.v3d;
if (v3d && v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_RETOPOLOGY) {
if (v3d && RETOPOLOGY_ENABLED(v3d)) {
return false;
}
}

View File

@ -281,6 +281,12 @@ static bool find_fcurve_segment(FCurve *fcu,
ListBase find_fcurve_segments(FCurve *fcu)
{
ListBase segments = {NULL, NULL};
/* Ignore baked curves. */
if (!fcu->bezt) {
return segments;
}
int segment_start_idx = 0;
int segment_len = 0;
int current_index = 0;

View File

@ -1097,7 +1097,7 @@ static void extrude_points_from_selected_vertices(const ViewContext *vc,
if (sel_exists) {
float disp_3d[3];
sub_v3_v3v3(disp_3d, location, center);
/* Reimplemenented due to unexpected behavior for extrusion of 2-point spline. */
/* Reimplemented due to unexpected behavior for extrusion of 2-point spline. */
extrude_vertices_from_selected_endpoints(editnurb, nurbs, cu, disp_3d);
}
else {

View File

@ -695,6 +695,7 @@ static void snap_curves_to_surface_exec_object(Object &curves_ob,
}
}
curves.tag_positions_changed();
DEG_id_tag_update(&curves_id.id, ID_RECALC_GEOMETRY);
}

View File

@ -1328,6 +1328,14 @@ void ED_view3d_shade_update(struct Main *bmain, struct View3D *v3d, struct ScrAr
#define XRAY_ENABLED(v3d) SHADING_XRAY_ENABLED((v3d)->shading)
#define XRAY_ACTIVE(v3d) SHADING_XRAY_ACTIVE((v3d)->shading)
#define OVERLAY_RETOPOLOGY_ENABLED(overlay) \
(((overlay).edit_flag & V3D_OVERLAY_EDIT_RETOPOLOGY) != 0)
#define OVERLAY_RETOPOLOGY_OFFSET(overlay) \
(OVERLAY_RETOPOLOGY_ENABLED(overlay) ? max_ff((overlay).retopology_offset, FLT_EPSILON) : 0.0f)
#define RETOPOLOGY_ENABLED(v3d) (OVERLAY_RETOPOLOGY_ENABLED((v3d)->overlay))
#define RETOPOLOGY_OFFSET(v3d) (OVERLAY_RETOPOLOGY_OFFSET((v3d)->overlay))
/* view3d_draw_legacy.c */
/**

View File

@ -512,6 +512,7 @@ bool paintface_mouse_select(bContext *C,
ED_region_tag_redraw(CTX_wm_region(C)); /* XXX: should redraw all 3D views. */
changed = true;
}
select_poly.finish();
return changed || found;
}

View File

@ -34,11 +34,13 @@
#include "ED_mesh.h"
#include "paint_intern.h" /* own include */
#include "sculpt_intern.hh"
using blender::Array;
using blender::ColorGeometry4f;
using blender::GMutableSpan;
using blender::IndexMask;
using blender::IndexRange;
using blender::Vector;
/* -------------------------------------------------------------------- */
@ -245,20 +247,20 @@ void PAINT_OT_vertex_color_smooth(wmOperatorType *ot)
* \{ */
template<typename TransformFn>
static bool transform_active_color(Mesh &mesh, const TransformFn &transform_fn)
static void transform_active_color_data(Mesh &mesh, const TransformFn &transform_fn)
{
using namespace blender;
const StringRef name = mesh.active_color_attribute;
bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
if (!attributes.contains(name)) {
BLI_assert_unreachable();
return false;
return;
}
bke::GAttributeWriter color_attribute = attributes.lookup_for_write(name);
if (!color_attribute) {
BLI_assert_unreachable();
return false;
return;
}
Vector<int64_t> indices;
@ -286,8 +288,34 @@ static bool transform_active_color(Mesh &mesh, const TransformFn &transform_fn)
color_attribute.finish();
DEG_id_tag_update(&mesh.id, 0);
}
return true;
template<typename TransformFn>
static void transform_active_color(bContext *C, wmOperator *op, const TransformFn &transform_fn)
{
Object *obact = CTX_data_active_object(C);
/* Ensure valid sculpt state. */
BKE_sculpt_update_object_for_edit(
CTX_data_ensure_evaluated_depsgraph(C), obact, true, false, true);
SCULPT_undo_push_begin(obact, op);
PBVHNode **nodes;
int nodes_num;
BKE_pbvh_search_gather(obact->sculpt->pbvh, nullptr, nullptr, &nodes, &nodes_num);
for (int i : IndexRange(nodes_num)) {
SCULPT_undo_push_node(obact, nodes[i], SCULPT_UNDO_COLOR);
}
transform_active_color_data(*BKE_mesh_from_object(obact), transform_fn);
for (int i : IndexRange(nodes_num)) {
BKE_pbvh_node_mark_update_color(nodes[i]);
}
SCULPT_undo_push_end(obact);
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obact);
}
static int vertex_color_brightness_contrast_exec(bContext *C, wmOperator *op)
@ -323,14 +351,12 @@ static int vertex_color_brightness_contrast_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
transform_active_color(*me, [&](ColorGeometry4f &color) {
transform_active_color(C, op, [&](ColorGeometry4f &color) {
for (int i = 0; i < 3; i++) {
color[i] = gain * color[i] + offset;
}
});
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obact);
return OPERATOR_FINISHED;
}
@ -371,7 +397,7 @@ static int vertex_color_hsv_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
transform_active_color(*me, [&](ColorGeometry4f &color) {
transform_active_color(C, op, [&](ColorGeometry4f &color) {
float hsv[3];
rgb_to_hsv_v(color, hsv);
@ -388,8 +414,6 @@ static int vertex_color_hsv_exec(bContext *C, wmOperator *op)
hsv_to_rgb_v(hsv, color);
});
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obact);
return OPERATOR_FINISHED;
}
@ -413,7 +437,7 @@ void PAINT_OT_vertex_color_hsv(wmOperatorType *ot)
RNA_def_float(ot->srna, "v", 1.0f, 0.0f, 2.0f, "Value", "", 0.0f, 2.0f);
}
static int vertex_color_invert_exec(bContext *C, wmOperator * /*op*/)
static int vertex_color_invert_exec(bContext *C, wmOperator *op)
{
Object *obact = CTX_data_active_object(C);
@ -423,14 +447,12 @@ static int vertex_color_invert_exec(bContext *C, wmOperator * /*op*/)
return OPERATOR_CANCELLED;
}
transform_active_color(*me, [&](ColorGeometry4f &color) {
transform_active_color(C, op, [&](ColorGeometry4f &color) {
for (int i = 0; i < 3; i++) {
color[i] = 1.0f - color[i];
}
});
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obact);
return OPERATOR_FINISHED;
}
@ -462,7 +484,7 @@ static int vertex_color_levels_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
transform_active_color(*me, [&](ColorGeometry4f &color) {
transform_active_color(C, op, [&](ColorGeometry4f &color) {
for (int i = 0; i < 3; i++) {
color[i] = gain * (color[i] + offset);
}

View File

@ -480,7 +480,7 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *region
/** \name Timeline - Caches
* \{ */
static bool timeline_cache_is_hidden_by_setting(SpaceAction *saction, PTCacheID *pid)
static bool timeline_cache_is_hidden_by_setting(const SpaceAction *saction, const PTCacheID *pid)
{
switch (pid->type) {
case PTCACHE_TYPE_SOFTBODY:
@ -674,14 +674,14 @@ static void timeline_cache_draw_single(PTCacheID *pid, float y_offset, float hei
GPU_matrix_pop();
}
void timeline_draw_cache(SpaceAction *saction, Object *ob, Scene *scene)
void timeline_draw_cache(const SpaceAction *saction, const Object *ob, const Scene *scene)
{
if ((saction->cache_display & TIME_CACHE_DISPLAY) == 0 || ob == nullptr) {
return;
}
ListBase pidlist;
BKE_ptcache_ids_from_object(&pidlist, ob, scene, 0);
BKE_ptcache_ids_from_object(&pidlist, const_cast<Object *>(ob), const_cast<Scene *>(scene), 0);
uint pos_id = GPU_vertformat_attr_add(
immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);

View File

@ -35,7 +35,7 @@ void draw_channel_names(bContext *C, bAnimContext *ac, ARegion *region);
*/
void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *region);
void timeline_draw_cache(SpaceAction *saction, Object *ob, Scene *scene);
void timeline_draw_cache(const SpaceAction *saction, const Object *ob, const Scene *scene);
/* ***************************************** */
/* action_select.c */

View File

@ -44,6 +44,8 @@
#include "BLO_read_write.h"
#include "GPU_matrix.h"
#include "action_intern.hh" /* own include */
/* -------------------------------------------------------------------- */
@ -212,11 +214,6 @@ static void action_main_region_draw(const bContext *C, ARegion *region)
ED_markers_draw(C, marker_flag);
}
/* caches */
if (saction->mode == SACTCONT_TIMELINE) {
timeline_draw_cache(saction, obact, scene);
}
/* preview range */
UI_view2d_view_ortho(v2d);
ANIM_draw_previewrange(C, v2d, 0);
@ -240,8 +237,17 @@ static void action_main_region_draw_overlay(const bContext *C, ARegion *region)
/* draw entirely, view changes should be handled here */
const SpaceAction *saction = CTX_wm_space_action(C);
const Scene *scene = CTX_data_scene(C);
const Object *obact = CTX_data_active_object(C);
View2D *v2d = &region->v2d;
/* caches */
if (saction->mode == SACTCONT_TIMELINE) {
GPU_matrix_push_projection();
UI_view2d_view_orthoSpecial(region, v2d, 1);
timeline_draw_cache(saction, obact, scene);
GPU_matrix_pop_projection();
}
/* scrubbing region */
ED_time_scrub_draw_current_frame(region, scene, saction->flag & SACTION_DRAWTIME);

View File

@ -703,7 +703,7 @@ static void draw_fcurve_curve_samples(bAnimContext *ac,
const uint shdr_pos,
const bool draw_extrapolation)
{
if (!draw_extrapolation) {
if (!draw_extrapolation && fcu->totvert == 1) {
return;
}
@ -816,7 +816,7 @@ static bool fcurve_can_use_simple_bezt_drawing(FCurve *fcu)
static void draw_fcurve_curve_bezts(
bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d, uint pos, const bool draw_extrapolation)
{
if (!draw_extrapolation) {
if (!draw_extrapolation && fcu->totvert == 1) {
return;
}

View File

@ -1136,12 +1136,11 @@ static void gaussian_smooth_free_operator_data(void *operator_data)
static void gaussian_smooth_draw_status_header(bContext *C, tGraphSliderOp *gso)
{
char status_str[UI_MAX_DRAW_STR];
char mode_str[32];
char slider_string[UI_MAX_DRAW_STR];
ED_slider_status_string_get(gso->slider, slider_string, UI_MAX_DRAW_STR);
strcpy(mode_str, TIP_("Gauss Smooth"));
const char *mode_str = TIP_("Gaussian Smooth");
if (hasNumInput(&gso->num)) {
char str_ofs[NUM_STR_REP_LEN];
@ -1274,7 +1273,7 @@ void GRAPH_OT_gaussian_smooth(wmOperatorType *ot)
/* Identifiers. */
ot->name = "Gaussian Smooth";
ot->idname = "GRAPH_OT_gaussian_smooth";
ot->description = "Smooth the curve using a Gauss filter";
ot->description = "Smooth the curve using a Gaussian filter";
/* API callbacks. */
ot->invoke = gaussian_smooth_invoke;
@ -1301,7 +1300,7 @@ void GRAPH_OT_gaussian_smooth(wmOperatorType *ot)
0.001f,
FLT_MAX,
"Sigma",
"The shape of the gauss distribution, lower values make it sharper",
"The shape of the gaussian distribution, lower values make it sharper",
0.001f,
100.0f);

View File

@ -805,7 +805,7 @@ static bool image_undosys_step_encode(struct bContext *C, struct Main * /*bmain*
us_reference = reinterpret_cast<ImageUndoStep *>(us_reference->step.prev);
}
/* Initialize undo tiles from ptiles (if they exist). */
/* Initialize undo tiles from paint-tiles (if they exist). */
for (PaintTile *ptile : us->paint_tile_map->map.values()) {
if (ptile->valid) {
UndoImageHandle *uh = uhandle_ensure(&us->handles, ptile->image, &ptile->iuser);

View File

@ -263,8 +263,11 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op)
const float2 offset = (mouse_location - center) / UI_SCALE_FAC;
for (bNode *new_node : node_map.values()) {
new_node->locx += offset.x;
new_node->locy += offset.y;
/* Skip the offset for parented nodes since the location is in parent space. */
if (new_node->parent == nullptr) {
new_node->locx += offset.x;
new_node->locy += offset.y;
}
}
}

View File

@ -2722,7 +2722,8 @@ static void frame_node_prepare_for_draw(bNode &node, Span<bNode *> nodes)
const float has_label = node.label[0] != '\0';
const float label_height = frame_node_label_height(*data);
/* Add an additional 25 % to account for the descenders. This works well in most cases. */
/* Add an additional 25% to account for the glyphs descender.
* This works well in most cases. */
const float margin_top = 0.5f * margin + (has_label ? 1.25f * label_height : 0.5f * margin);
/* Initialize rect from current frame size. */

View File

@ -419,16 +419,6 @@ static int transform_modal(bContext *C, wmOperator *op, const wmEvent *event)
exit_code = transformEvent(t, event);
t->context = NULL;
/* XXX, workaround: active needs to be calculated before transforming,
* since we're not reading from 'td->center' in this case. see: #40241 */
if (t->tsnap.source_operation == SCE_SNAP_SOURCE_ACTIVE) {
/* In camera view, tsnap callback is not set
* (see #initSnappingMode() in transform_snap.c, and #40348). */
if (t->tsnap.snap_source_fn && ((t->tsnap.status & SNAP_SOURCE_FOUND) == 0)) {
t->tsnap.snap_source_fn(t);
}
}
transformApply(C, t);
exit_code |= transformEnd(C, t);

View File

@ -947,6 +947,11 @@ static void setSnappingCallback(TransInfo *t)
break;
case SCE_SNAP_SOURCE_ACTIVE:
t->tsnap.snap_source_fn = snap_source_active_fn;
/* XXX, workaround: active needs to be calculated before transforming, otherwise
* `t->tsnap.snap_source` will be calculated with the transformed data since we're not
* reading from 'td->center' in this case. (See: #40241 and #40348). */
snap_source_active_fn(t);
break;
}
}
@ -1230,13 +1235,18 @@ static void snap_source_active_fn(TransInfo *t)
{
/* Only need to calculate once */
if ((t->tsnap.status & SNAP_SOURCE_FOUND) == 0) {
if (calculateCenterActive(t, true, t->tsnap.snap_source)) {
if (t->around == V3D_AROUND_ACTIVE) {
/* Just copy the already calculated active center. */
copy_v3_v3(t->tsnap.snap_source, t->center_global);
TargetSnapOffset(t, nullptr);
t->tsnap.status |= SNAP_SOURCE_FOUND;
}
else if (calculateCenterActive(t, true, t->tsnap.snap_source)) {
TargetSnapOffset(t, nullptr);
t->tsnap.status |= SNAP_SOURCE_FOUND;
}
/* No active, default to median */
else {
/* No active, default to median, */
t->tsnap.source_operation = SCE_SNAP_SOURCE_MEDIAN;
t->tsnap.snap_source_fn = snap_source_median_fn;
snap_source_median_fn(t);

View File

@ -1166,8 +1166,8 @@ static bool uv_snap_uvs_to_adjacent_unselected(Scene *scene, Object *obedit)
bool changed = false;
const BMUVOffsets offsets = BM_uv_map_get_offsets(em->bm);
/* index every vert that has a selected UV using it, but only once so as to
* get unique indices and to count how much to malloc */
/* Index every vert that has a selected UV using it, but only once so as to
* get unique indices and to count how much to `malloc`. */
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
if (uvedit_face_visible_test(scene, f)) {
BM_elem_flag_enable(f, BM_ELEM_TAG);

View File

@ -280,7 +280,7 @@ class Occupancy {
mutable float witness_distance_; /* Signed distance to nearest placed island. */
mutable uint triangle_hint_; /* Hint to a previously suspected overlapping triangle. */
const float terminal = 1048576.0f; /* A "very" large number, much bigger than 4 * bitmap_radix */
const float terminal = 1048576.0f; /* 4 * bitmap_radix < terminal < INT_MAX / 4. */
};
Occupancy::Occupancy(const float initial_scale)
@ -352,8 +352,9 @@ float Occupancy::trace_triangle(const float2 &uv0,
if (iy0 <= witness_.y && witness_.y < iy1) {
const float distance = signed_distance_fat_triangle(witness_, uv0s, uv1s, uv2s);
const float extent = epsilon - distance - witness_distance_;
if (extent > 0.0f) {
return extent; /* Witness observes occupied. */
const float pixel_round_off = -0.1f; /* Go faster on nearly-axis aligned edges. */
if (extent > pixel_round_off) {
return std::max(0.0f, extent); /* Witness observes occupied. */
}
}
}
@ -392,7 +393,7 @@ float Occupancy::trace_island(PackIsland *island,
if (!write) {
if (uv.x <= 0.0f || uv.y <= 0.0f) {
return std::max(-uv.x, -uv.y); /* Occupied. */
return terminal; /* Occupied. */
}
}
const float2 origin(island->bounds_rect.xmin, island->bounds_rect.ymin);
@ -421,9 +422,21 @@ static float2 find_best_fit_for_island(
const float size_x_scaled = BLI_rctf_size_x(&island->bounds_rect) * scale;
const float size_y_scaled = BLI_rctf_size_y(&island->bounds_rect) * scale;
/* Scan using an "Alpaca"-style search, first vertically. */
/* Scan using an "Alpaca"-style search, first horizontally using "less-than". */
int t = 0;
int t = int(ceilf(size_x_scaled * occupancy.bitmap_scale_reciprocal));
while (t < scan_line) {
const float t_bscaled = t / occupancy.bitmap_scale_reciprocal;
const float2 probe(t_bscaled - size_x_scaled, scan_line_bscaled - size_y_scaled);
const float extent = occupancy.trace_island(island, scale, margin, probe, false);
if (extent < 0.0f) {
return probe;
}
t = t + std::max(1, int(extent));
}
/* Then scan vertically using "less-than-or-equal" */
t = int(ceilf(size_y_scaled * occupancy.bitmap_scale_reciprocal));
while (t <= scan_line) {
const float t_bscaled = t / occupancy.bitmap_scale_reciprocal;
const float2 probe(scan_line_bscaled - size_x_scaled, t_bscaled - size_y_scaled);
@ -434,17 +447,6 @@ static float2 find_best_fit_for_island(
t = t + std::max(1, int(extent));
}
/* Now scan horizontally. */
t = 0;
while (t <= scan_line) {
const float t_bscaled = t / occupancy.bitmap_scale_reciprocal;
const float2 probe(t_bscaled - size_x_scaled, scan_line_bscaled - size_y_scaled);
const float extent = occupancy.trace_island(island, scale, margin, probe, false);
if (extent < 0.0f) {
return probe;
}
t = t + std::max(1, int(extent));
}
return float2(-1, -1);
}
@ -458,7 +460,7 @@ static float guess_initial_scale(const Span<PackIsland *> islands,
sum += BLI_rctf_size_x(&island->bounds_rect) * scale + 2 * margin;
sum += BLI_rctf_size_y(&island->bounds_rect) * scale + 2 * margin;
}
return sqrtf(sum) / 3.0f;
return sqrtf(sum) / 6.0f;
}
/**

View File

@ -437,6 +437,7 @@ set(GLSL_SRC
shaders/common/gpu_shader_math_matrix_lib.glsl
shaders/common/gpu_shader_math_rotation_lib.glsl
shaders/common/gpu_shader_math_vector_lib.glsl
shaders/common/gpu_shader_smaa_lib.glsl
shaders/common/gpu_shader_test_lib.glsl
shaders/common/gpu_shader_utildefines_lib.glsl

View File

@ -11,7 +11,7 @@
typedef struct TestOutputRawData TestOutputRawData;
#endif
/* NOTE: float3 has differing stride and alignment rules across different GPU backends. If 12 byte
/* NOTE: float3 has differing stride and alignment rules across different GPU back-ends. If 12 byte
* stride and alignment is essential, use `packed_float3` to avoid data read issues. This is
* required in the common use-case where a float3 and an int/float are paired together for optimal
* data transfer. */

View File

@ -34,9 +34,9 @@ namespace gpu {
class GLBackend : public GPUBackend {
private:
GLSharedOrphanLists shared_orphan_list_;
#ifdef WITH_RENDERDOC
#ifdef WITH_RENDERDOC
renderdoc::api::Renderdoc renderdoc_;
#endif
#endif
public:
GLBackend()

View File

@ -774,14 +774,19 @@ float2 SMAALumaEdgeDetectionPS(float2 texcoord,
delta.xy = abs(L - float2(Lleft, Ltop));
float2 edges = step(threshold, delta.xy);
# ifndef SMAA_NO_DISCARD
# ifdef GPU_FRAGMENT_SHADER
# ifdef GPU_FRAGMENT_SHADER
# ifndef SMAA_NO_DISCARD
// Then discard if there is no edge:
if (dot(edges, float2(1.0, 1.0)) == 0.0) {
discard;
return float2(0.0, 0.0);
}
# endif
# elif defined(GPU_COMPUTE_SHADER)
// Then return early if there is no edge:
if (dot(edges, float2(1.0, 1.0)) == 0.0) {
return float2(0.0);
}
# endif
// Calculate right and bottom deltas:
@ -802,9 +807,7 @@ float2 SMAALumaEdgeDetectionPS(float2 texcoord,
float finalDelta = max(maxDelta.x, maxDelta.y);
// Local contrast adaptation:
# if !defined(SHADER_API_OPENGL)
edges.xy *= step(finalDelta, SMAA_LOCAL_CONTRAST_ADAPTATION_FACTOR * delta.xy);
# endif
return edges;
}
@ -882,9 +885,7 @@ float2 SMAAColorEdgeDetectionPS(float2 texcoord,
float finalDelta = max(maxDelta.x, maxDelta.y);
// Local contrast adaptation:
# if !defined(SHADER_API_OPENGL)
edges.xy *= step(finalDelta, SMAA_LOCAL_CONTRAST_ADAPTATION_FACTOR * delta.xy);
# endif
return edges;
}

View File

@ -17,7 +17,7 @@
#define RUN_UNSUPPORTED false
/* Skip tests that haven't been developed yet due to non standard data types or it needs an
* framebuffer to create the texture. */
* frame-buffer to create the texture. */
#define RUN_SRGB_UNIMPLEMENTED false
#define RUN_NON_STANDARD_UNIMPLEMENTED false
#define RUN_COMPONENT_UNIMPLEMENTED false
@ -168,7 +168,7 @@ static void texture_create_upload_read_pixel()
}
/* -------------------------------------------------------------------- */
/** \name Roundtrip testing GPU_DATA_FLOAT
/** \name Round-trip testing GPU_DATA_FLOAT
* \{ */
static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_RGBA8()
{
@ -422,7 +422,7 @@ GPU_TEST(texture_roundtrip__GPU_DATA_FLOAT__GPU_DEPTH_COMPONENT16);
/* \} */
/* -------------------------------------------------------------------- */
/** \name Roundtrip testing GPU_DATA_HALF_FLOAT
/** \name Round-trip testing GPU_DATA_HALF_FLOAT
* \{ */
static void test_texture_roundtrip__GPU_DATA_HALF_FLOAT__GPU_RGBA16F()
@ -454,7 +454,7 @@ GPU_TEST(texture_roundtrip__GPU_DATA_HALF_FLOAT__GPU_RGB16F);
/* \} */
/* -------------------------------------------------------------------- */
/** \name Roundtrip testing GPU_DATA_INT
/** \name Round-trip testing GPU_DATA_INT
* \{ */
static void test_texture_roundtrip__GPU_DATA_INT__GPU_RGBA8I()
@ -534,7 +534,7 @@ GPU_TEST(texture_roundtrip__GPU_DATA_INT__GPU_RGB32I);
/* \} */
/* -------------------------------------------------------------------- */
/** \name Roundtrip testing GPU_DATA_UINT
/** \name Round-trip testing GPU_DATA_UINT
* \{ */
static void test_texture_roundtrip__GPU_DATA_UINT__GPU_RGBA8UI()
@ -648,7 +648,7 @@ GPU_TEST(texture_roundtrip__GPU_DATA_UINT__GPU_DEPTH_COMPONENT16);
/* \} */
/* -------------------------------------------------------------------- */
/** \name Roundtrip testing GPU_DATA_UBYTE
/** \name Round-trip testing GPU_DATA_UBYTE
* \{ */
static void test_texture_roundtrip__GPU_DATA_UBYTE__GPU_RGBA8UI()
@ -717,7 +717,7 @@ GPU_TEST(texture_roundtrip__GPU_DATA_UBYTE__GPU_SRGB8);
/* \} */
/* -------------------------------------------------------------------- */
/** \name Roundtrip testing GPU_DATA_UINT_24_8
/** \name Round-trip testing GPU_DATA_UINT_24_8
* \{ */
#if RUN_UNSUPPORTED
@ -737,7 +737,7 @@ GPU_TEST(texture_roundtrip__GPU_DATA_UINT_24_8__GPU_DEPTH24_STENCIL8);
/* \} */
/* -------------------------------------------------------------------- */
/** \name Roundtrip testing GPU_DATA_10_11_11_REV
/** \name Round-trip testing GPU_DATA_10_11_11_REV
* \{ */
static void test_texture_roundtrip__GPU_DATA_10_11_11_REV__GPU_R11F_G11F_B10F()
@ -749,7 +749,7 @@ GPU_TEST(texture_roundtrip__GPU_DATA_10_11_11_REV__GPU_R11F_G11F_B10F);
/* \} */
/* -------------------------------------------------------------------- */
/** \name Roundtrip testing GPU_DATA_2_10_10_10_REV
/** \name Round-trip testing GPU_DATA_2_10_10_10_REV
* \{ */
static void test_texture_roundtrip__GPU_DATA_2_10_10_10_REV__GPU_RGB10_A2()

View File

@ -89,7 +89,7 @@ typedef struct NoiseGpencilModifierData {
char layername[64];
/** Material name. */
char materialname[64] DNA_DEPRECATED;
/** Optional vertexgroup name, MAX_VGROUP_NAME. */
/** Optional vertex-group name, #MAX_VGROUP_NAME. */
char vgname[64];
/** Custom index for passes. */
int pass_index;
@ -175,7 +175,7 @@ typedef struct ThickGpencilModifierData {
char layername[64];
/** Material name. */
char materialname[64] DNA_DEPRECATED;
/** Optional vertexgroup name, MAX_VGROUP_NAME. */
/** Optional vertex-group name, #MAX_VGROUP_NAME. */
char vgname[64];
/** Custom index for passes. */
int pass_index;
@ -308,7 +308,7 @@ typedef struct OpacityGpencilModifierData {
char layername[64];
/** Material name. */
char materialname[64] DNA_DEPRECATED;
/** Optional vertexgroup name, MAX_VGROUP_NAME. */
/** Optional vertex-group name, #MAX_VGROUP_NAME. */
char vgname[64];
/** Custom index for passes. */
int pass_index;
@ -457,11 +457,11 @@ typedef struct BuildGpencilModifierData {
*/
short time_alignment;
/* Speed factor for GP_BUILD_TIMEMODE_DRAWSPEED. */
/** Speed factor for #GP_BUILD_TIMEMODE_DRAWSPEED. */
float speed_fac;
/* Maxmium time gap between strokes for GP_BUILD_TIMEMODE_DRAWSPEED. */
/** Maximum time gap between strokes for #GP_BUILD_TIMEMODE_DRAWSPEED. */
float speed_maxgap;
/* Which time mode should be used. */
/** Which time mode should be used. */
short time_mode;
char _pad[6];
@ -473,7 +473,7 @@ typedef struct BuildGpencilModifierData {
/** Weight fading at the end of the stroke. */
float fade_fac;
/** Target vertexgroup name, MAX_VGROUP_NAME. */
/** Target vertex-group name, #MAX_VGROUP_NAME. */
char target_vgname[64];
/** Fading strength of opacity and thickness */
float fade_opacity_strength;
@ -508,11 +508,11 @@ typedef enum eBuildGpencil_TimeAlignment {
} eBuildGpencil_TimeAlignment;
typedef enum eBuildGpencil_TimeMode {
/* Use a number of frames build. */
/** Use a number of frames build. */
GP_BUILD_TIMEMODE_FRAMES = 0,
/* Use manual percentage to build. */
/** Use manual percentage to build. */
GP_BUILD_TIMEMODE_PERCENTAGE = 1,
/* Use factor of recorded speed to build. */
/** Use factor of recorded speed to build. */
GP_BUILD_TIMEMODE_DRAWSPEED = 2,
} eBuildGpencil_TimeMode;
@ -536,7 +536,7 @@ typedef struct LatticeGpencilModifierData {
char layername[64];
/** Material name. */
char materialname[64] DNA_DEPRECATED;
/** Optional vertexgroup name, MAX_VGROUP_NAME. */
/** Optional vertex-group name, #MAX_VGROUP_NAME. */
char vgname[64];
/** Custom index for passes. */
int pass_index;
@ -685,7 +685,7 @@ typedef struct HookGpencilModifierData {
char layername[64];
/** Material name. */
char materialname[64] DNA_DEPRECATED;
/** Optional vertexgroup name, MAX_VGROUP_NAME. */
/** Optional vertex-group name, #MAX_VGROUP_NAME. */
char vgname[64];
/** Custom index for passes. */
int pass_index;
@ -694,7 +694,7 @@ typedef struct HookGpencilModifierData {
char _pad[4];
int flag;
/** Use enums from WarpGpencilModifier (exact same functionality). */
/** #eHookGpencil_Falloff. */
char falloff_type;
char _pad1[3];
/** Matrix making current transform unmodified. */
@ -790,7 +790,7 @@ typedef struct OffsetGpencilModifierData {
char layername[64];
/** Material name. */
char materialname[64] DNA_DEPRECATED;
/** Optional vertexgroup name, MAX_VGROUP_NAME. */
/** Optional vertex-group name, #MAX_VGROUP_NAME. */
char vgname[64];
/** Custom index for passes. */
int pass_index;
@ -832,7 +832,7 @@ typedef struct SmoothGpencilModifierData {
char layername[64];
/** Material name. */
char materialname[64] DNA_DEPRECATED;
/** Optional vertexgroup name, MAX_VGROUP_NAME. */
/** Optional vertex-group name, #MAX_VGROUP_NAME. */
char vgname[64];
/** Custom index for passes. */
int pass_index;
@ -871,7 +871,7 @@ typedef struct ArmatureGpencilModifierData {
struct Object *object;
/** Stored input of previous modifier, for vertex-group blending. */
float (*vert_coords_prev)[3];
/** MAX_VGROUP_NAME. */
/** #MAX_VGROUP_NAME. */
char vgname[64];
} ArmatureGpencilModifierData;
@ -919,7 +919,7 @@ typedef struct TintGpencilModifierData {
char layername[64];
/** Material name. */
char materialname[64] DNA_DEPRECATED;
/** Optional vertexgroup name, MAX_VGROUP_NAME. */
/** Optional vertex-group name, #MAX_VGROUP_NAME. */
char vgname[64];
/** Custom index for passes. */
int pass_index;
@ -965,7 +965,7 @@ typedef struct TextureGpencilModifierData {
char layername[64];
/** Material name. */
char materialname[64] DNA_DEPRECATED;
/** Optional vertexgroup name, MAX_VGROUP_NAME. */
/** Optional vertex-group name, #MAX_VGROUP_NAME. */
char vgname[64];
/** Custom index for passes. */
int pass_index;
@ -1010,13 +1010,13 @@ typedef enum eTextureGpencil_Mode {
typedef struct WeightProxGpencilModifierData {
GpencilModifierData modifier;
/** Target vertexgroup name, MAX_VGROUP_NAME. */
/** Target vertex-group name, #MAX_VGROUP_NAME. */
char target_vgname[64];
/** Material for filtering. */
struct Material *material;
/** Layer name. */
char layername[64];
/** Optional vertexgroup filter name, MAX_VGROUP_NAME. */
/** Optional vertex-group filter name, #MAX_VGROUP_NAME. */
char vgname[64];
/** Custom index for passes. */
int pass_index;
@ -1036,13 +1036,13 @@ typedef struct WeightProxGpencilModifierData {
typedef struct WeightAngleGpencilModifierData {
GpencilModifierData modifier;
/** Target vertexgroup name, MAX_VGROUP_NAME. */
/** Target vertex-group name, #MAX_VGROUP_NAME. */
char target_vgname[64];
/** Material for filtering. */
struct Material *material;
/** Layer name. */
char layername[64];
/** Optional vertexgroup filter name, MAX_VGROUP_NAME. */
/** Optional vertex-group filter name, #MAX_VGROUP_NAME. */
char vgname[64];
/** Custom index for passes. */
int pass_index;
@ -1209,7 +1209,7 @@ typedef struct LineartGpencilModifierData {
char _pad2[6];
struct LineartCache *cache;
/* Keep a pointer to the render buffer so we can call destroy from ModifierData. */
/** Keep a pointer to the render buffer so we can call destroy from #ModifierData. */
struct LineartData *la_data_ptr;
} LineartGpencilModifierData;
@ -1224,7 +1224,7 @@ typedef struct ShrinkwrapGpencilModifierData {
struct Material *material;
/** Layer name. */
char layername[64];
/** Optional vertexgroup filter name, MAX_VGROUP_NAME. */
/** Optional vertex-group filter name, #MAX_VGROUP_NAME. */
char vgname[64];
/** Custom index for passes. */
int pass_index;
@ -1274,7 +1274,7 @@ typedef struct EnvelopeGpencilModifierData {
struct Material *material;
/** Layer name. */
char layername[64];
/** Optional vertexgroup name, MAX_VGROUP_NAME. */
/** Optional vertex-group name, #MAX_VGROUP_NAME. */
char vgname[64];
/** Custom index for passes. */
int pass_index;

View File

@ -10,6 +10,7 @@
#include "UI_interface.h"
#include "UI_resources.h"
#include "COM_algorithm_smaa.hh"
#include "COM_node_operation.hh"
#include "node_composite_util.hh"
@ -18,9 +19,13 @@
namespace blender::nodes::node_composite_antialiasing_cc {
NODE_STORAGE_FUNCS(NodeAntiAliasingData)
static void cmp_node_antialiasing_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Color>(N_("Image")).default_value({1.0f, 1.0f, 1.0f, 1.0f});
b.add_input<decl::Color>(N_("Image"))
.default_value({1.0f, 1.0f, 1.0f, 1.0f})
.compositor_domain_priority(0);
b.add_output<decl::Color>(N_("Image"));
}
@ -54,8 +59,33 @@ class AntiAliasingOperation : public NodeOperation {
void execute() override
{
get_input("Image").pass_through(get_result("Image"));
context().set_info_message("Viewport compositor setup not fully supported");
smaa(context(),
get_input("Image"),
get_result("Image"),
get_threshold(),
get_local_contrast_adaptation_factor(),
get_corner_rounding());
}
/* Blender encodes the threshold in the [0, 1] range, while the SMAA algorithm expects it in
* the [0, 0.5] range. */
float get_threshold()
{
return node_storage(bnode()).threshold / 2.0f;
}
/* Blender encodes the local contrast adaptation factor in the [0, 1] range, while the SMAA
* algorithm expects it in the [0, 10] range. */
float get_local_contrast_adaptation_factor()
{
return node_storage(bnode()).threshold * 10.0f;
}
/* Blender encodes the corner rounding factor in the float [0, 1] range, while the SMAA algorithm
* expects it in the integer [0, 100] range. */
int get_corner_rounding()
{
return int(node_storage(bnode()).corner_rounding * 100.0f);
}
};
@ -81,8 +111,6 @@ void register_node_type_cmp_antialiasing()
node_type_storage(
&ntype, "NodeAntiAliasingData", node_free_standard_storage, node_copy_standard_storage);
ntype.get_compositor_operation = file_ns::get_compositor_operation;
ntype.realtime_compositor_unsupported_message = N_(
"Node not supported in the Viewport compositor");
nodeRegisterType(&ntype);
}

View File

@ -106,7 +106,7 @@ class BlurOperation : public NodeOperation {
return;
}
if (!get_input("Size").is_single_value() && get_variable_size()) {
if (use_variable_size()) {
execute_variable_size();
}
else if (use_separable_filter()) {
@ -261,6 +261,12 @@ class BlurOperation : public NodeOperation {
}
}
bool use_variable_size()
{
return get_variable_size() && !get_input("Size").is_single_value() &&
node_storage(bnode()).filtertype != R_FILTER_FAST_GAUSS;
}
float2 get_size_factor()
{
return float2(node_storage(bnode()).percentx, node_storage(bnode()).percenty) / 100.0f;

View File

@ -179,7 +179,7 @@ struct GrabState {
static bool wm_software_cursor_needed(void)
{
if (UNLIKELY(g_software_cursor.enabled == -1)) {
g_software_cursor.enabled = !GHOST_SupportsCursorWarp();
g_software_cursor.enabled = !(WM_capabilities_flag() & WM_CAPABILITY_CURSOR_WARP);
}
return g_software_cursor.enabled;
}

View File

@ -5165,7 +5165,8 @@ static void attach_ndof_data(wmEvent *event, const GHOST_TEventNDOFMotionData *g
static wmWindow *wm_event_cursor_other_windows(wmWindowManager *wm, wmWindow *win, wmEvent *event)
{
/* If GHOST doesn't support window positioning, don't use this feature at all. */
const static int8_t supports_window_position = GHOST_SupportsWindowPosition();
const static int8_t supports_window_position = (WM_capabilities_flag() &
WM_CAPABILITY_WINDOW_POSITION) != 0;
if (!supports_window_position) {
return nullptr;
}

View File

@ -998,7 +998,11 @@ wmWindow *WM_window_open(bContext *C,
return NULL;
}
/* ****************** Operators ****************** */
/** \} */
/* -------------------------------------------------------------------- */
/** \name Operators
* \{ */
int wm_window_close_exec(bContext *C, wmOperator *UNUSED(op))
{
@ -1063,7 +1067,11 @@ int wm_window_fullscreen_toggle_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_FINISHED;
}
/* ************ events *************** */
/** \} */
/* -------------------------------------------------------------------- */
/** \name Events
* \{ */
void wm_cursor_position_from_ghost_client_coords(wmWindow *win, int *x, int *y)
{
@ -1827,14 +1835,14 @@ eWM_CapabilitiesFlag WM_capabilities_flag(void)
return flag;
}
flag = 0;
if (GHOST_SupportsCursorWarp()) {
const GHOST_TCapabilityFlag ghost_flag = GHOST_GetCapabilities();
if (ghost_flag & GHOST_kCapabilityCursorWarp) {
flag |= WM_CAPABILITY_CURSOR_WARP;
}
if (GHOST_SupportsWindowPosition()) {
if (ghost_flag & GHOST_kCapabilityWindowPosition) {
flag |= WM_CAPABILITY_WINDOW_POSITION;
}
if (GHOST_SupportsPrimaryClipboard()) {
if (ghost_flag & GHOST_kCapabilityPrimaryClipboard) {
flag |= WM_CAPABILITY_PRIMARY_CLIPBOARD;
}

View File

@ -100,6 +100,7 @@ dict_custom = {
"dialogs",
"digitizers",
"dihedral",
"directionality",
"discoverability",
"discretization",
"discretized",
@ -144,6 +145,7 @@ dict_custom = {
"interdependencies",
"interferences",
"interocular",
"interpolator",
"invariant",
"invariants",
"invisibilities",
@ -157,6 +159,8 @@ dict_custom = {
"linearizing",
"linkable",
"lockless",
"looper",
"loopers",
"losslessly",
"luminances",
"mappable",
@ -174,6 +178,8 @@ dict_custom = {
"occludee",
"occluder",
"occluders",
"octant",
"octants",
"optionals",
"orthogonalize",
"orthogonally",
@ -186,6 +192,7 @@ dict_custom = {
"parallelize",
"parallelizing",
"parameterization",
"parameterless",
"parametrization",
"parentless",
"passepartout",
@ -247,6 +254,8 @@ dict_custom = {
"redistributions",
"registerable",
"reimplement",
"reimplemented",
"reimplementing",
"remappable",
"remapper",
"remappings",
@ -258,9 +267,14 @@ dict_custom = {
"reparameterization",
"reparametization",
"representable",
"reprojected",
"reprojecting",
"reprojection",
"reprojections",
"repurpose",
"respecialized",
"resynced",
"resyncing",
"retiming",
"reusability",
"saveable",
@ -325,6 +339,7 @@ dict_custom = {
"undistored",
"undistorted",
"undistorting",
"unduplicated",
"uneditable",
"unflagged",
"unflip",
@ -368,6 +383,7 @@ dict_custom = {
"unpoision",
"unproject",
"unquantifiable",
"unreferenced",
"unregister",
"unregistering",
"unregisters",
@ -429,6 +445,7 @@ dict_custom = {
"addon",
"addons",
"autocomplete",
"codegen",
"colospace",
"datablock",
"datablocks",
@ -451,6 +468,7 @@ dict_custom = {
"config", # configuration.
"coord",
"coords",
"ctrl", # control (modifier key).
"iter", # iteration.
"multi",
"numpad", # numeric-pad.