WIP: eevee-next-world-irradiance #108304

Closed
Jeroen Bakker wants to merge 79 commits from Jeroen-Bakker:eevee-next-world-irradiance into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
98 changed files with 2966 additions and 346 deletions
Showing only changes of commit 6f6c3afe91 - Show all commits

View File

@ -39,7 +39,8 @@ OrientationBounds merge(const OrientationBounds &cone_a, const OrientationBounds
b = &cone_a;
}
float theta_d = safe_acosf(dot(a->axis, b->axis));
float cos_a_b = dot(a->axis, b->axis);
float theta_d = safe_acosf(cos_a_b);
float theta_e = fmaxf(a->theta_e, b->theta_e);
/* Return axis and theta_o of a if it already contains b. */
@ -55,10 +56,18 @@ OrientationBounds merge(const OrientationBounds &cone_a, const OrientationBounds
return OrientationBounds({a->axis, M_PI_F, theta_e});
}
/* Rotate new axis to be between a and b. */
float theta_r = theta_o - a->theta_o;
float3 new_axis = rotate_around_axis(a->axis, safe_normalize(cross(a->axis, b->axis)), theta_r);
new_axis = normalize(new_axis);
/* Slerp between a and b. */
float3 new_axis;
if (cos_a_b < -0.9995f) {
/* Opposite direction, any orthogonal vector is fine. */
float3 unused;
make_orthonormals(a->axis, &new_axis, &unused);
}
else {
float theta_r = theta_o - a->theta_o;
float3 ortho = normalize(b->axis - a->axis * cos_a_b);
new_axis = a->axis * cosf(theta_r) + ortho * sinf(theta_r);
}
return OrientationBounds({new_axis, theta_o, theta_e});
}

View File

@ -933,6 +933,11 @@ extern bool GHOST_SupportsCursorWarp(void);
*/
extern bool GHOST_SupportsWindowPosition(void);
/**
* Support a separate primary clipboard.
*/
extern bool GHOST_SupportsPrimaryClipboard(void);
/**
* Assign the callback which generates a back-trace (may be NULL).
*/

View File

@ -327,6 +327,11 @@ class GHOST_ISystem {
*/
virtual bool supportsWindowPosition() = 0;
/**
* Return true when a separate primary clipboard is supported.
*/
virtual bool supportsPrimaryClipboard() = 0;
/**
* Focus window after opening, or put them in the background.
*/

View File

@ -907,6 +907,12 @@ bool GHOST_SupportsWindowPosition(void)
return system->supportsWindowPosition();
}
bool GHOST_SupportsPrimaryClipboard(void)
{
GHOST_ISystem *system = GHOST_ISystem::getSystem();
return system->supportsPrimaryClipboard();
}
void GHOST_SetBacktraceHandler(GHOST_TBacktraceFn backtrace_fn)
{
GHOST_ISystem::setBacktraceFn(backtrace_fn);

View File

@ -428,6 +428,11 @@ 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

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

View File

@ -1117,7 +1117,7 @@ using GWL_RegistryHandler_UpdateFn = void (*)(GWL_Display *display,
using GWL_RegistryEntry_RemoveFn = void (*)(GWL_Display *display, void *user_data, bool on_exit);
struct GWL_RegistryHandler {
/** Pointer to the name (not the name it's self), needed as the values aren't set on startup. */
/** Pointer to the name (not the name itself), needed as the values aren't set on startup. */
const char *const *interface_p = nullptr;
/** Add the interface. */
@ -2016,7 +2016,13 @@ static char *read_file_as_buffer(const int fd, const bool nil_terminate, size_t
{
struct ByteChunk {
ByteChunk *next;
char data[4096 - sizeof(ByteChunk *)];
/* NOTE(@ideasman42): On GNOME-SHELL-43.3, non powers of two values
* (1023 or 4088 for e.g.) makes `read()` *intermittently* include uninitialized memory
* (failing to read the end of the chunk) as well as truncating the end of the whole buffer.
* The WAYLAND spec doesn't mention buffer-size so this may be a bug in GNOME-SHELL.
* Whatever the case, using a power of two isn't a problem (besides some slop-space waste).
* This workaround isn't necessary for KDE & WLROOTS based compositors, see: #106040. */
char data[4096];
};
ByteChunk *chunk_first = nullptr, **chunk_link_p = &chunk_first;
bool ok = true;
@ -3621,7 +3627,7 @@ static void tablet_seat_handle_tool_added(void *data,
GWL_TabletTool *tablet_tool = new GWL_TabletTool();
tablet_tool->seat = seat;
/* Every tool has it's own cursor wl_surface. */
/* Every tool has its own cursor wl_surface. */
tablet_tool->wl_surface_cursor = wl_compositor_create_surface(seat->system->wl_compositor());
ghost_wl_surface_tag_cursor_tablet(tablet_tool->wl_surface_cursor);
@ -3963,7 +3969,7 @@ static void keyboard_handle_key(void *data,
}
else if (xkb_keymap_key_repeats(xkb_state_get_keymap(seat->xkb_state), key_code)) {
if (etype == GHOST_kEventKeyDown) {
/* Any other key-down always cancels (and may start it's own repeat timer). */
/* Any other key-down always cancels (and may start its own repeat timer). */
timer_action = CANCEL;
}
else {
@ -6682,6 +6688,11 @@ bool GHOST_SystemWayland::supportsWindowPosition()
return false;
}
bool GHOST_SystemWayland::supportsPrimaryClipboard()
{
return true;
}
bool GHOST_SystemWayland::cursor_grab_use_software_display_get(const GHOST_TGrabCursorMode mode)
{
/* Caller must lock `server_mutex`. */

View File

@ -144,6 +144,7 @@ class GHOST_SystemWayland : public GHOST_System {
bool supportsCursorWarp() override;
bool supportsWindowPosition() override;
bool supportsPrimaryClipboard() override;
/* WAYLAND utility functions (share window/system logic). */

View File

@ -1740,6 +1740,11 @@ GHOST_TSuccess GHOST_SystemX11::setCursorPosition(int32_t x, int32_t y)
return GHOST_kSuccess;
}
bool GHOST_SystemX11::supportsPrimaryClipboard()
{
return true;
}
void GHOST_SystemX11::addDirtyWindow(GHOST_WindowX11 *bad_wind)
{
GHOST_ASSERT((bad_wind != nullptr), "addDirtyWindow() nullptr ptr trapped (window)");

View File

@ -168,6 +168,8 @@ class GHOST_SystemX11 : public GHOST_System {
*/
GHOST_TSuccess getButtons(GHOST_Buttons &buttons) const;
bool supportsPrimaryClipboard() override;
/**
* Flag a window as dirty. This will
* generate a GHOST window update event on a call to processEvents()

View File

@ -70,7 +70,7 @@ _script_module_dirs = "startup", "modules"
# Base scripts, this points to the directory containing: "modules" & "startup" (see `_script_module_dirs`).
# In Blender's code-base this is `./scripts`.
#
# NOTE: in virtually all cases this should match `BLENDER_SYSTEM_SCRIPTS` as this script is it's self a system script,
# NOTE: in virtually all cases this should match `BLENDER_SYSTEM_SCRIPTS` as this script is itself a system script,
# it must be in the `BLENDER_SYSTEM_SCRIPTS` by definition and there is no need for a look-up from `_bpy_script_paths`.
_script_base_dir = _os.path.dirname(_os.path.dirname(_os.path.dirname(_os.path.dirname(__file__))))

View File

@ -208,6 +208,7 @@ url_manual_mapping = (
("bpy.types.brushgpencilsettings.use_jitter_pressure*", "grease_pencil/modes/draw/tools/draw.html#bpy-types-brushgpencilsettings-use-jitter-pressure"),
("bpy.types.brushgpencilsettings.use_random_press_uv*", "grease_pencil/modes/draw/tools/draw.html#bpy-types-brushgpencilsettings-use-random-press-uv"),
("bpy.types.brushgpencilsettings.use_settings_random*", "grease_pencil/modes/draw/tools/draw.html#bpy-types-brushgpencilsettings-use-settings-random"),
("bpy.types.brushgpencilsettings.vertex_color_factor*", "grease_pencil/modes/draw/tool_settings/color.html#bpy-types-brushgpencilsettings-vertex-color-factor"),
("bpy.types.clothcollisionsettings.collision_quality*", "physics/cloth/settings/collisions.html#bpy-types-clothcollisionsettings-collision-quality"),
("bpy.types.clothcollisionsettings.self_distance_min*", "physics/cloth/settings/collisions.html#bpy-types-clothcollisionsettings-self-distance-min"),
("bpy.types.clothsettings.internal_spring_max_length*", "physics/cloth/settings/physical_properties.html#bpy-types-clothsettings-internal-spring-max-length"),
@ -239,6 +240,7 @@ url_manual_mapping = (
("bpy.types.sequencertimelineoverlay.show_thumbnails*", "editors/video_sequencer/sequencer/display.html#bpy-types-sequencertimelineoverlay-show-thumbnails"),
("bpy.types.spacespreadsheet.geometry_component_type*", "editors/spreadsheet.html#bpy-types-spacespreadsheet-geometry-component-type"),
("bpy.types.toolsettings.use_gpencil_weight_data_add*", "grease_pencil/modes/draw/introduction.html#bpy-types-toolsettings-use-gpencil-weight-data-add"),
("bpy.types.view3doverlay.sculpt_curves_cage_opacity*", "sculpt_paint/curves_sculpting/introduction.html#bpy-types-view3doverlay-sculpt-curves-cage-opacity"),
("bpy.types.view3doverlay.texture_paint_mode_opacity*", "editors/3dview/display/overlays.html#bpy-types-view3doverlay-texture-paint-mode-opacity"),
("bpy.ops.mesh.customdata_bevel_weight_vertex_clear*", "modeling/meshes/properties/custom_data.html#bpy-ops-mesh-customdata-bevel-weight-vertex-clear"),
("bpy.ops.mesh.customdata_custom_splitnormals_clear*", "modeling/meshes/properties/custom_data.html#bpy-ops-mesh-customdata-custom-splitnormals-clear"),
@ -382,7 +384,6 @@ url_manual_mapping = (
("bpy.types.freestylelineset.select_by_edge_types*", "render/freestyle/view_layer/line_set.html#bpy-types-freestylelineset-select-by-edge-types"),
("bpy.types.freestylelineset.select_by_face_marks*", "render/freestyle/view_layer/line_set.html#bpy-types-freestylelineset-select-by-face-marks"),
("bpy.types.geometrynodeinputcurvehandlepositions*", "modeling/geometry_nodes/curve/read/curve_handle_position.html#bpy-types-geometrynodeinputcurvehandlepositions"),
("bpy.types.geometrynodeinputedgepathstoselection*", "modeling/geometry_nodes/mesh/operations/edge_paths_to_selection.html#bpy-types-geometrynodeinputedgepathstoselection"),
("bpy.types.linestyle*modifier_distancefromcamera*", "render/freestyle/view_layer/line_style/modifiers/color/distance_from_camera.html#bpy-types-linestyle-modifier-distancefromcamera"),
("bpy.types.linestyle*modifier_distancefromobject*", "render/freestyle/view_layer/line_style/modifiers/color/distance_from_object.html#bpy-types-linestyle-modifier-distancefromobject"),
("bpy.types.linestylegeometrymodifier_2dtransform*", "render/freestyle/view_layer/line_style/modifiers/geometry/2d_transform.html#bpy-types-linestylegeometrymodifier-2dtransform"),
@ -406,9 +407,11 @@ url_manual_mapping = (
("bpy.types.toolsettings.gpencil_stroke_placement*", "grease_pencil/modes/draw/stroke_placement.html#bpy-types-toolsettings-gpencil-stroke-placement"),
("bpy.types.toolsettings.use_keyframe_cycle_aware*", "editors/timeline.html#bpy-types-toolsettings-use-keyframe-cycle-aware"),
("bpy.types.toolsettings.use_keyframe_insert_auto*", "editors/timeline.html#bpy-types-toolsettings-use-keyframe-insert-auto"),
("bpy.types.view3doverlay.show_sculpt_curves_cage*", "sculpt_paint/curves_sculpting/introduction.html#bpy-types-view3doverlay-show-sculpt-curves-cage"),
("bpy.types.viewlayer.use_pass_cryptomatte_object*", "render/layers/passes.html#bpy-types-viewlayer-use-pass-cryptomatte-object"),
("bpy.ops.armature.rigify_apply_selection_colors*", "addons/rigging/rigify/metarigs.html#bpy-ops-armature-rigify-apply-selection-colors"),
("bpy.ops.ed.lib_id_generate_preview_from_object*", "editors/asset_browser.html#bpy-ops-ed-lib-id-generate-preview-from-object"),
("bpy.ops.paint.vertex_color_brightness_contrast*", "sculpt_paint/vertex_paint/editing.html#bpy-ops-paint-vertex-color-brightness-contrast"),
("bpy.types.brushcurvessculptsettings.add_amount*", "sculpt_paint/curves_sculpting/tools/add_curves.html#bpy-types-brushcurvessculptsettings-add-amount"),
("bpy.types.brushgpencilsettings.fill_layer_mode*", "grease_pencil/modes/draw/tools/fill.html#bpy-types-brushgpencilsettings-fill-layer-mode"),
("bpy.types.brushgpencilsettings.random_strength*", "grease_pencil/modes/draw/tools/draw.html#bpy-types-brushgpencilsettings-random-strength"),
@ -449,6 +452,7 @@ url_manual_mapping = (
("bpy.types.movietrackingcamera.distortion_model*", "movie_clip/tracking/clip/sidebar/track/camera.html#bpy-types-movietrackingcamera-distortion-model"),
("bpy.types.movietrackingtrack.use_alpha_preview*", "movie_clip/tracking/clip/sidebar/track/track.html#bpy-types-movietrackingtrack-use-alpha-preview"),
("bpy.types.movietrackingtrack.use_green_channel*", "movie_clip/tracking/clip/sidebar/track/track.html#bpy-types-movietrackingtrack-use-green-channel"),
("bpy.types.nodesocketinterface.hide_in_modifier*", "interface/controls/nodes/groups.html#bpy-types-nodesocketinterface-hide-in-modifier"),
("bpy.types.rendersettings.resolution_percentage*", "render/output/properties/format.html#bpy-types-rendersettings-resolution-percentage"),
("bpy.types.rendersettings_simplify_gpencil_tint*", "render/cycles/render_settings/simplify.html#bpy-types-rendersettings-simplify-gpencil-tint"),
("bpy.types.softbodysettings.use_estimate_matrix*", "physics/soft_body/settings/solver.html#bpy-types-softbodysettings-use-estimate-matrix"),
@ -524,6 +528,7 @@ url_manual_mapping = (
("bpy.types.softbodysettings.use_edge_collision*", "physics/soft_body/settings/edges.html#bpy-types-softbodysettings-use-edge-collision"),
("bpy.types.softbodysettings.use_face_collision*", "physics/soft_body/settings/edges.html#bpy-types-softbodysettings-use-face-collision"),
("bpy.types.softbodysettings.use_self_collision*", "physics/soft_body/settings/self_collision.html#bpy-types-softbodysettings-use-self-collision"),
("bpy.types.spaceclipeditor.show_gizmo_navigate*", "editors/clip/display/gizmo.html#bpy-types-spaceclipeditor-show-gizmo-navigate"),
("bpy.types.spacegrapheditor.show_extrapolation*", "editors/graph_editor/introduction.html#bpy-types-spacegrapheditor-show-extrapolation"),
("bpy.types.spaceoutliner.use_filter_collection*", "editors/outliner/interface.html#bpy-types-spaceoutliner-use-filter-collection"),
("bpy.types.spacesequenceeditor.cursor_location*", "editors/video_sequencer/preview/sidebar.html#bpy-types-spacesequenceeditor-cursor-location"),
@ -534,6 +539,7 @@ url_manual_mapping = (
("bpy.types.spacespreadsheetrowfilter.operation*", "editors/spreadsheet.html#bpy-types-spacespreadsheetrowfilter-operation"),
("bpy.types.spacespreadsheetrowfilter.threshold*", "editors/spreadsheet.html#bpy-types-spacespreadsheetrowfilter-threshold"),
("bpy.types.toolsettings.use_snap_grid_absolute*", "editors/3dview/controls/snapping.html#bpy-types-toolsettings-use-snap-grid-absolute"),
("bpy.types.transformsequence.use_uniform_scale*", "video_editing/edit/montage/strips/effects/transform.html#bpy-types-transformsequence-use-uniform-scale"),
("bpy.types.view3doverlay.show_face_orientation*", "editors/3dview/display/overlays.html#bpy-types-view3doverlay-show-face-orientation"),
("bpy.types.view3doverlay.show_viewer_attribute*", "modeling/geometry_nodes/output/viewer.html#bpy-types-view3doverlay-show-viewer-attribute"),
("bpy.ops.gpencil.bake_grease_pencil_animation*", "grease_pencil/animation/tools.html#bpy-ops-gpencil-bake-grease-pencil-animation"),
@ -577,7 +583,6 @@ url_manual_mapping = (
("bpy.types.freestylelinestyle.use_same_object*", "render/freestyle/view_layer/line_style/strokes.html#bpy-types-freestylelinestyle-use-same-object"),
("bpy.types.functionnodeinputspecialcharacters*", "modeling/geometry_nodes/utilities/text/special_characters.html#bpy-types-functionnodeinputspecialcharacters"),
("bpy.types.geometrynodecurveendpointselection*", "modeling/geometry_nodes/curve/read/endpoint_selection.html#bpy-types-geometrynodecurveendpointselection"),
("bpy.types.geometrynodeinputedgepathstocurves*", "modeling/geometry_nodes/mesh/operations/edge_paths_to_curves.html#bpy-types-geometrynodeinputedgepathstocurves"),
("bpy.types.geometrynodeinputmeshedgeneighbors*", "modeling/geometry_nodes/mesh/read/edge_neighbors.html#bpy-types-geometrynodeinputmeshedgeneighbors"),
("bpy.types.geometrynodeinputmeshfaceneighbors*", "modeling/geometry_nodes/mesh/read/face_neighbors.html#bpy-types-geometrynodeinputmeshfaceneighbors"),
("bpy.types.geometrynodeinputshortestedgepaths*", "modeling/geometry_nodes/mesh/read/shortest_edge_paths.html#bpy-types-geometrynodeinputshortestedgepaths"),
@ -610,9 +615,11 @@ url_manual_mapping = (
("bpy.types.toolsettings.transform_pivot_point*", "editors/3dview/controls/pivot_point/index.html#bpy-types-toolsettings-transform-pivot-point"),
("bpy.types.toolsettings.use_proportional_edit*", "editors/3dview/controls/proportional_editing.html#bpy-types-toolsettings-use-proportional-edit"),
("bpy.types.toolsettings.uv_sticky_select_mode*", "editors/uv/selecting.html#bpy-types-toolsettings-uv-sticky-select-mode"),
("bpy.types.transformsequence.translation_unit*", "video_editing/edit/montage/strips/effects/transform.html#bpy-types-transformsequence-translation-unit"),
("bpy.types.volumedisplay.interpolation_method*", "modeling/volumes/properties.html#bpy-types-volumedisplay-interpolation-method"),
("bpy.ops.geometry.color_attribute_render_set*", "modeling/meshes/properties/object_data.html#bpy-ops-geometry-color-attribute-render-set"),
("bpy.ops.mesh.customdata_crease_vertex_clear*", "modeling/meshes/properties/custom_data.html#bpy-ops-mesh-customdata-crease-vertex-clear"),
("bpy.ops.object.geometry_nodes_move_to_nodes*", "modeling/modifiers/generate/geometry_nodes.html#bpy-ops-object-geometry-nodes-move-to-nodes"),
("bpy.types.brushgpencilsettings.angle_factor*", "grease_pencil/modes/draw/tools/draw.html#bpy-types-brushgpencilsettings-angle-factor"),
("bpy.types.brushgpencilsettings.pen_strength*", "grease_pencil/modes/draw/tools/erase.html#bpy-types-brushgpencilsettings-pen-strength"),
("bpy.types.clothcollisionsettings.collection*", "physics/cloth/settings/collisions.html#bpy-types-clothcollisionsettings-collection"),
@ -625,6 +632,7 @@ url_manual_mapping = (
("bpy.types.cyclescamerasettings.fisheye_lens*", "render/cycles/object_settings/cameras.html#bpy-types-cyclescamerasettings-fisheye-lens"),
("bpy.types.cyclesobjectsettings.motion_steps*", "render/cycles/object_settings/object_data.html#bpy-types-cyclesobjectsettings-motion-steps"),
("bpy.types.cyclesrendersettings.filter_width*", "render/cycles/render_settings/film.html#bpy-types-cyclesrendersettings-filter-width"),
("bpy.types.fileassetselectparams.import_type*", "editors/asset_browser.html#bpy-types-fileassetselectparams-import-type"),
("bpy.types.fluiddomainsettings.cfl_condition*", "physics/fluid/type/domain/settings.html#bpy-types-fluiddomainsettings-cfl-condition"),
("bpy.types.fluiddomainsettings.show_velocity*", "physics/fluid/type/domain/gas/viewport_display.html#bpy-types-fluiddomainsettings-show-velocity"),
("bpy.types.fluiddomainsettings.timesteps_max*", "physics/fluid/type/domain/settings.html#bpy-types-fluiddomainsettings-timesteps-max"),
@ -672,9 +680,11 @@ url_manual_mapping = (
("bpy.types.spaceview3d.transform_orientation*", "editors/3dview/controls/orientation.html#bpy-types-spaceview3d-transform-orientation"),
("bpy.types.spaceview3d.use_local_collections*", "editors/3dview/sidebar.html#bpy-types-spaceview3d-use-local-collections"),
("bpy.types.toolsettings.use_snap_peel_object*", "editors/3dview/controls/snapping.html#bpy-types-toolsettings-use-snap-peel-object"),
("bpy.types.transformsequence.translate_start*", "video_editing/edit/montage/strips/effects/transform.html#bpy-types-transformsequence-translate-start"),
("bpy.types.view3doverlay.fade_inactive_alpha*", "editors/3dview/display/overlays.html#bpy-types-view3doverlay-fade-inactive-alpha"),
("bpy.types.view3doverlay.wireframe_threshold*", "editors/3dview/display/overlays.html#bpy-types-view3doverlay-wireframe-threshold"),
("bpy.types.viewlayer.active_lightgroup_index*", "render/layers/passes.html#bpy-types-viewlayer-active-lightgroup-index"),
("bpy.ops.brush.sculpt_curves_falloff_preset*", "sculpt_paint/curves_sculpting/tools/comb_curves.html#bpy-ops-brush-sculpt-curves-falloff-preset"),
("bpy.ops.ed.lib_id_override_editable_toggle*", "editors/outliner/interface.html#bpy-ops-ed-lib-id-override-editable-toggle"),
("bpy.ops.geometry.color_attribute_duplicate*", "modeling/meshes/properties/object_data.html#bpy-ops-geometry-color-attribute-duplicate"),
("bpy.ops.object.constraint_add_with_targets*", "animation/constraints/interface/adding_removing.html#bpy-ops-object-constraint-add-with-targets"),
@ -683,9 +693,11 @@ url_manual_mapping = (
("bpy.ops.scene.freestyle_alpha_modifier_add*", "render/freestyle/view_layer/line_style/alpha.html#bpy-ops-scene-freestyle-alpha-modifier-add"),
("bpy.ops.scene.freestyle_color_modifier_add*", "render/freestyle/view_layer/line_style/color.html#bpy-ops-scene-freestyle-color-modifier-add"),
("bpy.ops.scene.view_layer_remove_lightgroup*", "render/layers/passes.html#bpy-ops-scene-view-layer-remove-lightgroup"),
("bpy.ops.sequencer.scene_frame_range_update*", "video_editing/edit/montage/editing.html#bpy-ops-sequencer-scene-frame-range-update"),
("bpy.types.brush.cloth_simulation_area_type*", "sculpt_paint/sculpting/tools/cloth.html#bpy-types-brush-cloth-simulation-area-type"),
("bpy.types.brushgpencilsettings.eraser_mode*", "grease_pencil/modes/draw/tools/erase.html#bpy-types-brushgpencilsettings-eraser-mode"),
("bpy.types.brushgpencilsettings.fill_factor*", "grease_pencil/modes/draw/tools/fill.html#bpy-types-brushgpencilsettings-fill-factor"),
("bpy.types.brushgpencilsettings.vertex_mode*", "grease_pencil/modes/draw/tool_settings/color.html#bpy-types-brushgpencilsettings-vertex-mode"),
("bpy.types.clothsettings.use_sewing_springs*", "physics/cloth/settings/shape.html#bpy-types-clothsettings-use-sewing-springs"),
("bpy.types.curve.bevel_factor_mapping_start*", "modeling/curves/properties/geometry.html#bpy-types-curve-bevel-factor-mapping-start"),
("bpy.types.cyclescamerasettings.fisheye_fov*", "render/cycles/object_settings/cameras.html#bpy-types-cyclescamerasettings-fisheye-fov"),
@ -720,8 +732,8 @@ url_manual_mapping = (
("bpy.types.freestylesettings.use_smoothness*", "render/freestyle/view_layer/freestyle.html#bpy-types-freestylesettings-use-smoothness"),
("bpy.types.geometrynodecurveprimitivecircle*", "modeling/geometry_nodes/curve/primitives/curve_circle.html#bpy-types-geometrynodecurveprimitivecircle"),
("bpy.types.geometrynodecurvequadraticbezier*", "modeling/geometry_nodes/curve/primitives/quadratic_bezier.html#bpy-types-geometrynodecurvequadraticbezier"),
("bpy.types.geometrynoderemovenamedattribute*", "modeling/geometry_nodes/attribute/remove_named_attribute.html#bpy-types-geometrynoderemovenamedattribute"),
("bpy.types.geometrynodesamplenearestsurface*", "modeling/geometry_nodes/mesh/operations/sample_nearest_surface.html#bpy-types-geometrynodesamplenearestsurface"),
("bpy.types.geometrynodeedgepathstoselection*", "modeling/geometry_nodes/mesh/operations/edge_paths_to_selection.html#bpy-types-geometrynodeedgepathstoselection"),
("bpy.types.geometrynodesamplenearestsurface*", "modeling/geometry_nodes/mesh/sample/sample_nearest_surface.html#bpy-types-geometrynodesamplenearestsurface"),
("bpy.types.gpencillayer.use_viewlayer_masks*", "grease_pencil/properties/layers.html#bpy-types-gpencillayer-use-viewlayer-masks"),
("bpy.types.greasepencil.onion_keyframe_type*", "grease_pencil/properties/onion_skinning.html#bpy-types-greasepencil-onion-keyframe-type"),
("bpy.types.lineartgpencilmodifier.use_cache*", "grease_pencil/modifiers/generate/line_art.html#bpy-types-lineartgpencilmodifier-use-cache"),
@ -745,6 +757,7 @@ url_manual_mapping = (
("bpy.types.spacesequenceeditor.display_mode*", "editors/video_sequencer/preview/display/display_mode.html#bpy-types-spacesequenceeditor-display-mode"),
("bpy.types.spaceview3d.show_object_viewport*", "editors/3dview/display/visibility.html#bpy-types-spaceview3d-show-object-viewport"),
("bpy.types.toolsettings.use_snap_selectable*", "editors/3dview/controls/snapping.html#bpy-types-toolsettings-use-snap-selectable"),
("bpy.types.transformsequence.rotation_start*", "video_editing/edit/montage/strips/effects/transform.html#bpy-types-transformsequence-rotation-start"),
("bpy.types.view3doverlay.show_fade_inactive*", "editors/3dview/display/overlays.html#bpy-types-view3doverlay-show-fade-inactive"),
("bpy.types.viewlayer.pass_cryptomatte_depth*", "render/layers/passes.html#bpy-types-viewlayer-pass-cryptomatte-depth"),
("bpy.ops.clip.stabilize_2d_rotation_select*", "movie_clip/tracking/clip/selecting.html#bpy-ops-clip-stabilize-2d-rotation-select"),
@ -764,6 +777,7 @@ url_manual_mapping = (
("bpy.types.animvizmotionpaths.frame_before*", "animation/motion_paths.html#bpy-types-animvizmotionpaths-frame-before"),
("bpy.types.brush.disconnected_distance_max*", "sculpt_paint/sculpting/tools/pose.html#bpy-types-brush-disconnected-distance-max"),
("bpy.types.brush.surface_smooth_iterations*", "sculpt_paint/sculpting/tools/smooth.html#bpy-types-brush-surface-smooth-iterations"),
("bpy.types.brush.use_color_as_displacement*", "sculpt_paint/brush/texture.html#bpy-types-brush-use-color-as-displacement"),
("bpy.types.brushgpencilsettings.pen_jitter*", "grease_pencil/modes/draw/tools/draw.html#bpy-types-brushgpencilsettings-pen-jitter"),
("bpy.types.brushgpencilsettings.show_lasso*", "grease_pencil/modes/draw/tools/draw.html#bpy-types-brushgpencilsettings-show-lasso"),
("bpy.types.clothsettings.bending_stiffness*", "physics/cloth/settings/physical_properties.html#bpy-types-clothsettings-bending-stiffness"),
@ -795,6 +809,7 @@ url_manual_mapping = (
("bpy.types.freestylelinestyle.use_chaining*", "render/freestyle/view_layer/line_style/strokes.html#bpy-types-freestylelinestyle-use-chaining"),
("bpy.types.freestylesettings.sphere_radius*", "render/freestyle/view_layer/freestyle.html#bpy-types-freestylesettings-sphere-radius"),
("bpy.types.geometrynodeattributedomainsize*", "modeling/geometry_nodes/attribute/domain_size.html#bpy-types-geometrynodeattributedomainsize"),
("bpy.types.geometrynodeinputnamedattribute*", "modeling/geometry_nodes/geometry/read/named_attribute.html#bpy-types-geometrynodeinputnamedattribute"),
("bpy.types.geometrynodesetsplineresolution*", "modeling/geometry_nodes/curve/write/set_spline_resolution.html#bpy-types-geometrynodesetsplineresolution"),
("bpy.types.geometrynodestorenamedattribute*", "modeling/geometry_nodes/attribute/store_named_attribute.html#bpy-types-geometrynodestorenamedattribute"),
("bpy.types.gpencillayer.annotation_opacity*", "interface/annotate_tool.html#bpy-types-gpencillayer-annotation-opacity"),
@ -837,8 +852,10 @@ url_manual_mapping = (
("bpy.types.toolsettings.use_snap_sequencer*", "video_editing/edit/montage/editing.html#bpy-types-toolsettings-use-snap-sequencer"),
("bpy.types.toolsettings.use_snap_translate*", "editors/3dview/controls/snapping.html#bpy-types-toolsettings-use-snap-translate"),
("bpy.types.toolsettings.use_uv_select_sync*", "editors/uv/selecting.html#bpy-types-toolsettings-use-uv-select-sync"),
("bpy.types.transformsequence.interpolation*", "video_editing/edit/montage/strips/effects/transform.html#bpy-types-transformsequence-interpolation"),
("bpy.types.view3doverlay.wireframe_opacity*", "editors/3dview/display/overlays.html#bpy-types-view3doverlay-wireframe-opacity"),
("bpy.ops.asset.open_containing_blend_file*", "editors/asset_browser.html#bpy-ops-asset-open-containing-blend-file"),
("bpy.ops.geometry.color_attribute_convert*", "modeling/meshes/properties/object_data.html#bpy-ops-geometry-color-attribute-convert"),
("bpy.ops.gpencil.active_frames_delete_all*", "grease_pencil/animation/tools.html#bpy-ops-gpencil-active-frames-delete-all"),
("bpy.ops.gpencil.stroke_merge_by_distance*", "grease_pencil/modes/edit/grease_pencil_menu.html#bpy-ops-gpencil-stroke-merge-by-distance"),
("bpy.ops.node.collapse_hide_unused_toggle*", "interface/controls/nodes/editing.html#bpy-ops-node-collapse-hide-unused-toggle"),
@ -988,9 +1005,12 @@ url_manual_mapping = (
("bpy.types.freestylelinestyle.split_dash*", "render/freestyle/view_layer/line_style/strokes.html#bpy-types-freestylelinestyle-split-dash"),
("bpy.types.freestylesettings.use_culling*", "render/freestyle/view_layer/freestyle.html#bpy-types-freestylesettings-use-culling"),
("bpy.types.geometrynodeduplicateelements*", "modeling/geometry_nodes/geometry/operations/duplicate_elements.html#bpy-types-geometrynodeduplicateelements"),
("bpy.types.geometrynodeedgepathstocurves*", "modeling/geometry_nodes/mesh/operations/edge_paths_to_curves.html#bpy-types-geometrynodeedgepathstocurves"),
("bpy.types.geometrynodeedgestofacegroups*", "modeling/geometry_nodes/mesh/read/edges_to_face_groups.html#bpy-types-geometrynodeedgestofacegroups"),
("bpy.types.geometrynodeinputmeshfacearea*", "modeling/geometry_nodes/mesh/read/face_area.html#bpy-types-geometrynodeinputmeshfacearea"),
("bpy.types.geometrynodeinputsplinecyclic*", "modeling/geometry_nodes/curve/read/is_spline_cyclic.html#bpy-types-geometrynodeinputsplinecyclic"),
("bpy.types.geometrynodeinstancestopoints*", "modeling/geometry_nodes/instances/instances_to_points.html#bpy-types-geometrynodeinstancestopoints"),
("bpy.types.geometrynodeinterpolatecurves*", "modeling/geometry_nodes/curve/operations/interpolate_curves.html#bpy-types-geometrynodeinterpolatecurves"),
("bpy.types.geometrynodematerialselection*", "modeling/geometry_nodes/material/material_selection.html#bpy-types-geometrynodematerialselection"),
("bpy.types.gpencillayer.viewlayer_render*", "grease_pencil/properties/layers.html#bpy-types-gpencillayer-viewlayer-render"),
("bpy.types.imagepaint.use_normal_falloff*", "sculpt_paint/brush/falloff.html#bpy-types-imagepaint-use-normal-falloff"),
@ -1027,6 +1047,7 @@ url_manual_mapping = (
("bpy.types.toolsettings.use_snap_nonedit*", "editors/3dview/controls/snapping.html#bpy-types-toolsettings-use-snap-nonedit"),
("bpy.types.toolsettings.use_snap_project*", "editors/3dview/controls/snapping.html#bpy-types-toolsettings-use-snap-project"),
("bpy.types.transformorientationslot.type*", "editors/3dview/controls/orientation.html#bpy-types-transformorientationslot-type"),
("bpy.types.transformsequence.scale_start*", "video_editing/edit/montage/strips/effects/transform.html#bpy-types-transformsequence-scale-start"),
("bpy.types.unitsettings.temperature_unit*", "scene_layout/scene/properties.html#bpy-types-unitsettings-temperature-unit"),
("bpy.types.vertexweightproximitymodifier*", "modeling/modifiers/modify/weight_proximity.html#bpy-types-vertexweightproximitymodifier"),
("bpy.types.view3doverlay.show_wireframes*", "editors/3dview/display/overlays.html#bpy-types-view3doverlay-show-wireframes"),
@ -1038,6 +1059,7 @@ url_manual_mapping = (
("bpy.ops.mesh.vertices_smooth_laplacian*", "modeling/meshes/editing/vertex/laplacian_smooth.html#bpy-ops-mesh-vertices-smooth-laplacian"),
("bpy.ops.object.multires_rebuild_subdiv*", "modeling/modifiers/generate/multiresolution.html#bpy-ops-object-multires-rebuild-subdiv"),
("bpy.ops.outliner.liboverride_operation*", "files/linked_libraries/library_overrides.html#bpy-ops-outliner-liboverride-operation"),
("bpy.ops.paint.vertex_color_from_weight*", "sculpt_paint/vertex_paint/editing.html#bpy-ops-paint-vertex-color-from-weight"),
("bpy.ops.screen.space_type_set_or_cycle*", "editors/index.html#bpy-ops-screen-space-type-set-or-cycle"),
("bpy.ops.sculpt.dynamic_topology_toggle*", "sculpt_paint/sculpting/tool_settings/dyntopo.html#bpy-ops-sculpt-dynamic-topology-toggle"),
("bpy.ops.sequencer.select_side_of_frame*", "video_editing/edit/montage/selecting.html#bpy-ops-sequencer-select-side-of-frame"),
@ -1161,6 +1183,7 @@ url_manual_mapping = (
("bpy.types.compositornodedistancematte*", "compositing/types/matte/distance_key.html#bpy-types-compositornodedistancematte"),
("bpy.types.compositornodeseparatecolor*", "compositing/types/converter/separate_color.html#bpy-types-compositornodeseparatecolor"),
("bpy.types.compositornodesetalpha.mode*", "compositing/types/converter/set_alpha.html#bpy-types-compositornodesetalpha-mode"),
("bpy.types.curves.use_sculpt_collision*", "sculpt_paint/curves_sculpting/introduction.html#bpy-types-curves-use-sculpt-collision"),
("bpy.types.dopesheet.use_filter_invert*", "editors/graph_editor/channels.html#bpy-types-dopesheet-use-filter-invert"),
("bpy.types.editbone.use_local_location*", "animation/armatures/bones/properties/relations.html#bpy-types-editbone-use-local-location"),
("bpy.types.ffmpegsettings.audio_volume*", "render/output/properties/output.html#bpy-types-ffmpegsettings-audio-volume"),
@ -1181,9 +1204,10 @@ url_manual_mapping = (
("bpy.types.geometrynodecurvesplinetype*", "modeling/geometry_nodes/curve/write/set_spline_type.html#bpy-types-geometrynodecurvesplinetype"),
("bpy.types.geometrynodeinputmeshisland*", "modeling/geometry_nodes/mesh/read/mesh_island.html#bpy-types-geometrynodeinputmeshisland"),
("bpy.types.geometrynodemergebydistance*", "modeling/geometry_nodes/geometry/operations/merge_by_distance.html#bpy-types-geometrynodemergebydistance"),
("bpy.types.geometrynoderemoveattribute*", "modeling/geometry_nodes/attribute/remove_named_attribute.html#bpy-types-geometrynoderemoveattribute"),
("bpy.types.geometrynodereplacematerial*", "modeling/geometry_nodes/material/replace_material.html#bpy-types-geometrynodereplacematerial"),
("bpy.types.geometrynoderotateinstances*", "modeling/geometry_nodes/instances/rotate_instances.html#bpy-types-geometrynoderotateinstances"),
("bpy.types.geometrynodesampleuvsurface*", "modeling/geometry_nodes/mesh/operations/sample_uv_surface.html#bpy-types-geometrynodesampleuvsurface"),
("bpy.types.geometrynodesampleuvsurface*", "modeling/geometry_nodes/mesh/sample/sample_uv_surface.html#bpy-types-geometrynodesampleuvsurface"),
("bpy.types.geometrynodesetsplinecyclic*", "modeling/geometry_nodes/curve/write/set_spline_cyclic.html#bpy-types-geometrynodesetsplinecyclic"),
("bpy.types.geometrynodesplineparameter*", "modeling/geometry_nodes/curve/read/spline_parameter.html#bpy-types-geometrynodesplineparameter"),
("bpy.types.gpencillayer.use_mask_layer*", "grease_pencil/properties/layers.html#bpy-types-gpencillayer-use-mask-layer"),
@ -1197,6 +1221,7 @@ url_manual_mapping = (
("bpy.types.movietrackingcamera.brown_p*", "movie_clip/tracking/clip/sidebar/track/camera.html#bpy-types-movietrackingcamera-brown-p"),
("bpy.types.object.visible_transmission*", "render/cycles/object_settings/object_data.html#bpy-types-object-visible-transmission"),
("bpy.types.particlesettingstextureslot*", "physics/particles/texture_influence.html#bpy-types-particlesettingstextureslot"),
("bpy.types.pointlight.shadow_soft_size*", "render/lights/light_object.html#bpy-types-pointlight-shadow-soft-size"),
("bpy.types.posebone.ik_rotation_weight*", "animation/armatures/posing/bone_constraints/inverse_kinematics/introduction.html#bpy-types-posebone-ik-rotation-weight"),
("bpy.types.regionview3d.show_sync_view*", "editors/3dview/navigate/views.html#bpy-types-regionview3d-show-sync-view"),
("bpy.types.rendersettings.resolution_x*", "render/output/properties/format.html#bpy-types-rendersettings-resolution-x"),
@ -1277,7 +1302,6 @@ url_manual_mapping = (
("bpy.types.geometrynodedeletegeometry*", "modeling/geometry_nodes/geometry/operations/delete_geometry.html#bpy-types-geometrynodedeletegeometry"),
("bpy.types.geometrynodeinputcurvetilt*", "modeling/geometry_nodes/curve/read/curve_tilt.html#bpy-types-geometrynodeinputcurvetilt"),
("bpy.types.geometrynodeinputscenetime*", "modeling/geometry_nodes/input/scene/scene_time.html#bpy-types-geometrynodeinputscenetime"),
("bpy.types.geometrynodenamedattribute*", "modeling/geometry_nodes/geometry/read/named_attribute.html#bpy-types-geometrynodenamedattribute"),
("bpy.types.geometrynodepointstovolume*", "modeling/geometry_nodes/point/points_to_volume.html#bpy-types-geometrynodepointstovolume"),
("bpy.types.geometrynodescaleinstances*", "modeling/geometry_nodes/instances/scale_instances.html#bpy-types-geometrynodescaleinstances"),
("bpy.types.geometrynodesetcurvenormal*", "modeling/geometry_nodes/curve/write/set_curve_normal.html#bpy-types-geometrynodesetcurvenormal"),
@ -1309,10 +1333,12 @@ url_manual_mapping = (
("bpy.types.softbodysettings.ball_damp*", "physics/soft_body/settings/self_collision.html#bpy-types-softbodysettings-ball-damp"),
("bpy.types.softbodysettings.ball_size*", "physics/soft_body/settings/self_collision.html#bpy-types-softbodysettings-ball-size"),
("bpy.types.softbodysettings.use_edges*", "physics/soft_body/settings/edges.html#bpy-types-softbodysettings-use-edges"),
("bpy.types.spaceclipeditor.show_gizmo*", "editors/clip/display/gizmo.html#bpy-types-spaceclipeditor-show-gizmo"),
("bpy.types.spacefilebrowser.bookmarks*", "editors/file_browser.html#bpy-types-spacefilebrowser-bookmarks"),
("bpy.types.spaceoutliner.display_mode*", "editors/outliner/interface.html#bpy-types-spaceoutliner-display-mode"),
("bpy.types.spaceoutliner.filter_state*", "editors/outliner/interface.html#bpy-types-spaceoutliner-filter-state"),
("bpy.types.spaceuveditor.show_stretch*", "editors/uv/overlays.html#bpy-types-spaceuveditor-show-stretch"),
("bpy.types.spotlight.shadow_soft_size*", "render/lights/light_object.html#bpy-types-spotlight-shadow-soft-size"),
("bpy.types.toolsettings.keyframe_type*", "editors/timeline.html#bpy-types-toolsettings-keyframe-type"),
("bpy.types.toolsettings.snap_elements*", "editors/3dview/controls/snapping.html#bpy-types-toolsettings-snap-elements"),
("bpy.types.toolsettings.use_snap_edit*", "editors/3dview/controls/snapping.html#bpy-types-toolsettings-use-snap-edit"),
@ -1321,6 +1347,7 @@ url_manual_mapping = (
("bpy.types.viewlayer.active_aov_index*", "render/layers/passes.html#bpy-types-viewlayer-active-aov-index"),
("bpy.ops.clip.tracking_object_remove*", "movie_clip/tracking/clip/sidebar/track/objects.html#bpy-ops-clip-tracking-object-remove"),
("bpy.ops.constraint.copy_to_selected*", "animation/constraints/interface/header.html#bpy-ops-constraint-copy-to-selected"),
("bpy.ops.curves.set_selection_domain*", "modeling/curves/primitives.html#bpy-ops-curves-set-selection-domain"),
("bpy.ops.gpencil.bake_mesh_animation*", "grease_pencil/animation/tools.html#bpy-ops-gpencil-bake-mesh-animation"),
("bpy.ops.gpencil.select_vertex_color*", "grease_pencil/selecting.html#bpy-ops-gpencil-select-vertex-color"),
("bpy.ops.gpencil.set_active_material*", "grease_pencil/modes/edit/stroke_menu.html#bpy-ops-gpencil-set-active-material"),
@ -1329,6 +1356,7 @@ url_manual_mapping = (
("bpy.ops.gpencil.vertex_color_invert*", "grease_pencil/modes/vertex_paint/editing.html#bpy-ops-gpencil-vertex-color-invert"),
("bpy.ops.gpencil.vertex_color_levels*", "grease_pencil/modes/vertex_paint/editing.html#bpy-ops-gpencil-vertex-color-levels"),
("bpy.ops.mask.slide_spline_curvature*", "movie_clip/masking/editing.html#bpy-ops-mask-slide-spline-curvature"),
("bpy.ops.mesh.flip_quad_tessellation*", "modeling/meshes/editing/face/face_data.html#bpy-ops-mesh-flip-quad-tessellation"),
("bpy.ops.mesh.primitive_cylinder_add*", "modeling/meshes/primitives.html#bpy-ops-mesh-primitive-cylinder-add"),
("bpy.ops.mesh.set_normals_from_faces*", "modeling/meshes/editing/mesh/normals.html#bpy-ops-mesh-set-normals-from-faces"),
("bpy.ops.mesh.shape_propagate_to_all*", "modeling/meshes/editing/vertex/propagate_shapes.html#bpy-ops-mesh-shape-propagate-to-all"),
@ -1390,6 +1418,7 @@ url_manual_mapping = (
("bpy.types.functionnodeseparatecolor*", "modeling/geometry_nodes/utilities/color/separate_color.html#bpy-types-functionnodeseparatecolor"),
("bpy.types.functionnodevaluetostring*", "modeling/geometry_nodes/utilities/text/value_to_string.html#bpy-types-functionnodevaluetostring"),
("bpy.types.geometrynodeblurattribute*", "modeling/geometry_nodes/attribute/blur_attribute.html#bpy-types-geometrynodeblurattribute"),
("bpy.types.geometrynodecornersofface*", "modeling/geometry_nodes/mesh/topology/corners_of_face.html#bpy-types-geometrynodecornersofface"),
("bpy.types.geometrynodecurvetopoints*", "modeling/geometry_nodes/curve/operations/curve_to_points.html#bpy-types-geometrynodecurvetopoints"),
("bpy.types.geometrynodeedgesofcorner*", "modeling/geometry_nodes/mesh/topology/edges_of_corner.html#bpy-types-geometrynodeedgesofcorner"),
("bpy.types.geometrynodeedgesofvertex*", "modeling/geometry_nodes/mesh/topology/edges_of_vertex.html#bpy-types-geometrynodeedgesofvertex"),
@ -1454,6 +1483,7 @@ url_manual_mapping = (
("bpy.types.worldmistsettings.falloff*", "render/cycles/world_settings.html#bpy-types-worldmistsettings-falloff"),
("bpy.ops.clip.lock_selection_toggle*", "editors/clip/introduction.html#bpy-ops-clip-lock-selection-toggle"),
("bpy.ops.ed.lib_id_generate_preview*", "editors/asset_browser.html#bpy-ops-ed-lib-id-generate-preview"),
("bpy.ops.geometry.attribute_convert*", "modeling/geometry_nodes/attributes_reference.html#bpy-ops-geometry-attribute-convert"),
("bpy.ops.mesh.customdata_mask_clear*", "modeling/meshes/properties/custom_data.html#bpy-ops-mesh-customdata-mask-clear"),
("bpy.ops.mesh.customdata_skin_clear*", "modeling/meshes/properties/custom_data.html#bpy-ops-mesh-customdata-skin-clear"),
("bpy.ops.mesh.extrude_vertices_move*", "modeling/meshes/editing/vertex/extrude_vertices.html#bpy-ops-mesh-extrude-vertices-move"),
@ -1564,6 +1594,7 @@ url_manual_mapping = (
("bpy.types.spaceuveditor.show_faces*", "editors/uv/overlays.html#bpy-types-spaceuveditor-show-faces"),
("bpy.types.spaceuveditor.uv_opacity*", "editors/uv/overlays.html#bpy-types-spaceuveditor-uv-opacity"),
("bpy.types.subdividegpencilmodifier*", "grease_pencil/modifiers/generate/subdivide.html#bpy-types-subdividegpencilmodifier"),
("bpy.types.texturenodehuesaturation*", "editors/texture_node/types/color/hue_saturation.html#bpy-types-texturenodehuesaturation"),
("bpy.types.texturenodeseparatecolor*", "editors/texture_node/types/color/separate_color.html#bpy-types-texturenodeseparatecolor"),
("bpy.types.thicknessgpencilmodifier*", "grease_pencil/modifiers/deform/thickness.html#bpy-types-thicknessgpencilmodifier"),
("bpy.types.toolsettings.snap_target*", "editors/3dview/controls/snapping.html#bpy-types-toolsettings-snap-target"),
@ -1599,6 +1630,9 @@ url_manual_mapping = (
("bpy.ops.object.multires_subdivide*", "modeling/modifiers/generate/multiresolution.html#bpy-ops-object-multires-subdivide"),
("bpy.ops.object.shape_key_transfer*", "animation/shape_keys/shape_keys_panel.html#bpy-ops-object-shape-key-transfer"),
("bpy.ops.object.vertex_group_clean*", "sculpt_paint/weight_paint/editing.html#bpy-ops-object-vertex-group-clean"),
("bpy.ops.paint.vertex_color_invert*", "sculpt_paint/vertex_paint/editing.html#bpy-ops-paint-vertex-color-invert"),
("bpy.ops.paint.vertex_color_levels*", "sculpt_paint/vertex_paint/editing.html#bpy-ops-paint-vertex-color-levels"),
("bpy.ops.paint.vertex_color_smooth*", "sculpt_paint/vertex_paint/editing.html#bpy-ops-paint-vertex-color-smooth"),
("bpy.ops.poselib.create_pose_asset*", "animation/armatures/posing/editing/pose_library.html#bpy-ops-poselib-create-pose-asset"),
("bpy.ops.preferences.theme_install*", "editors/preferences/themes.html#bpy-ops-preferences-theme-install"),
("bpy.ops.render.play_rendered_anim*", "render/output/animation_player.html#bpy-ops-render-play-rendered-anim"),
@ -1624,6 +1658,7 @@ url_manual_mapping = (
("bpy.types.compositornodealphaover*", "compositing/types/color/alpha_over.html#bpy-types-compositornodealphaover"),
("bpy.types.compositornodebokehblur*", "compositing/types/filter/bokeh_blur.html#bpy-types-compositornodebokehblur"),
("bpy.types.compositornodecomposite*", "compositing/types/output/composite.html#bpy-types-compositornodecomposite"),
("bpy.types.compositornodecornerpin*", "compositing/types/distort/corner_pin.html#bpy-types-compositornodecornerpin"),
("bpy.types.compositornodedespeckle*", "compositing/types/filter/despeckle.html#bpy-types-compositornodedespeckle"),
("bpy.types.compositornodediffmatte*", "compositing/types/matte/difference_key.html#bpy-types-compositornodediffmatte"),
("bpy.types.compositornodelumamatte*", "compositing/types/matte/luminance_key.html#bpy-types-compositornodelumamatte"),
@ -1661,7 +1696,7 @@ url_manual_mapping = (
("bpy.types.geometrynodeinputradius*", "modeling/geometry_nodes/geometry/read/radius.html#bpy-types-geometrynodeinputradius"),
("bpy.types.geometrynodemeshboolean*", "modeling/geometry_nodes/mesh/operations/mesh_boolean.html#bpy-types-geometrynodemeshboolean"),
("bpy.types.geometrynodemeshtocurve*", "modeling/geometry_nodes/mesh/operations/mesh_to_curve.html#bpy-types-geometrynodemeshtocurve"),
("bpy.types.geometrynodesamplecurve*", "modeling/geometry_nodes/curve/operations/sample_curve.html#bpy-types-geometrynodesamplecurve"),
("bpy.types.geometrynodesamplecurve*", "modeling/geometry_nodes/curve/sample/sample_curve.html#bpy-types-geometrynodesamplecurve"),
("bpy.types.geometrynodesampleindex*", "modeling/geometry_nodes/geometry/sample/sample_index.html#bpy-types-geometrynodesampleindex"),
("bpy.types.geometrynodesetmaterial*", "modeling/geometry_nodes/material/set_material.html#bpy-types-geometrynodesetmaterial"),
("bpy.types.geometrynodesetposition*", "modeling/geometry_nodes/geometry/write/set_position.html#bpy-types-geometrynodesetposition"),
@ -1729,7 +1764,6 @@ url_manual_mapping = (
("bpy.ops.mesh.primitive_plane_add*", "modeling/meshes/primitives.html#bpy-ops-mesh-primitive-plane-add"),
("bpy.ops.mesh.primitive_torus_add*", "modeling/meshes/primitives.html#bpy-ops-mesh-primitive-torus-add"),
("bpy.ops.mesh.select_non_manifold*", "modeling/meshes/selecting/all_by_trait.html#bpy-ops-mesh-select-non-manifold"),
("bpy.ops.object.attribute_convert*", "modeling/geometry_nodes/attributes_reference.html#bpy-ops-object-attribute-convert"),
("bpy.ops.object.constraints_clear*", "animation/constraints/interface/adding_removing.html#bpy-ops-object-constraints-clear"),
("bpy.ops.object.quadriflow_remesh*", "modeling/meshes/retopology.html#bpy-ops-object-quadriflow-remesh"),
("bpy.ops.object.vertex_group_copy*", "modeling/meshes/properties/vertex_groups/vertex_groups.html#bpy-ops-object-vertex-group-copy"),
@ -1780,6 +1814,7 @@ url_manual_mapping = (
("bpy.types.compositornodesetalpha*", "compositing/types/converter/set_alpha.html#bpy-types-compositornodesetalpha"),
("bpy.types.compositornodesunbeams*", "compositing/types/filter/sun_beams.html#bpy-types-compositornodesunbeams"),
("bpy.types.compositornodetrackpos*", "compositing/types/input/track_position.html#bpy-types-compositornodetrackpos"),
("bpy.types.compositornodevaltorgb*", "compositing/types/converter/color_ramp.html#bpy-types-compositornodevaltorgb"),
("bpy.types.compositornodezcombine*", "compositing/types/color/z_combine.html#bpy-types-compositornodezcombine"),
("bpy.types.constraint.owner_space*", "animation/constraints/interface/common.html#bpy-types-constraint-owner-space"),
("bpy.types.copylocationconstraint*", "animation/constraints/transform/copy_location.html#bpy-types-copylocationconstraint"),
@ -1802,7 +1837,7 @@ url_manual_mapping = (
("bpy.types.functionnodefloattoint*", "modeling/geometry_nodes/utilities/math/float_to_integer.html#bpy-types-functionnodefloattoint"),
("bpy.types.functionnodeinputcolor*", "modeling/geometry_nodes/input/constant/color.html#bpy-types-functionnodeinputcolor"),
("bpy.types.geometrynodeconvexhull*", "modeling/geometry_nodes/geometry/operations/convex_hull.html#bpy-types-geometrynodeconvexhull"),
("bpy.types.geometrynodeimageinput*", "modeling/geometry_nodes/input/constant/image.html#bpy-types-geometrynodeimageinput"),
("bpy.types.geometrynodeinputimage*", "modeling/geometry_nodes/input/constant/image.html#bpy-types-geometrynodeinputimage"),
("bpy.types.geometrynodeinputindex*", "modeling/geometry_nodes/geometry/read/input_index.html#bpy-types-geometrynodeinputindex"),
("bpy.types.geometrynodeisviewport*", "modeling/geometry_nodes/input/scene/is_viewport.html#bpy-types-geometrynodeisviewport"),
("bpy.types.geometrynodemeshcircle*", "modeling/geometry_nodes/mesh/primitives/mesh_circle.html#bpy-types-geometrynodemeshcircle"),
@ -1903,6 +1938,7 @@ url_manual_mapping = (
("bpy.ops.outliner.show_hierarchy*", "editors/outliner/editing.html#bpy-ops-outliner-show-hierarchy"),
("bpy.ops.outliner.show_one_level*", "editors/outliner/editing.html#bpy-ops-outliner-show-one-level"),
("bpy.ops.paint.brush_colors_flip*", "sculpt_paint/brush/brush_settings.html#bpy-ops-paint-brush-colors-flip"),
("bpy.ops.paint.vertex_color_dirt*", "sculpt_paint/vertex_paint/editing.html#bpy-ops-paint-vertex-color-dirt"),
("bpy.ops.paint.weight_from_bones*", "sculpt_paint/weight_paint/editing.html#bpy-ops-paint-weight-from-bones"),
("bpy.ops.paintcurve.delete_point*", "sculpt_paint/brush/stroke.html#bpy-ops-paintcurve-delete-point"),
("bpy.ops.pose.paths_range_update*", "animation/motion_paths.html#bpy-ops-pose-paths-range-update"),
@ -1954,7 +1990,6 @@ url_manual_mapping = (
("bpy.types.fluideffectorsettings*", "physics/fluid/type/effector.html#bpy-types-fluideffectorsettings"),
("bpy.types.followtrackconstraint*", "animation/constraints/motion_tracking/follow_track.html#bpy-types-followtrackconstraint"),
("bpy.types.functionnodeinputbool*", "modeling/geometry_nodes/input/constant/boolean.html#bpy-types-functionnodeinputbool"),
("bpy.types.geometrycornersofface*", "modeling/geometry_nodes/mesh/topology/corners_of_face.html#bpy-types-geometrycornersofface"),
("bpy.types.geometrynodecurvestar*", "modeling/geometry_nodes/curve/primitives/star.html#bpy-types-geometrynodecurvestar"),
("bpy.types.geometrynodefillcurve*", "modeling/geometry_nodes/curve/operations/fill_curve.html#bpy-types-geometrynodefillcurve"),
("bpy.types.geometrynodeflipfaces*", "modeling/geometry_nodes/mesh/operations/flip_faces.html#bpy-types-geometrynodeflipfaces"),
@ -1993,6 +2028,7 @@ url_manual_mapping = (
("bpy.types.shadernodeseparatexyz*", "render/shader_nodes/converter/separate_xyz.html#bpy-types-shadernodeseparatexyz"),
("bpy.types.shadernodeshadertorgb*", "render/shader_nodes/converter/shader_to_rgb.html#bpy-types-shadernodeshadertorgb"),
("bpy.types.shadernodetexgradient*", "render/shader_nodes/textures/gradient.html#bpy-types-shadernodetexgradient"),
("bpy.types.shadernodetexmusgrave*", "render/shader_nodes/textures/musgrave.html#bpy-types-shadernodetexmusgrave"),
("bpy.types.shadernodevectorcurve*", "render/shader_nodes/vector/curves.html#bpy-types-shadernodevectorcurve"),
("bpy.types.shadernodevertexcolor*", "render/shader_nodes/input/vertex_color.html#bpy-types-shadernodevertexcolor"),
("bpy.types.shapekey.relative_key*", "animation/shape_keys/shape_keys_panel.html#bpy-types-shapekey-relative-key"),
@ -2041,6 +2077,8 @@ url_manual_mapping = (
("bpy.ops.outliner.lib_operation*", "files/linked_libraries/link_append.html#bpy-ops-outliner-lib-operation"),
("bpy.ops.outliner.orphans_purge*", "editors/outliner/interface.html#bpy-ops-outliner-orphans-purge"),
("bpy.ops.paint.mask_box_gesture*", "sculpt_paint/sculpting/editing/mask.html#bpy-ops-paint-mask-box-gesture"),
("bpy.ops.paint.vertex_color_hsv*", "sculpt_paint/vertex_paint/editing.html#bpy-ops-paint-vertex-color-hsv"),
("bpy.ops.paint.vertex_color_set*", "sculpt_paint/vertex_paint/editing.html#bpy-ops-paint-vertex-color-set"),
("bpy.ops.pose.blend_to_neighbor*", "animation/armatures/posing/editing/in_betweens.html#bpy-ops-pose-blend-to-neighbor"),
("bpy.ops.screen.region_quadview*", "editors/3dview/navigate/views.html#bpy-ops-screen-region-quadview"),
("bpy.ops.screen.screenshot_area*", "interface/window_system/topbar.html#bpy-ops-screen-screenshot-area"),
@ -2126,6 +2164,7 @@ url_manual_mapping = (
("bpy.types.spacedopesheeteditor*", "editors/dope_sheet/index.html#bpy-types-spacedopesheeteditor"),
("bpy.types.spaceview3d.clip_end*", "editors/3dview/sidebar.html#bpy-types-spaceview3d-clip-end"),
("bpy.types.speedcontrolsequence*", "video_editing/edit/montage/strips/effects/speed_control.html#bpy-types-speedcontrolsequence"),
("bpy.types.spotlight.spot_blend*", "render/lights/light_object.html#bpy-types-spotlight-spot-blend"),
("bpy.types.texturenodecurvetime*", "editors/texture_node/types/input/time.html#bpy-types-texturenodecurvetime"),
("bpy.types.texturenodetexclouds*", "editors/texture_node/types/textures/clouds.html#bpy-types-texturenodetexclouds"),
("bpy.types.texturenodetexmarble*", "editors/texture_node/types/textures/marble.html#bpy-types-texturenodetexmarble"),
@ -2222,6 +2261,7 @@ url_manual_mapping = (
("bpy.types.curve.path_duration*", "modeling/curves/properties/path_animation.html#bpy-types-curve-path-duration"),
("bpy.types.curve.use_fill_caps*", "modeling/curves/properties/geometry.html#bpy-types-curve-use-fill-caps"),
("bpy.types.curve.use_map_taper*", "modeling/curves/properties/geometry.html#bpy-types-curve-use-map-taper"),
("bpy.types.curves.use_mirror_z*", "sculpt_paint/curves_sculpting/introduction.html#bpy-types-curves-use-mirror-z"),
("bpy.types.cyclesworldsettings*", "render/cycles/world_settings.html#bpy-types-cyclesworldsettings"),
("bpy.types.dashgpencilmodifier*", "grease_pencil/modifiers/generate/dash.html#bpy-types-dashgpencilmodifier"),
("bpy.types.fieldsettings.noise*", "physics/forces/force_fields/introduction.html#bpy-types-fieldsettings-noise"),
@ -2262,6 +2302,8 @@ url_manual_mapping = (
("bpy.types.spline.resolution_u*", "modeling/curves/properties/active_spline.html#bpy-types-spline-resolution-u"),
("bpy.types.spline.use_bezier_u*", "modeling/curves/properties/active_spline.html#bpy-types-spline-use-bezier-u"),
("bpy.types.spline.use_cyclic_u*", "modeling/curves/properties/active_spline.html#bpy-types-spline-use-cyclic-u"),
("bpy.types.spotlight.show_cone*", "render/lights/light_object.html#bpy-types-spotlight-show-cone"),
("bpy.types.spotlight.spot_size*", "render/lights/light_object.html#bpy-types-spotlight-spot-size"),
("bpy.types.stretchtoconstraint*", "animation/constraints/tracking/stretch_to.html#bpy-types-stretchtoconstraint"),
("bpy.types.texturenodecurvergb*", "editors/texture_node/types/color/rgb_curves.html#bpy-types-texturenodecurvergb"),
("bpy.types.texturenodedistance*", "editors/texture_node/types/converter/distance.html#bpy-types-texturenodedistance"),
@ -2269,7 +2311,7 @@ url_manual_mapping = (
("bpy.types.texturenodetexmagic*", "editors/texture_node/types/textures/magic.html#bpy-types-texturenodetexmagic"),
("bpy.types.texturenodetexnoise*", "editors/texture_node/types/textures/noise.html#bpy-types-texturenodetexnoise"),
("bpy.types.texturenodevaltonor*", "editors/texture_node/types/converter/value_to_normal.html#bpy-types-texturenodevaltonor"),
("bpy.types.texturenodevaltorgb*", "editors/texture_node/types/converter/rgb_to_bw.html#bpy-types-texturenodevaltorgb"),
("bpy.types.texturenodevaltorgb*", "editors/texture_node/types/converter/color_ramp.html#bpy-types-texturenodevaltorgb"),
("bpy.types.timegpencilmodifier*", "grease_pencil/modifiers/modify/time_offset.html#bpy-types-timegpencilmodifier"),
("bpy.types.tintgpencilmodifier*", "grease_pencil/modifiers/color/tint.html#bpy-types-tintgpencilmodifier"),
("bpy.types.transformconstraint*", "animation/constraints/transform/transformation.html#bpy-types-transformconstraint"),
@ -2393,6 +2435,7 @@ url_manual_mapping = (
("bpy.types.object.hide_select*", "scene_layout/object/properties/visibility.html#bpy-types-object-hide-select"),
("bpy.types.object.parent_type*", "scene_layout/object/properties/relations.html#bpy-types-object-parent-type"),
("bpy.types.object.show_bounds*", "scene_layout/object/properties/display.html#bpy-types-object-show-bounds"),
("bpy.types.palettecolor.color*", "interface/controls/templates/color_palette.html#bpy-types-palettecolor-color"),
("bpy.types.rendersettings.fps*", "render/output/properties/format.html#bpy-types-rendersettings-fps"),
("bpy.types.scene.audio_volume*", "scene_layout/scene/properties.html#bpy-types-scene-audio-volume"),
("bpy.types.sculpt.detail_size*", "sculpt_paint/sculpting/tool_settings/dyntopo.html#bpy-types-sculpt-detail-size"),
@ -2407,10 +2450,12 @@ url_manual_mapping = (
("bpy.types.shadernodeteximage*", "render/shader_nodes/textures/image.html#bpy-types-shadernodeteximage"),
("bpy.types.shadernodetexmagic*", "render/shader_nodes/textures/magic.html#bpy-types-shadernodetexmagic"),
("bpy.types.shadernodetexnoise*", "render/shader_nodes/textures/noise.html#bpy-types-shadernodetexnoise"),
("bpy.types.shadernodevaltorgb*", "render/shader_nodes/converter/color_ramp.html#bpy-types-shadernodevaltorgb"),
("bpy.types.shrinkwrapmodifier*", "modeling/modifiers/deform/shrinkwrap.html#bpy-types-shrinkwrapmodifier"),
("bpy.types.spaceview3d.camera*", "editors/3dview/sidebar.html#bpy-types-spaceview3d-camera"),
("bpy.types.splineikconstraint*", "animation/constraints/tracking/spline_ik.html#bpy-types-splineikconstraint"),
("bpy.types.texturenodechecker*", "editors/texture_node/types/patterns/checker.html#bpy-types-texturenodechecker"),
("bpy.types.texturenodergbtobw*", "editors/texture_node/types/converter/rgb_to_bw.html#bpy-types-texturenodergbtobw"),
("bpy.types.texturenodetexture*", "editors/texture_node/types/input/texture.html#bpy-types-texturenodetexture"),
("bpy.types.texturenodetexwood*", "editors/texture_node/types/textures/wood.html#bpy-types-texturenodetexwood"),
("bpy.types.textureslot.offset*", "sculpt_paint/brush/texture.html#bpy-types-textureslot-offset"),
@ -2424,6 +2469,7 @@ url_manual_mapping = (
("bpy.ops.armature.parent_set*", "animation/armatures/bones/editing/parenting.html#bpy-ops-armature-parent-set"),
("bpy.ops.armature.select_all*", "animation/armatures/bones/selecting.html#bpy-ops-armature-select-all"),
("bpy.ops.armature.symmetrize*", "animation/armatures/bones/editing/symmetrize.html#bpy-ops-armature-symmetrize"),
("bpy.ops.asset.catalogs_save*", "files/asset_libraries/catalogs.html#bpy-ops-asset-catalogs-save"),
("bpy.ops.clip.average_tracks*", "movie_clip/tracking/clip/editing/track.html#bpy-ops-clip-average-tracks"),
("bpy.ops.clip.refine_markers*", "movie_clip/tracking/clip/editing/track.html#bpy-ops-clip-refine-markers"),
("bpy.ops.clip.select_grouped*", "movie_clip/tracking/clip/selecting.html#bpy-ops-clip-select-grouped"),
@ -2525,6 +2571,7 @@ url_manual_mapping = (
("bpy.types.object.lightgroup*", "render/cycles/object_settings/object_data.html#bpy-types-object-lightgroup"),
("bpy.types.object.pass_index*", "scene_layout/object/properties/relations.html#bpy-types-object-pass-index"),
("bpy.types.object.track_axis*", "scene_layout/object/properties/relations.html#bpy-types-object-track-axis"),
("bpy.types.pointlight.energy*", "render/lights/light_object.html#bpy-types-pointlight-energy"),
("bpy.types.pose.use_mirror_x*", "animation/armatures/posing/tool_settings.html#bpy-types-pose-use-mirror-x"),
("bpy.types.preferencessystem*", "editors/preferences/system.html#bpy-types-preferencessystem"),
("bpy.types.scene.active_clip*", "scene_layout/scene/properties.html#bpy-types-scene-active-clip"),
@ -2541,6 +2588,7 @@ url_manual_mapping = (
("bpy.types.soundsequence.pan*", "editors/video_sequencer/sequencer/sidebar/strip.html#bpy-types-soundsequence-pan"),
("bpy.types.spline.use_smooth*", "modeling/curves/properties/active_spline.html#bpy-types-spline-use-smooth"),
("bpy.types.texturenodebricks*", "editors/texture_node/types/patterns/bricks.html#bpy-types-texturenodebricks"),
("bpy.types.texturenodeinvert*", "editors/texture_node/types/color/invert.html#bpy-types-texturenodeinvert"),
("bpy.types.texturenodemixrgb*", "editors/texture_node/types/color/mix_rgb.html#bpy-types-texturenodemixrgb"),
("bpy.types.texturenodeoutput*", "editors/texture_node/types/output/output.html#bpy-types-texturenodeoutput"),
("bpy.types.texturenoderotate*", "editors/texture_node/types/distort/rotate.html#bpy-types-texturenoderotate"),
@ -2555,6 +2603,8 @@ url_manual_mapping = (
("bpy.types.worldmistsettings*", "render/cycles/world_settings.html#bpy-types-worldmistsettings"),
("bpy.ops.anim.channels_move*", "editors/graph_editor/channels.html#bpy-ops-anim-channels-move"),
("bpy.ops.armature.subdivide*", "animation/armatures/bones/editing/subdivide.html#bpy-ops-armature-subdivide"),
("bpy.ops.asset.catalog_redo*", "editors/asset_browser.html#bpy-ops-asset-catalog-redo"),
("bpy.ops.asset.catalog_undo*", "editors/asset_browser.html#bpy-ops-asset-catalog-undo"),
("bpy.ops.brush.curve_preset*", "sculpt_paint/brush/falloff.html#bpy-ops-brush-curve-preset"),
("bpy.ops.buttons.toggle_pin*", "editors/properties_editor.html#bpy-ops-buttons-toggle-pin"),
("bpy.ops.clip.delete_marker*", "movie_clip/tracking/clip/editing/track.html#bpy-ops-clip-delete-marker"),
@ -2571,6 +2621,7 @@ url_manual_mapping = (
("bpy.ops.mask.paste_splines*", "movie_clip/masking/editing.html#bpy-ops-mask-paste-splines"),
("bpy.ops.mask.select_circle*", "movie_clip/masking/selecting.html#bpy-ops-mask-select-circle"),
("bpy.ops.mask.select_linked*", "movie_clip/masking/selecting.html#bpy-ops-mask-select-linked"),
("bpy.ops.mesh.attribute_set*", "modeling/meshes/editing/mesh/set_attribute.html#bpy-ops-mesh-attribute-set"),
("bpy.ops.mesh.beautify_fill*", "modeling/meshes/editing/face/beautify_faces.html#bpy-ops-mesh-beautify-fill"),
("bpy.ops.mesh.colors_rotate*", "modeling/meshes/editing/face/face_data.html#bpy-ops-mesh-colors-rotate"),
("bpy.ops.mesh.edge_collapse*", "modeling/meshes/editing/mesh/delete.html#bpy-ops-mesh-edge-collapse"),
@ -2611,6 +2662,7 @@ url_manual_mapping = (
("bpy.ops.wm.search_operator*", "interface/controls/templates/operator_search.html#bpy-ops-wm-search-operator"),
("bpy.types.actionconstraint*", "animation/constraints/relationship/action.html#bpy-types-actionconstraint"),
("bpy.types.addonpreferences*", "editors/preferences/addons.html#bpy-types-addonpreferences"),
("bpy.types.arealight.energy*", "render/lights/light_object.html#bpy-types-arealight-energy"),
("bpy.types.arealight.spread*", "render/cycles/light_settings.html#bpy-types-arealight-spread"),
("bpy.types.armaturemodifier*", "modeling/modifiers/deform/armature.html#bpy-types-armaturemodifier"),
("bpy.types.bone.head_radius*", "animation/armatures/bones/properties/deform.html#bpy-types-bone-head-radius"),
@ -2672,6 +2724,7 @@ url_manual_mapping = (
("bpy.types.spaceview3d.lens*", "editors/3dview/sidebar.html#bpy-types-spaceview3d-lens"),
("bpy.types.spaceview3d.show*", "editors/3dview/display/index.html#bpy-types-spaceview3d-show"),
("bpy.types.sphfluidsettings*", "physics/particles/emitter/physics/fluid.html#bpy-types-sphfluidsettings"),
("bpy.types.spotlight.energy*", "render/lights/light_object.html#bpy-types-spotlight-energy"),
("bpy.types.subtractsequence*", "video_editing/edit/montage/strips/effects/subtract.html#bpy-types-subtractsequence"),
("bpy.types.text.indentation*", "editors/text_editor.html#bpy-types-text-indentation"),
("bpy.types.texture.contrast*", "render/materials/legacy_textures/colors.html#bpy-types-texture-contrast"),
@ -2681,6 +2734,7 @@ url_manual_mapping = (
("bpy.types.world.lightgroup*", "render/cycles/world_settings.html#bpy-types-world-lightgroup"),
("bpy.ops.armature.dissolve*", "animation/armatures/bones/editing/delete.html#bpy-ops-armature-dissolve"),
("bpy.ops.armature.separate*", "animation/armatures/bones/editing/separate_bones.html#bpy-ops-armature-separate"),
("bpy.ops.asset.catalog_new*", "files/asset_libraries/catalogs.html#bpy-ops-asset-catalog-new"),
("bpy.ops.clip.clean_tracks*", "movie_clip/tracking/clip/editing/track.html#bpy-ops-clip-clean-tracks"),
("bpy.ops.clip.delete_track*", "movie_clip/tracking/clip/editing/track.html#bpy-ops-clip-delete-track"),
("bpy.ops.clip.select_lasso*", "movie_clip/tracking/clip/selecting.html#bpy-ops-clip-select-lasso"),
@ -2734,6 +2788,7 @@ url_manual_mapping = (
("bpy.ops.uv.sphere_project*", "modeling/meshes/editing/uv.html#bpy-ops-uv-sphere-project"),
("bpy.ops.view3d.view_orbit*", "editors/3dview/navigate/navigation.html#bpy-ops-view3d-view-orbit"),
("bpy.ops.wm.previews_clear*", "files/blend/previews.html#bpy-ops-wm-previews-clear"),
("bpy.types.arealight.shape*", "render/lights/light_object.html#bpy-types-arealight-shape"),
("bpy.types.armature.layers*", "animation/armatures/properties/skeleton.html#bpy-types-armature-layers"),
("bpy.types.armature.rigify*", "addons/rigging/rigify/basics.html#bpy-types-armature-rigify"),
("bpy.types.bone.use_deform*", "animation/armatures/bones/properties/deform.html#bpy-types-bone-use-deform"),
@ -2776,6 +2831,7 @@ url_manual_mapping = (
("bpy.types.spaceproperties*", "editors/properties_editor.html#bpy-types-spaceproperties"),
("bpy.types.spacetexteditor*", "editors/text_editor.html#bpy-types-spacetexteditor"),
("bpy.types.subsurfmodifier*", "modeling/modifiers/generate/subdivision_surface.html#bpy-types-subsurfmodifier"),
("bpy.types.sunlight.energy*", "render/lights/light_object.html#bpy-types-sunlight-energy"),
("bpy.types.texturenodemath*", "editors/texture_node/types/converter/math.html#bpy-types-texturenodemath"),
("bpy.types.volume.filepath*", "modeling/volumes/properties.html#bpy-types-volume-filepath"),
("bpy.ops.asset.tag_remove*", "editors/asset_browser.html#bpy-ops-asset-tag-remove"),
@ -2804,6 +2860,7 @@ url_manual_mapping = (
("bpy.ops.node.hide_toggle*", "interface/controls/nodes/editing.html#bpy-ops-node-hide-toggle"),
("bpy.ops.node.mute_toggle*", "interface/controls/nodes/editing.html#bpy-ops-node-mute-toggle"),
("bpy.ops.object.hide_view*", "scene_layout/object/editing/show_hide.html#bpy-ops-object-hide-view"),
("bpy.ops.object.quick_fur*", "physics/introduction.html#bpy-ops-object-quick-fur"),
("bpy.ops.object.track_set*", "animation/constraints/interface/adding_removing.html#bpy-ops-object-track-set"),
("bpy.ops.pose.paths_clear*", "animation/motion_paths.html#bpy-ops-pose-paths-clear"),
("bpy.ops.pose.scale_clear*", "animation/armatures/posing/editing/clear.html#bpy-ops-pose-scale-clear"),
@ -2830,6 +2887,8 @@ url_manual_mapping = (
("bpy.ops.wm.owner_disable*", "interface/window_system/workspaces.html#bpy-ops-wm-owner-disable"),
("bpy.ops.wm.save_homefile*", "interface/window_system/topbar.html#bpy-ops-wm-save-homefile"),
("bpy.ops.wm.save_mainfile*", "files/blend/open_save.html#bpy-ops-wm-save-mainfile"),
("bpy.types.arealight.size*", "render/lights/light_object.html#bpy-types-arealight-size"),
("bpy.types.attributegroup*", "modeling/meshes/properties/object_data.html#bpy-types-attributegroup"),
("bpy.types.bone.show_wire*", "animation/armatures/bones/properties/display.html#bpy-types-bone-show-wire"),
("bpy.types.brush.hardness*", "sculpt_paint/brush/brush_settings.html#bpy-types-brush-hardness"),
("bpy.types.brush.strength*", "sculpt_paint/brush/brush_settings.html#bpy-types-brush-strength"),
@ -2860,6 +2919,7 @@ url_manual_mapping = (
("bpy.types.smoothmodifier*", "modeling/modifiers/deform/smooth.html#bpy-types-smoothmodifier"),
("bpy.types.sound.use_mono*", "editors/video_sequencer/sequencer/sidebar/strip.html#bpy-types-sound-use-mono"),
("bpy.types.spline.order_u*", "modeling/curves/properties/active_spline.html#bpy-types-spline-order-u"),
("bpy.types.sunlight.angle*", "render/lights/light_object.html#bpy-types-sunlight-angle"),
("bpy.types.timelinemarker*", "animation/markers.html#bpy-types-timelinemarker"),
("bpy.types.usersolidlight*", "editors/preferences/lights.html#bpy-types-usersolidlight"),
("bpy.types.uvwarpmodifier*", "modeling/modifiers/modify/uv_warp.html#bpy-types-uvwarpmodifier"),
@ -3041,6 +3101,7 @@ url_manual_mapping = (
("bpy.types.object.delta*", "scene_layout/object/properties/transforms.html#bpy-types-object-delta"),
("bpy.types.object.empty*", "modeling/empties.html#bpy-types-object-empty"),
("bpy.types.object.scale*", "scene_layout/object/properties/transforms.html#bpy-types-object-scale"),
("bpy.types.palettecolor*", "interface/controls/templates/color_palette.html#bpy-types-palettecolor"),
("bpy.types.particleedit*", "physics/particles/mode.html#bpy-types-particleedit"),
("bpy.types.scene.camera*", "scene_layout/scene/properties.html#bpy-types-scene-camera"),
("bpy.types.sequencecrop*", "editors/video_sequencer/sequencer/sidebar/strip.html#bpy-types-sequencecrop"),
@ -3063,6 +3124,7 @@ url_manual_mapping = (
("bpy.ops.asset.tag_add*", "editors/asset_browser.html#bpy-ops-asset-tag-add"),
("bpy.ops.clip.prefetch*", "movie_clip/tracking/clip/editing/clip.html#bpy-ops-clip-prefetch"),
("bpy.ops.clip.set_axis*", "movie_clip/tracking/clip/editing/reconstruction.html#bpy-ops-clip-set-axis"),
("bpy.ops.curves.delete*", "modeling/curves/primitives.html#bpy-ops-curves-delete"),
("bpy.ops.file.pack_all*", "files/blend/packed_data.html#bpy-ops-file-pack-all"),
("bpy.ops.file.previous*", "editors/file_browser.html#bpy-ops-file-previous"),
("bpy.ops.gpencil.paste*", "grease_pencil/modes/edit/grease_pencil_menu.html#bpy-ops-gpencil-paste"),
@ -3153,6 +3215,7 @@ url_manual_mapping = (
("bpy.types.constraint*", "animation/constraints/index.html#bpy-types-constraint"),
("bpy.types.imagepaint*", "sculpt_paint/texture_paint/index.html#bpy-types-imagepaint"),
("bpy.types.keymapitem*", "editors/preferences/keymap.html#bpy-types-keymapitem"),
("bpy.types.light.type*", "render/lights/light_object.html#bpy-types-light-type"),
("bpy.types.lightprobe*", "render/eevee/light_probes/index.html#bpy-types-lightprobe"),
("bpy.types.maskparent*", "movie_clip/masking/sidebar.html#bpy-types-maskparent"),
("bpy.types.maskspline*", "movie_clip/masking/sidebar.html#bpy-types-maskspline"),
@ -3218,6 +3281,7 @@ url_manual_mapping = (
("bpy.ops.curve.spin*", "modeling/surfaces/editing/surface.html#bpy-ops-curve-spin"),
("bpy.ops.graph.bake*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-bake"),
("bpy.ops.graph.copy*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-copy"),
("bpy.ops.graph.ease*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-ease"),
("bpy.ops.graph.hide*", "editors/graph_editor/channels.html#bpy-ops-graph-hide"),
("bpy.ops.graph.snap*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-snap"),
("bpy.ops.image.flip*", "editors/image/editing.html#bpy-ops-image-flip"),
@ -3318,6 +3382,7 @@ url_manual_mapping = (
("bpy.ops.ed.undo*", "interface/undo_redo.html#bpy-ops-ed-undo"),
("bpy.ops.gpencil*", "grease_pencil/index.html#bpy-ops-gpencil"),
("bpy.ops.lattice*", "animation/lattice.html#bpy-ops-lattice"),
("bpy.ops.palette*", "interface/controls/templates/color_palette.html#bpy-ops-palette"),
("bpy.ops.poselib*", "animation/armatures/posing/editing/pose_library.html#bpy-ops-poselib"),
("bpy.ops.ptcache*", "physics/baking.html#bpy-ops-ptcache"),
("bpy.ops.surface*", "modeling/surfaces/index.html#bpy-ops-surface"),

View File

@ -330,6 +330,7 @@ class GRAPH_MT_slider(Menu):
layout.operator("graph.blend_to_neighbor", text="Blend to Neighbor")
layout.operator("graph.blend_to_default", text="Blend to Default Value")
layout.operator("graph.ease", text="Ease")
layout.operator("graph.gaussian_smooth", text="Smooth")
class GRAPH_MT_view_pie(Menu):

View File

@ -58,7 +58,7 @@ struct bDeformGroup *BKE_object_defgroup_find_name(const struct Object *ob, cons
*
* \param use_default: How to handle cases where no symmetrical group is found.
* - false: sets these indices to -1, indicating the group should be ignored.
* - true: sets the index to its location in the array (making the group point to it's self).
* - true: sets the index to its location in the array (making the group point to itself).
* Enable this for symmetrical actions which apply weight operations on symmetrical vertices
* where the symmetrical group will be used (if found), otherwise the same group is used.
*

View File

@ -93,7 +93,7 @@ void txt_sel_all(struct Text *text);
void txt_sel_clear(struct Text *text);
void txt_sel_line(struct Text *text);
void txt_sel_set(struct Text *text, int startl, int startc, int endl, int endc);
char *txt_sel_to_buf(struct Text *text, size_t *r_buf_strlen);
char *txt_sel_to_buf(const struct Text *text, size_t *r_buf_strlen);
void txt_insert_buf(struct Text *text, const char *in_buffer, int in_buffer_len)
ATTR_NONNULL(1, 2);
void txt_split_curline(struct Text *text);

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

@ -688,8 +688,10 @@ static void pbvh_draw_args_init(PBVH *pbvh, PBVH_GPU_Args *args, PBVHNode *node)
args->face_sets_color_default = pbvh->face_sets_color_default;
args->face_sets_color_seed = pbvh->face_sets_color_seed;
args->vert_positions = pbvh->vert_positions;
args->corner_verts = {pbvh->corner_verts, pbvh->mesh->totloop};
args->corner_edges = pbvh->mesh ? pbvh->mesh->corner_edges() : blender::Span<int>();
if (pbvh->mesh) {
args->corner_verts = {pbvh->corner_verts, pbvh->mesh->totloop};
args->corner_edges = pbvh->mesh->corner_edges();
}
args->polys = pbvh->polys;
args->mlooptri = pbvh->looptri;

View File

@ -1450,7 +1450,7 @@ char *txt_to_buf(Text *text, size_t *r_buf_strlen)
return buf;
}
char *txt_sel_to_buf(Text *text, size_t *r_buf_strlen)
char *txt_sel_to_buf(const Text *text, size_t *r_buf_strlen)
{
char *buf;
size_t length = 0;

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

@ -102,6 +102,11 @@ size_t BLI_str_utf8_as_utf32(char32_t *__restrict dst_w,
size_t maxncpy) ATTR_NONNULL(1, 2);
size_t BLI_str_utf32_as_utf8(char *__restrict dst, const char32_t *__restrict src, size_t maxncpy)
ATTR_NONNULL(1, 2);
/**
* \return The UTF-32 len in UTF-8 with a clamped length.
*/
size_t BLI_str_utf32_as_utf8_len_ex(const char32_t *src, size_t src_maxlen) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL(1);
/**
* \return The UTF-32 len in UTF-8.
*/

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

@ -147,6 +147,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
@ -347,6 +348,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 +535,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

@ -651,6 +651,18 @@ size_t BLI_str_utf32_as_utf8(char *__restrict dst,
return len;
}
size_t BLI_str_utf32_as_utf8_len_ex(const char32_t *src, const size_t src_maxlen)
{
size_t len = 0;
const char32_t *src_end = src + src_maxlen;
while ((src < src_end) && *src) {
len += BLI_str_utf8_from_unicode_len((uint)*src++);
}
return len;
}
size_t BLI_str_utf32_as_utf8_len(const char32_t *src)
{
size_t len = 0;

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())) {

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

@ -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;
@ -392,7 +398,56 @@ void blend_to_default_fcurve(PointerRNA *id_ptr, FCurve *fcu, const float factor
move_key(&fcu->bezt[i], key_y_value);
}
}
/* ---------------- */
void ED_ANIM_get_1d_gauss_kernel(const float sigma, const int kernel_size, double *r_kernel)
{
BLI_assert(sigma > 0.0f);
BLI_assert(kernel_size > 0);
const double sigma_sq = 2.0 * sigma * sigma;
double sum = 0.0;
for (int i = 0; i < kernel_size; i++) {
const double normalized_index = (double)i / (kernel_size - 1);
r_kernel[i] = exp(-normalized_index * normalized_index / sigma_sq);
if (i == 0) {
sum += r_kernel[i];
}
else {
/* We only calculate half the kernel,
* the normalization needs to take that into account. */
sum += r_kernel[i] * 2;
}
}
/* Normalize kernel values. */
for (int i = 0; i < kernel_size; i++) {
r_kernel[i] /= sum;
}
}
void smooth_fcurve_segment(FCurve *fcu,
FCurveSegment *segment,
float *samples,
const float factor,
const int kernel_size,
double *kernel)
{
const int segment_end_index = segment->start_index + segment->length;
const int segment_start_x = fcu->bezt[segment->start_index].vec[1][0];
for (int i = segment->start_index; i < segment_end_index; i++) {
const int sample_index = (int)(fcu->bezt[i].vec[1][0] - segment_start_x) + kernel_size;
/* Apply the kernel. */
double filter_result = samples[sample_index] * kernel[0];
for (int j = 1; j <= kernel_size; j++) {
const double kernel_value = kernel[j];
filter_result += samples[sample_index + j] * kernel_value;
filter_result += samples[sample_index - j] * kernel_value;
}
const float key_y_value = interpf((float)filter_result, samples[sample_index], factor);
move_key(&fcu->bezt[i], key_y_value);
}
}
/* ---------------- */
void ease_fcurve_segment(FCurve *fcu, FCurveSegment *segment, const float factor)
@ -680,6 +735,16 @@ typedef struct TempFrameValCache {
float frame, val;
} TempFrameValCache;
void sample_fcurve_segment(FCurve *fcu,
const float start_frame,
float *samples,
const int sample_count)
{
for (int i = 0; i < sample_count; i++) {
samples[i] = evaluate_fcurve(fcu, start_frame + i);
}
}
void sample_fcurve(FCurve *fcu)
{
BezTriple *bezt, *start = NULL, *end = NULL;

View File

@ -10,6 +10,7 @@
#include "BKE_asset.h"
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_icons.h"
#include "BKE_idtype.h"
#include "BKE_lib_id.h"
@ -52,7 +53,7 @@ void ED_asset_generate_preview(const bContext *C, ID *id)
BKE_previewimg_clear(preview);
}
UI_icon_render_id(C, nullptr, id, ICON_SIZE_PREVIEW, true);
UI_icon_render_id(C, nullptr, id, ICON_SIZE_PREVIEW, !G.background);
}
bool ED_asset_clear_id(ID *id)

View File

@ -57,6 +57,7 @@
#define MAXTEXT 32766
static int kill_selection(Object *obedit, int ins);
static char *font_select_to_buffer(Object *obedit);
/* -------------------------------------------------------------------- */
/** \name Internal Utilities
@ -453,6 +454,19 @@ static int kill_selection(Object *obedit, int ins) /* ins == new character len *
return direction;
}
static void font_select_update_primary_clipboard(Object *obedit)
{
if ((WM_capabilities_flag() & WM_CAPABILITY_PRIMARY_CLIPBOARD) == 0) {
return;
}
char *buf = font_select_to_buffer(obedit);
if (buf == NULL) {
return;
}
WM_clipboard_text_set(buf, true);
MEM_freeN(buf);
}
/** \} */
/* -------------------------------------------------------------------- */
@ -525,6 +539,29 @@ static bool font_paste_utf8(bContext *C, const char *str, const size_t str_len)
/** \} */
/* -------------------------------------------------------------------- */
/** \name Generic Copy Functions
* \{ */
static char *font_select_to_buffer(Object *obedit)
{
int selstart, selend;
if (!BKE_vfont_select_get(obedit, &selstart, &selend)) {
return NULL;
}
Curve *cu = obedit->data;
EditFont *ef = cu->editfont;
char32_t *text_buf = ef->textbuf + selstart;
const size_t text_buf_len = selend - selstart;
const size_t len_utf8 = BLI_str_utf32_as_utf8_len_ex(text_buf, text_buf_len + 1);
char *buf = MEM_mallocN(len_utf8 + 1, __func__);
BLI_str_utf32_as_utf8(buf, text_buf, len_utf8);
return buf;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Paste From File Operator
* \{ */
@ -864,6 +901,7 @@ static int font_select_all_exec(bContext *C, wmOperator *UNUSED(op))
ef->pos = ef->len;
text_update_edited(C, obedit, FO_SELCHANGE);
font_select_update_primary_clipboard(obedit);
return OPERATOR_FINISHED;
}
@ -1000,6 +1038,7 @@ static bool paste_selection(Object *obedit, ReportList *reports)
static int paste_text_exec(bContext *C, wmOperator *op)
{
const bool selection = RNA_boolean_get(op->ptr, "selection");
Object *obedit = CTX_data_edit_object(C);
int retval;
size_t len_utf8;
@ -1013,7 +1052,7 @@ static int paste_text_exec(bContext *C, wmOperator *op)
int len;
} clipboard_system = {NULL}, clipboard_vfont = {NULL};
clipboard_system.buf = WM_clipboard_text_get(false, &clipboard_system.len);
clipboard_system.buf = WM_clipboard_text_get(selection, &clipboard_system.len);
if (clipboard_system.buf == NULL) {
return OPERATOR_CANCELLED;
@ -1077,6 +1116,15 @@ void FONT_OT_text_paste(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
PropertyRNA *prop;
prop = RNA_def_boolean(ot->srna,
"selection",
0,
"Selection",
"Paste text selected elsewhere rather than copied (X11/Wayland only)");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/** \} */
@ -1216,6 +1264,7 @@ static int move_cursor(bContext *C, int type, const bool select)
if (select) {
ef->selend = ef->pos;
font_select_update_primary_clipboard(obedit);
}
text_update_edited(C, obedit, cursmove);

View File

@ -425,6 +425,17 @@ void blend_to_neighbor_fcurve_segment(struct FCurve *fcu,
struct FCurveSegment *segment,
float factor);
void breakdown_fcurve_segment(struct FCurve *fcu, struct FCurveSegment *segment, float factor);
/** Get a 1D gauss kernel. Since the kernel is symmetrical, only calculates the positive side.
* \param sigma The shape of the gauss distribution.
* \param kernel_size How long the kernel array is.
*/
void ED_ANIM_get_1d_gauss_kernel(const float sigma, int kernel_size, double *r_kernel);
void smooth_fcurve_segment(struct FCurve *fcu,
struct FCurveSegment *segment,
float *samples,
float factor,
int kernel_size,
double *kernel);
void ease_fcurve_segment(struct FCurve *fcu, struct FCurveSegment *segment, float factor);
bool decimate_fcurve(struct bAnimListElem *ale, float remove_ratio, float error_sq_max);
void blend_to_default_fcurve(struct PointerRNA *id_ptr, struct FCurve *fcu, float factor);
@ -433,6 +444,10 @@ void blend_to_default_fcurve(struct PointerRNA *id_ptr, struct FCurve *fcu, floa
*/
void smooth_fcurve(struct FCurve *fcu);
void sample_fcurve(struct FCurve *fcu);
void sample_fcurve_segment(struct FCurve *fcu,
float start_frame,
float *r_samples,
int sample_count);
/* ----------- */

View File

@ -74,7 +74,7 @@ class AbstractView {
* \note This drop target may be requested for each event. The view doesn't keep the drop target
* around currently. So it cannot contain persistent state.
*/
virtual std::unique_ptr<AbstractViewDropTarget> create_drop_target() const;
virtual std::unique_ptr<AbstractViewDropTarget> create_drop_target();
/** Listen to a notifier, returning true if a redraw is needed. */
virtual bool listen(const wmNotifier &) const;
@ -166,7 +166,7 @@ class AbstractViewItem {
* \note This drop target may be requested for each event. The view doesn't keep a drop target
* around currently. So it can not contain persistent state.
*/
virtual std::unique_ptr<AbstractViewItemDropTarget> create_drop_target() const;
virtual std::unique_ptr<AbstractViewItemDropTarget> create_drop_target();
/** Get the view this item is registered for using #AbstractView::register_item(). */
AbstractView &get_view() const;

View File

@ -111,8 +111,8 @@ bool drop_target_apply_drop(bContext &C,
*/
char *drop_target_tooltip(const DropTargetInterface &drop_target, const wmDrag &drag);
std::unique_ptr<DropTargetInterface> view_drop_target(const uiViewHandle *view_handle);
std::unique_ptr<DropTargetInterface> view_item_drop_target(const uiViewItemHandle *item_handle);
std::unique_ptr<DropTargetInterface> view_drop_target(uiViewHandle *view_handle);
std::unique_ptr<DropTargetInterface> view_item_drop_target(uiViewItemHandle *item_handle);
/**
* Try to find a view item with a drop target under the mouse cursor, or if not found, a view
* with a drop target.

View File

@ -2014,7 +2014,11 @@ void UI_block_end_ex(const bContext *C, uiBlock *block, const int xy[2], int r_x
break;
}
ui_block_views_bounds_calc(block);
/* Update bounds of all views in this block. If this block is a panel, this will be done later in
* #UI_panels_end(), because buttons are offset there. */
if (!block->panel) {
ui_block_views_bounds_calc(block);
}
if (block->rect.xmin == 0.0f && block->rect.xmax == 0.0f) {
UI_block_bounds_set_normal(block, 0);

View File

@ -1831,6 +1831,10 @@ void UI_panels_end(const bContext *C, ARegion *region, int *r_x, int *r_y)
LISTBASE_FOREACH (uiBlock *, block, &region->uiblocks) {
if (block->active && block->panel) {
ui_offset_panel_block(block);
/* Update bounds for all "views" in this block. Usually this is done in #UI_block_end(), but
* that wouldn't work because of the offset applied above. */
ui_block_views_bounds_calc(block);
}
}

View File

@ -62,7 +62,7 @@ void AbstractView::update_from_old(uiBlock &new_block)
/** \name Default implementations of virtual functions
* \{ */
std::unique_ptr<AbstractViewDropTarget> AbstractView::create_drop_target() const
std::unique_ptr<AbstractViewDropTarget> AbstractView::create_drop_target()
{
/* There's no drop target (and hence no drop support) by default. */
return nullptr;
@ -121,9 +121,9 @@ std::optional<rcti> AbstractView::get_bounds() const
/** \name General API functions
* \{ */
std::unique_ptr<DropTargetInterface> view_drop_target(const uiViewHandle *view_handle)
std::unique_ptr<DropTargetInterface> view_drop_target(uiViewHandle *view_handle)
{
const AbstractView &view = reinterpret_cast<const AbstractView &>(*view_handle);
AbstractView &view = reinterpret_cast<AbstractView &>(*view_handle);
return view.create_drop_target();
}

View File

@ -174,7 +174,7 @@ std::unique_ptr<AbstractViewItemDragController> AbstractViewItem::create_drag_co
return nullptr;
}
std::unique_ptr<AbstractViewItemDropTarget> AbstractViewItem::create_drop_target() const
std::unique_ptr<AbstractViewItemDropTarget> AbstractViewItem::create_drop_target()
{
/* There's no drop target (and hence no drop support) by default. */
return nullptr;
@ -221,9 +221,9 @@ bool AbstractViewItem::is_active() const
/** \name General API functions
* \{ */
std::unique_ptr<DropTargetInterface> view_item_drop_target(const uiViewItemHandle *item_handle)
std::unique_ptr<DropTargetInterface> view_item_drop_target(uiViewItemHandle *item_handle)
{
const AbstractViewItem &item = reinterpret_cast<const AbstractViewItem &>(*item_handle);
AbstractViewItem &item = reinterpret_cast<AbstractViewItem &>(*item_handle);
return item.create_drop_target();
}

View File

@ -194,7 +194,7 @@ namespace blender::ui {
std::unique_ptr<DropTargetInterface> region_views_find_drop_target_at(const ARegion *region,
const int xy[2])
{
const uiViewItemHandle *hovered_view_item = UI_region_views_find_item_at(region, xy);
uiViewItemHandle *hovered_view_item = UI_region_views_find_item_at(region, xy);
if (hovered_view_item) {
std::unique_ptr<DropTargetInterface> drop_target = view_item_drop_target(hovered_view_item);
if (drop_target) {
@ -204,7 +204,7 @@ std::unique_ptr<DropTargetInterface> region_views_find_drop_target_at(const AReg
/* Get style for some sensible padding around the view items. */
const uiStyle *style = UI_style_get_dpi();
const uiViewHandle *hovered_view = UI_region_view_find_at(region, xy, style->buttonspacex);
uiViewHandle *hovered_view = UI_region_view_find_at(region, xy, style->buttonspacex);
if (hovered_view) {
std::unique_ptr<DropTargetInterface> drop_target = view_drop_target(hovered_view);
if (drop_target) {

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

@ -344,9 +344,9 @@ static void um_arraystore_compact_ex(UndoMesh *um, const UndoMesh *um_ref, bool
/* Compacting can be time consuming, run in parallel.
*
* NOTE(@ideasman42): this could be further parallelized with every custom-data layer
* running in it's own thread. If this is a bottleneck it's worth considering.
* At the moment it seems fast enough to split by element type.
* Since this is it's self a background thread, using too many threads here could
* running in its own thread. If this is a bottleneck it's worth considering.
* At the moment it seems fast enough to split by domain.
* Since this is itself a background thread, using too many threads here could
* interfere with foreground tasks. */
blender::threading::parallel_invoke(
4096 < (me->totvert + me->totedge + me->totloop + me->totpoly),

View File

@ -34,6 +34,72 @@
#include "console_intern.h"
/* -------------------------------------------------------------------- */
/** \name Utilities
* \{ */
static char *console_select_to_buffer(SpaceConsole *sc)
{
if (sc->sel_start == sc->sel_end) {
return NULL;
}
ConsoleLine cl_dummy = {NULL};
console_scrollback_prompt_begin(sc, &cl_dummy);
int offset = 0;
for (ConsoleLine *cl = sc->scrollback.first; cl; cl = cl->next) {
offset += cl->len + 1;
}
char *buf_str = NULL;
if (offset != 0) {
offset -= 1;
int sel[2] = {offset - sc->sel_end, offset - sc->sel_start};
DynStr *buf_dyn = BLI_dynstr_new();
for (ConsoleLine *cl = sc->scrollback.first; cl; cl = cl->next) {
if (sel[0] <= cl->len && sel[1] >= 0) {
int sta = max_ii(sel[0], 0);
int end = min_ii(sel[1], cl->len);
if (BLI_dynstr_get_len(buf_dyn)) {
BLI_dynstr_append(buf_dyn, "\n");
}
BLI_dynstr_nappend(buf_dyn, cl->line + sta, end - sta);
}
sel[0] -= cl->len + 1;
sel[1] -= cl->len + 1;
}
buf_str = BLI_dynstr_get_cstring(buf_dyn);
BLI_dynstr_free(buf_dyn);
}
console_scrollback_prompt_end(sc, &cl_dummy);
return buf_str;
}
static void console_select_update_primary_clipboard(SpaceConsole *sc)
{
if ((WM_capabilities_flag() & WM_CAPABILITY_PRIMARY_CLIPBOARD) == 0) {
return;
}
if (sc->sel_start == sc->sel_end) {
return;
}
char *buf = console_select_to_buffer(sc);
if (buf == NULL) {
return;
}
WM_clipboard_text_set(buf, true);
MEM_freeN(buf);
}
/** \} */
/* so when we type - the view scrolls to the bottom */
static void console_scroll_bottom(ARegion *region)
{
@ -966,61 +1032,13 @@ void CONSOLE_OT_scrollback_append(wmOperatorType *ot)
static int console_copy_exec(bContext *C, wmOperator *UNUSED(op))
{
SpaceConsole *sc = CTX_wm_space_console(C);
DynStr *buf_dyn;
char *buf_str;
ConsoleLine *cl;
int sel[2];
int offset = 0;
ConsoleLine cl_dummy = {NULL};
if (sc->sel_start == sc->sel_end) {
char *buf = console_select_to_buffer(sc);
if (buf == NULL) {
return OPERATOR_CANCELLED;
}
console_scrollback_prompt_begin(sc, &cl_dummy);
for (cl = sc->scrollback.first; cl; cl = cl->next) {
offset += cl->len + 1;
}
if (offset == 0) {
console_scrollback_prompt_end(sc, &cl_dummy);
return OPERATOR_CANCELLED;
}
buf_dyn = BLI_dynstr_new();
offset -= 1;
sel[0] = offset - sc->sel_end;
sel[1] = offset - sc->sel_start;
for (cl = sc->scrollback.first; cl; cl = cl->next) {
if (sel[0] <= cl->len && sel[1] >= 0) {
int sta = max_ii(sel[0], 0);
int end = min_ii(sel[1], cl->len);
if (BLI_dynstr_get_len(buf_dyn)) {
BLI_dynstr_append(buf_dyn, "\n");
}
BLI_dynstr_nappend(buf_dyn, cl->line + sta, end - sta);
}
sel[0] -= cl->len + 1;
sel[1] -= cl->len + 1;
}
buf_str = BLI_dynstr_get_cstring(buf_dyn);
BLI_dynstr_free(buf_dyn);
WM_clipboard_text_set(buf_str, 0);
MEM_freeN(buf_str);
console_scrollback_prompt_end(sc, &cl_dummy);
WM_clipboard_text_set(buf, 0);
MEM_freeN(buf);
return OPERATOR_FINISHED;
}
@ -1038,14 +1056,15 @@ void CONSOLE_OT_copy(wmOperatorType *ot)
/* properties */
}
static int console_paste_exec(bContext *C, wmOperator *UNUSED(op))
static int console_paste_exec(bContext *C, wmOperator *op)
{
const bool selection = RNA_boolean_get(op->ptr, "selection");
SpaceConsole *sc = CTX_wm_space_console(C);
ARegion *region = CTX_wm_region(C);
ConsoleLine *ci = console_history_verify(C);
int buf_len;
char *buf_str = WM_clipboard_text_get(false, &buf_len);
char *buf_str = WM_clipboard_text_get(selection, &buf_len);
char *buf_step, *buf_next;
if (buf_str == NULL) {
@ -1091,6 +1110,13 @@ void CONSOLE_OT_paste(wmOperatorType *ot)
ot->exec = console_paste_exec;
/* properties */
PropertyRNA *prop;
prop = RNA_def_boolean(ot->srna,
"selection",
0,
"Selection",
"Paste text selected elsewhere rather than copied (X11/Wayland only)");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
typedef struct SetConsoleCursor {
@ -1146,18 +1172,12 @@ static void console_modal_select_apply(bContext *C, wmOperator *op, const wmEven
}
}
static void console_cursor_set_exit(bContext *UNUSED(C), wmOperator *op)
static void console_cursor_set_exit(bContext *C, wmOperator *op)
{
// SpaceConsole *sc = CTX_wm_space_console(C);
SpaceConsole *sc = CTX_wm_space_console(C);
SetConsoleCursor *scu = op->customdata;
#if 0
if (txt_has_sel(text)) {
buffer = txt_sel_to_buf(text);
WM_clipboard_text_set(buffer, 1);
MEM_freeN(buffer);
}
#endif
console_select_update_primary_clipboard(sc);
MEM_freeN(scu);
}
@ -1254,6 +1274,11 @@ static int console_selectword_invoke(bContext *C, wmOperator *UNUSED(op), const
}
console_scrollback_prompt_end(sc, &cl_dummy);
if (ret & OPERATOR_FINISHED) {
console_select_update_primary_clipboard(sc);
}
return ret;
}

View File

@ -90,7 +90,7 @@ class AssetCatalogTreeViewItem : public ui::BasicTreeViewItem {
/** Add drag support for catalog items. */
std::unique_ptr<ui::AbstractViewItemDragController> create_drag_controller() const override;
/** Add dropping support for catalog items. */
std::unique_ptr<ui::AbstractViewItemDropTarget> create_drop_target() const override;
std::unique_ptr<ui::AbstractViewItemDropTarget> create_drop_target() override;
};
class AssetCatalogDragController : public ui::AbstractViewItemDragController {
@ -154,7 +154,7 @@ class AssetCatalogTreeViewAllItem : public ui::BasicTreeViewItem {
bool on_drop(struct bContext *C, const wmDrag &drag) const override;
};
std::unique_ptr<ui::AbstractViewItemDropTarget> create_drop_target() const override;
std::unique_ptr<ui::AbstractViewItemDropTarget> create_drop_target() override;
};
class AssetCatalogTreeViewUnassignedItem : public ui::BasicTreeViewItem {
@ -168,7 +168,7 @@ class AssetCatalogTreeViewUnassignedItem : public ui::BasicTreeViewItem {
bool on_drop(struct bContext *C, const wmDrag &drag) const override;
};
std::unique_ptr<ui::AbstractViewItemDropTarget> create_drop_target() const override;
std::unique_ptr<ui::AbstractViewItemDropTarget> create_drop_target() override;
};
/* ---------------------------------------------------------------------- */
@ -340,7 +340,6 @@ bool AssetCatalogTreeViewItem::rename(StringRefNull new_name)
}
std::unique_ptr<ui::AbstractViewItemDropTarget> AssetCatalogTreeViewItem::create_drop_target()
const
{
return std::make_unique<AssetCatalogDropTarget>(
static_cast<AssetCatalogTreeView &>(get_tree_view()), catalog_item_);
@ -580,7 +579,6 @@ void AssetCatalogTreeViewAllItem::build_row(uiLayout &row)
}
std::unique_ptr<ui::AbstractViewItemDropTarget> AssetCatalogTreeViewAllItem::create_drop_target()
const
{
return std::make_unique<AssetCatalogTreeViewAllItem::DropTarget>(
static_cast<AssetCatalogTreeView &>(get_tree_view()));
@ -635,7 +633,7 @@ bool AssetCatalogTreeViewAllItem::DropTarget::on_drop(struct bContext * /*C*/,
/* ---------------------------------------------------------------------- */
std::unique_ptr<ui::AbstractViewItemDropTarget> AssetCatalogTreeViewUnassignedItem::
create_drop_target() const
create_drop_target()
{
return std::make_unique<AssetCatalogTreeViewUnassignedItem::DropTarget>(
static_cast<AssetCatalogTreeView &>(get_tree_view()));

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

@ -116,6 +116,7 @@ void GRAPH_OT_breakdown(struct wmOperatorType *ot);
void GRAPH_OT_ease(struct wmOperatorType *ot);
void GRAPH_OT_decimate(struct wmOperatorType *ot);
void GRAPH_OT_blend_to_default(struct wmOperatorType *ot);
void GRAPH_OT_gaussian_smooth(struct wmOperatorType *ot);
void GRAPH_OT_sample(struct wmOperatorType *ot);
void GRAPH_OT_bake(struct wmOperatorType *ot);
void GRAPH_OT_unbake(struct wmOperatorType *ot);

View File

@ -464,6 +464,7 @@ void graphedit_operatortypes(void)
WM_operatortype_append(GRAPH_OT_breakdown);
WM_operatortype_append(GRAPH_OT_ease);
WM_operatortype_append(GRAPH_OT_blend_to_default);
WM_operatortype_append(GRAPH_OT_gaussian_smooth);
WM_operatortype_append(GRAPH_OT_euler_filter);
WM_operatortype_append(GRAPH_OT_delete);
WM_operatortype_append(GRAPH_OT_duplicate);

View File

@ -69,6 +69,10 @@ typedef struct tGraphSliderOp {
/* Each operator has a specific update function. */
void (*modal_update)(struct bContext *, struct wmOperator *);
/* If an operator stores custom data, it also needs to provide the function to clean it up. */
void *operator_data;
void (*free_operator_data)(void *operator_data);
NumInput num;
} tGraphSliderOp;
@ -191,6 +195,10 @@ static void graph_slider_exit(bContext *C, wmOperator *op)
return;
}
if (gso->free_operator_data != NULL) {
gso->free_operator_data(gso->operator_data);
}
ScrArea *area = gso->area;
LinkData *link;
@ -1053,3 +1061,257 @@ void GRAPH_OT_ease(wmOperatorType *ot)
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Gauss Smooth Operator
* \{ */
/* It is necessary to store data for smoothing when running in modal, because the sampling of
* FCurves shouldn't be done on every update. */
typedef struct tGaussOperatorData {
double *kernel;
ListBase segment_links; /* tFCurveSegmentLink */
ListBase anim_data; /* bAnimListElem */
} tGaussOperatorData;
/* Store data to smooth an FCurve segment. */
typedef struct tFCurveSegmentLink {
struct tFCurveSegmentLink *prev, *next;
FCurve *fcu;
FCurveSegment *segment;
float *samples; /* Array of y-values of the FCurve segment. */
} tFCurveSegmentLink;
static void gaussian_smooth_allocate_operator_data(tGraphSliderOp *gso,
const int filter_width,
const float sigma)
{
tGaussOperatorData *operator_data = MEM_callocN(sizeof(tGaussOperatorData),
"tGaussOperatorData");
const int kernel_size = filter_width + 1;
double *kernel = MEM_callocN(sizeof(double) * kernel_size, "Gauss Kernel");
ED_ANIM_get_1d_gauss_kernel(sigma, kernel_size, kernel);
operator_data->kernel = kernel;
ListBase anim_data = {NULL, NULL};
ANIM_animdata_filter(&gso->ac, &anim_data, OPERATOR_DATA_FILTER, gso->ac.data, gso->ac.datatype);
ListBase segment_links = {NULL, NULL};
LISTBASE_FOREACH (bAnimListElem *, ale, &anim_data) {
FCurve *fcu = (FCurve *)ale->key_data;
ListBase fcu_segments = find_fcurve_segments(fcu);
LISTBASE_FOREACH (FCurveSegment *, segment, &fcu_segments) {
tFCurveSegmentLink *segment_link = MEM_callocN(sizeof(tFCurveSegmentLink),
"FCurve Segment Link");
segment_link->fcu = fcu;
segment_link->segment = segment;
BezTriple left_bezt = fcu->bezt[segment->start_index];
BezTriple right_bezt = fcu->bezt[segment->start_index + segment->length - 1];
const int sample_count = (int)(right_bezt.vec[1][0] - left_bezt.vec[1][0]) +
(filter_width * 2 + 1);
float *samples = MEM_callocN(sizeof(float) * sample_count, "Smooth FCurve Op Samples");
sample_fcurve_segment(fcu, left_bezt.vec[1][0] - filter_width, samples, sample_count);
segment_link->samples = samples;
BLI_addtail(&segment_links, segment_link);
}
}
operator_data->anim_data = anim_data;
operator_data->segment_links = segment_links;
gso->operator_data = operator_data;
}
static void gaussian_smooth_free_operator_data(void *operator_data)
{
tGaussOperatorData *gauss_data = (tGaussOperatorData *)operator_data;
LISTBASE_FOREACH (tFCurveSegmentLink *, segment_link, &gauss_data->segment_links) {
MEM_freeN(segment_link->samples);
MEM_freeN(segment_link->segment);
}
MEM_freeN(gauss_data->kernel);
BLI_freelistN(&gauss_data->segment_links);
ANIM_animdata_freelist(&gauss_data->anim_data);
MEM_freeN(gauss_data);
}
static void gaussian_smooth_draw_status_header(bContext *C, tGraphSliderOp *gso)
{
char status_str[UI_MAX_DRAW_STR];
char slider_string[UI_MAX_DRAW_STR];
ED_slider_status_string_get(gso->slider, slider_string, UI_MAX_DRAW_STR);
const char *mode_str = TIP_("Gaussian Smooth");
if (hasNumInput(&gso->num)) {
char str_ofs[NUM_STR_REP_LEN];
outputNumInput(&gso->num, str_ofs, &gso->scene->unit);
BLI_snprintf(status_str, sizeof(status_str), "%s: %s", mode_str, str_ofs);
}
else {
BLI_snprintf(status_str, sizeof(status_str), "%s: %s", mode_str, slider_string);
}
ED_workspace_status_text(C, status_str);
}
static void gaussian_smooth_modal_update(bContext *C, wmOperator *op)
{
tGraphSliderOp *gso = op->customdata;
bAnimContext ac;
if (ANIM_animdata_get_context(C, &ac) == 0) {
return;
}
gaussian_smooth_draw_status_header(C, gso);
const float factor = slider_factor_get_and_remember(op);
tGaussOperatorData *operator_data = (tGaussOperatorData *)gso->operator_data;
const int filter_width = RNA_int_get(op->ptr, "filter_width");
LISTBASE_FOREACH (tFCurveSegmentLink *, segment, &operator_data->segment_links) {
smooth_fcurve_segment(segment->fcu,
segment->segment,
segment->samples,
factor,
filter_width,
operator_data->kernel);
}
LISTBASE_FOREACH (bAnimListElem *, ale, &operator_data->anim_data) {
ale->update |= ANIM_UPDATE_DEFAULT;
}
ANIM_animdata_update(&ac, &operator_data->anim_data);
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
}
static int gaussian_smooth_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
const int invoke_result = graph_slider_invoke(C, op, event);
if (invoke_result == OPERATOR_CANCELLED) {
return invoke_result;
}
tGraphSliderOp *gso = op->customdata;
gso->modal_update = gaussian_smooth_modal_update;
gso->factor_prop = RNA_struct_find_property(op->ptr, "factor");
const float sigma = RNA_float_get(op->ptr, "sigma");
const int filter_width = RNA_int_get(op->ptr, "filter_width");
gaussian_smooth_allocate_operator_data(gso, filter_width, sigma);
gso->free_operator_data = gaussian_smooth_free_operator_data;
ED_slider_allow_overshoot_set(gso->slider, false);
ED_slider_factor_set(gso->slider, 0.0f);
gaussian_smooth_draw_status_header(C, gso);
return invoke_result;
}
static void gaussian_smooth_graph_keys(bAnimContext *ac,
const float factor,
double *kernel,
const int filter_width)
{
ListBase anim_data = {NULL, NULL};
ANIM_animdata_filter(ac, &anim_data, OPERATOR_DATA_FILTER, ac->data, ac->datatype);
LISTBASE_FOREACH (bAnimListElem *, ale, &anim_data) {
FCurve *fcu = (FCurve *)ale->key_data;
ListBase segments = find_fcurve_segments(fcu);
LISTBASE_FOREACH (FCurveSegment *, segment, &segments) {
BezTriple left_bezt = fcu->bezt[segment->start_index];
BezTriple right_bezt = fcu->bezt[segment->start_index + segment->length - 1];
const int sample_count = (int)(right_bezt.vec[1][0] - left_bezt.vec[1][0]) +
(filter_width * 2 + 1);
float *samples = MEM_callocN(sizeof(float) * sample_count, "Smooth FCurve Op Samples");
sample_fcurve_segment(fcu, left_bezt.vec[1][0] - filter_width, samples, sample_count);
smooth_fcurve_segment(fcu, segment, samples, factor, filter_width, kernel);
MEM_freeN(samples);
}
BLI_freelistN(&segments);
ale->update |= ANIM_UPDATE_DEFAULT;
}
ANIM_animdata_update(ac, &anim_data);
ANIM_animdata_freelist(&anim_data);
}
static int gaussian_smooth_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
if (ANIM_animdata_get_context(C, &ac) == 0) {
return OPERATOR_CANCELLED;
}
const float factor = RNA_float_get(op->ptr, "factor");
const int filter_width = RNA_int_get(op->ptr, "filter_width");
const int kernel_size = filter_width + 1;
double *kernel = MEM_callocN(sizeof(double) * kernel_size, "Gauss Kernel");
ED_ANIM_get_1d_gauss_kernel(RNA_float_get(op->ptr, "sigma"), kernel_size, kernel);
gaussian_smooth_graph_keys(&ac, factor, kernel, filter_width);
MEM_freeN(kernel);
/* Set notifier that keyframes have changed. */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL);
return OPERATOR_FINISHED;
}
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 Gaussian filter";
/* API callbacks. */
ot->invoke = gaussian_smooth_invoke;
ot->modal = graph_slider_modal;
ot->exec = gaussian_smooth_exec;
ot->poll = graphop_editable_keyframes_poll;
/* Flags. */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
RNA_def_float_factor(ot->srna,
"factor",
1.0f,
0.0f,
FLT_MAX,
"Factor",
"How much to blend to the default value",
0.0f,
1.0f);
RNA_def_float(ot->srna,
"sigma",
0.33f,
0.001f,
FLT_MAX,
"Sigma",
"The shape of the gaussian distribution, lower values make it sharper",
0.001f,
100.0f);
RNA_def_int(ot->srna,
"filter_width",
6,
1,
64,
"Filter Width",
"How far to each side the operator will average the key values",
1,
32);
}
/** \} */

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

@ -159,6 +159,22 @@ BLI_INLINE int text_pixel_x_to_column(SpaceText *st, const int x)
return (x + (st->runtime.cwidth_px / 2)) / st->runtime.cwidth_px;
}
static void text_select_update_primary_clipboard(const Text *text)
{
if ((WM_capabilities_flag() & WM_CAPABILITY_PRIMARY_CLIPBOARD) == 0) {
return;
}
if (!txt_has_sel(text)) {
return;
}
char *buf = txt_sel_to_buf(text, NULL);
if (buf == NULL) {
return;
}
WM_clipboard_text_set(buf, true);
MEM_freeN(buf);
}
/** \} */
/* -------------------------------------------------------------------- */
@ -954,11 +970,13 @@ void TEXT_OT_paste(wmOperatorType *ot)
ot->flag = OPTYPE_UNDO;
/* properties */
RNA_def_boolean(ot->srna,
"selection",
0,
"Selection",
"Paste text selected elsewhere rather than copied (X11 only)");
PropertyRNA *prop;
prop = RNA_def_boolean(ot->srna,
"selection",
0,
"Selection",
"Paste text selected elsewhere rather than copied (X11/Wayland only)");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/** \} */
@ -1499,6 +1517,8 @@ static int text_select_all_exec(bContext *C, wmOperator *UNUSED(op))
txt_sel_all(text);
text_update_cursor_moved(C);
text_select_update_primary_clipboard(text);
WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
return OPERATOR_FINISHED;
@ -1529,6 +1549,8 @@ static int text_select_line_exec(bContext *C, wmOperator *UNUSED(op))
txt_sel_line(text);
text_update_cursor_moved(C);
text_select_update_primary_clipboard(text);
WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
return OPERATOR_FINISHED;
@ -1562,6 +1584,8 @@ static int text_select_word_exec(bContext *C, wmOperator *UNUSED(op))
txt_jump_right(text, true, use_init_step);
text_update_cursor_moved(C);
text_select_update_primary_clipboard(text);
WM_event_add_notifier(C, NC_TEXT | NA_EDITED, text);
return OPERATOR_FINISHED;
@ -2246,6 +2270,10 @@ static int text_move_cursor(bContext *C, int type, bool select)
}
text_update_cursor_moved(C);
if (select) {
text_select_update_primary_clipboard(st->text);
}
WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, text);
return OPERATOR_FINISHED;
@ -3243,17 +3271,11 @@ static void text_cursor_set_apply(bContext *C, wmOperator *op, const wmEvent *ev
static void text_cursor_set_exit(bContext *C, wmOperator *op)
{
SpaceText *st = CTX_wm_space_text(C);
Text *text = st->text;
SetSelection *ssel = op->customdata;
char *buffer;
if (txt_has_sel(text)) {
buffer = txt_sel_to_buf(text, NULL);
WM_clipboard_text_set(buffer, 1);
MEM_freeN(buffer);
}
text_update_cursor_moved(C);
text_select_update_primary_clipboard(st->text);
WM_event_add_notifier(C, NC_TEXT | ND_CURSOR, st->text);
text_cursor_timer_remove(C, ssel);

View File

@ -52,7 +52,7 @@
* would be used for this purpose. The problem with using poll is once the gizmo is visible again
* is there is a visible flicker showing the previous location before cursor motion causes the
* pre selection to be updated. While this is only a glitch, it's distracting.
* The gizmo system it's self could support this use case by tracking which gizmos draw and ensure
* The gizmo system itself could support this use case by tracking which gizmos draw and ensure
* gizmos always run #wmGizmoType.test_select before drawing, however pre-selection is already
* outside the scope of what gizmos are meant to be used for, so keep this workaround localized
* to this gizmo type unless this seems worth supporting for more typical use-cases.

View File

@ -421,27 +421,29 @@ 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. */
int t = 0;
while (t <= scan_line) {
const float t_bscaled = t / occupancy.bitmap_scale_reciprocal;
/* Scan using an "Alpaca"-style search, both horizontally and vertically at the same time. */
const float2 horiz(scan_line_bscaled - size_x_scaled, t_bscaled - size_y_scaled);
const float extentH = occupancy.trace_island(island, scale, margin, horiz, false);
if (extentH < 0.0f) {
return horiz;
const float2 probe(scan_line_bscaled - size_x_scaled, t_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));
}
const float2 vert(t_bscaled - size_x_scaled, scan_line_bscaled - size_y_scaled);
const float extentV = occupancy.trace_island(island, scale, margin, vert, false);
if (extentV < 0.0f) {
return vert;
/* 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;
}
const float min_extent = std::min(extentH, extentV);
t = t + std::max(1, int(min_extent));
t = t + std::max(1, int(extent));
}
return float2(-1, -1);
}

View File

@ -2439,6 +2439,17 @@ static float p_abf_compute_gradient(PAbfSystem *sys, PChart *chart)
return norm;
}
static void p_abf_adjust_alpha(PAbfSystem *sys,
const int id,
const float dlambda1,
const float pre)
{
float alpha = sys->alpha[id];
const float dalpha = (sys->bAlpha[id] - dlambda1);
alpha += dalpha / sys->weight[id] - pre;
sys->alpha[id] = clamp_f(alpha, 0.0f, float(M_PI));
}
static bool p_abf_matrix_invert(PAbfSystem *sys, PChart *chart)
{
int ninterior = sys->ninterior;
@ -2596,11 +2607,11 @@ static bool p_abf_matrix_invert(PAbfSystem *sys, PChart *chart)
if (success) {
for (PFace *f = chart->faces; f; f = f->nextlink) {
float dlambda1, pre[3], dalpha;
float pre[3];
PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
pre[0] = pre[1] = pre[2] = 0.0;
pre[0] = pre[1] = pre[2] = 0.0f;
if (v1->flag & PVERT_INTERIOR) {
float x = EIG_linear_solver_variable_get(context, 0, v1->u.id);
@ -2626,30 +2637,14 @@ static bool p_abf_matrix_invert(PAbfSystem *sys, PChart *chart)
pre[2] += sys->J2dt[e3->u.id][2] * x;
}
dlambda1 = pre[0] + pre[1] + pre[2];
float dlambda1 = pre[0] + pre[1] + pre[2];
dlambda1 = sys->dstar[f->u.id] * (sys->bstar[f->u.id] - dlambda1);
sys->lambdaTriangle[f->u.id] += dlambda1;
dalpha = (sys->bAlpha[e1->u.id] - dlambda1);
sys->alpha[e1->u.id] += dalpha / sys->weight[e1->u.id] - pre[0];
dalpha = (sys->bAlpha[e2->u.id] - dlambda1);
sys->alpha[e2->u.id] += dalpha / sys->weight[e2->u.id] - pre[1];
dalpha = (sys->bAlpha[e3->u.id] - dlambda1);
sys->alpha[e3->u.id] += dalpha / sys->weight[e3->u.id] - pre[2];
/* clamp */
PEdge *e = f->edge;
do {
if (sys->alpha[e->u.id] > float(M_PI)) {
sys->alpha[e->u.id] = float(M_PI);
}
else if (sys->alpha[e->u.id] < 0.0f) {
sys->alpha[e->u.id] = 0.0f;
}
} while (e != f->edge);
p_abf_adjust_alpha(sys, e1->u.id, dlambda1, pre[0]);
p_abf_adjust_alpha(sys, e2->u.id, dlambda1, pre[1]);
p_abf_adjust_alpha(sys, e3->u.id, dlambda1, pre[2]);
}
for (int i = 0; i < ninterior; i++) {

View File

@ -374,7 +374,7 @@ typedef struct LineartData {
bool do_shadow_cast;
bool light_reference_available;
/* Keep an copy of these data so when line art is running it's self-contained. */
/* Keep an copy of these data so when line art is running itself contained. */
bool cam_is_persp;
/* "Secondary" ones are from viewing camera
* (as opposed to shadow camera), during shadow calculation. */

View File

@ -52,6 +52,7 @@ endif()
set(INC_SYS
${Epoxy_INCLUDE_DIRS}
${IMATH_INCLUDE_DIR}
)
set(SRC
@ -203,6 +204,7 @@ set(VULKAN_SRC
vulkan/vk_command_buffer.cc
vulkan/vk_common.cc
vulkan/vk_context.cc
vulkan/vk_data_conversion.cc
vulkan/vk_debug.cc
vulkan/vk_descriptor_pools.cc
vulkan/vk_descriptor_set.cc
@ -216,6 +218,7 @@ set(VULKAN_SRC
vulkan/vk_pixel_buffer.cc
vulkan/vk_push_constants.cc
vulkan/vk_query.cc
vulkan/vk_resource_tracker.cc
vulkan/vk_shader.cc
vulkan/vk_shader_interface.cc
vulkan/vk_shader_log.cc
@ -231,6 +234,7 @@ set(VULKAN_SRC
vulkan/vk_command_buffer.hh
vulkan/vk_common.hh
vulkan/vk_context.hh
vulkan/vk_data_conversion.hh
vulkan/vk_descriptor_pools.hh
vulkan/vk_descriptor_set.hh
vulkan/vk_drawlist.hh
@ -243,6 +247,7 @@ set(VULKAN_SRC
vulkan/vk_pixel_buffer.hh
vulkan/vk_push_constants.hh
vulkan/vk_query.hh
vulkan/vk_resource_tracker.hh
vulkan/vk_shader.hh
vulkan/vk_shader_interface.hh
vulkan/vk_shader_log.hh

View File

@ -213,7 +213,8 @@ void Texture::detach_from(FrameBuffer *fb)
void Texture::update(eGPUDataFormat format, const void *data)
{
int mip = 0;
int extent[3], offset[3] = {0, 0, 0};
int extent[3] = {1, 1, 1};
int offset[3] = {0, 0, 0};
this->mip_size_get(mip, extent);
this->update_sub(mip, offset, extent, format, data);
}

View File

@ -759,7 +759,8 @@ inline size_t to_bytesize(eGPUTextureFormat tex_format, eGPUDataFormat data_form
}
/* Definitely not complete, edit according to the gl specification. */
inline bool validate_data_format(eGPUTextureFormat tex_format, eGPUDataFormat data_format)
constexpr inline bool validate_data_format(eGPUTextureFormat tex_format,
eGPUDataFormat data_format)
{
switch (tex_format) {
/* Formats texture & render-buffer */

View File

@ -78,6 +78,11 @@ struct Shader {
GPUShader *shader = nullptr;
Vector<CallData> call_datas;
Shader()
{
call_datas.reserve(10);
}
~Shader()
{
if (shader != nullptr) {
@ -117,7 +122,9 @@ struct Shader {
void dispatch()
{
GPU_compute_dispatch(shader, 1, 1, 1);
/* Dispatching 1000000 times to add some stress to the GPU. Without it tests may succeed when
* using too simple shaders. */
GPU_compute_dispatch(shader, 1000, 1000, 1);
}
};
@ -177,11 +184,7 @@ static void test_push_constants_512bytes()
}
GPU_TEST(push_constants_512bytes)
#if 0
/* Schedule multiple simultaneously. */
/* These test have been disabled for now as this will to be solved in a separate PR.
* - `DescriptorSets` may not be altered, when they are in the command queue or being executed.
*/
static void test_push_constants_multiple()
{
do_push_constants_test("gpu_push_constants_test", 10);
@ -205,6 +208,5 @@ static void test_push_constants_multiple_512bytes()
do_push_constants_test("gpu_push_constants_512bytes_test", 10);
}
GPU_TEST(push_constants_multiple_512bytes)
#endif
} // namespace blender::gpu::tests

View File

@ -5,10 +5,23 @@
#include "MEM_guardedalloc.h"
#include "BLI_math_vector.hh"
#include "BLI_vector.hh"
#include "GPU_context.h"
#include "GPU_texture.h"
#include "gpu_texture_private.hh"
/* Not all texture types are supported by all platforms. This define safe guards them until we have
* a working workaround or decided to remove support for those texture types. */
#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. */
#define RUN_SRGB_UNIMPLEMENTED false
#define RUN_NON_STANDARD_UNIMPLEMENTED false
#define RUN_COMPONENT_UNIMPLEMENTED false
namespace blender::gpu::tests {
static void test_texture_read()
@ -48,4 +61,709 @@ static void test_texture_read()
}
GPU_TEST(texture_read)
template<typename DataType> static DataType *generate_test_data(size_t data_len)
{
DataType *data = static_cast<DataType *>(MEM_mallocN(data_len * sizeof(DataType), __func__));
for (int i : IndexRange(data_len)) {
if (std::is_same<DataType, float>()) {
data[i] = (DataType)(i % 8) / 8.0f;
}
else {
data[i] = (DataType)(i % 8);
}
}
return data;
}
template<eGPUTextureFormat DeviceFormat,
eGPUDataFormat HostFormat,
typename DataType,
int Size = 16>
static void texture_create_upload_read()
{
static_assert(!std::is_same<DataType, float>());
static_assert(validate_data_format(DeviceFormat, HostFormat));
eGPUTextureUsage usage = GPU_TEXTURE_USAGE_ATTACHMENT | GPU_TEXTURE_USAGE_HOST_READ;
GPUTexture *texture = GPU_texture_create_2d(
"texture", Size, Size, 1, DeviceFormat, usage, nullptr);
if (texture == nullptr) {
GTEST_SKIP() << "Platform doesn't support texture format [" << STRINGIFY(DeviceFormat) << "]";
}
size_t data_len = Size * Size * to_component_len(DeviceFormat);
DataType *data = static_cast<DataType *>(generate_test_data<DataType>(data_len));
GPU_texture_update(texture, HostFormat, data);
DataType *read_data = static_cast<DataType *>(GPU_texture_read(texture, HostFormat, 0));
bool failed = false;
for (int i : IndexRange(data_len)) {
bool ok = (read_data[i] - data[i]) == 0;
failed |= !ok;
}
EXPECT_FALSE(failed);
MEM_freeN(read_data);
MEM_freeN(data);
GPU_texture_free(texture);
}
template<eGPUTextureFormat DeviceFormat, eGPUDataFormat HostFormat, int Size = 16>
static void texture_create_upload_read_with_bias(float max_allowed_bias)
{
static_assert(validate_data_format(DeviceFormat, HostFormat));
eGPUTextureUsage usage = GPU_TEXTURE_USAGE_ATTACHMENT | GPU_TEXTURE_USAGE_HOST_READ;
GPUTexture *texture = GPU_texture_create_2d(
"texture", Size, Size, 1, DeviceFormat, usage, nullptr);
if (texture == nullptr) {
GTEST_SKIP() << "Platform doesn't support texture format [" << STRINGIFY(DeviceFormat) << "]";
}
size_t data_len = Size * Size * to_component_len(DeviceFormat);
float *data = static_cast<float *>(generate_test_data<float>(data_len));
GPU_texture_update(texture, HostFormat, data);
float *read_data = static_cast<float *>(GPU_texture_read(texture, HostFormat, 0));
float max_used_bias = 0.0f;
for (int i : IndexRange(data_len)) {
float bias = abs(read_data[i] - data[i]);
max_used_bias = max_ff(max_used_bias, bias);
}
EXPECT_LE(max_used_bias, max_allowed_bias);
MEM_freeN(read_data);
MEM_freeN(data);
GPU_texture_free(texture);
}
/* Derivative of texture_create_upload_read_pixels that doesn't test each component, but a pixel at
* a time. This is needed to check the R11G11B10 and similar types. */
template<eGPUTextureFormat DeviceFormat, eGPUDataFormat HostFormat, int Size = 16>
static void texture_create_upload_read_pixel()
{
using DataType = uint32_t;
static_assert(validate_data_format(DeviceFormat, HostFormat));
eGPUTextureUsage usage = GPU_TEXTURE_USAGE_ATTACHMENT | GPU_TEXTURE_USAGE_HOST_READ;
GPUTexture *texture = GPU_texture_create_2d(
"texture", Size, Size, 1, DeviceFormat, usage, nullptr);
ASSERT_NE(texture, nullptr);
size_t data_len = Size * Size;
DataType *data = static_cast<DataType *>(generate_test_data<DataType>(data_len));
GPU_texture_update(texture, HostFormat, data);
DataType *read_data = static_cast<DataType *>(GPU_texture_read(texture, HostFormat, 0));
bool failed = false;
for (int i : IndexRange(data_len)) {
bool ok = (read_data[i] - data[i]) == 0;
failed |= !ok;
}
EXPECT_FALSE(failed);
MEM_freeN(read_data);
MEM_freeN(data);
GPU_texture_free(texture);
}
/* -------------------------------------------------------------------- */
/** \name Roundtrip testing GPU_DATA_FLOAT
* \{ */
static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_RGBA8()
{
texture_create_upload_read_with_bias<GPU_RGBA8, GPU_DATA_FLOAT>(0.004f);
}
GPU_TEST(texture_roundtrip__GPU_DATA_FLOAT__GPU_RGBA8);
static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_RGBA16F()
{
texture_create_upload_read_with_bias<GPU_RGBA16F, GPU_DATA_FLOAT>(0.9f);
}
GPU_TEST(texture_roundtrip__GPU_DATA_FLOAT__GPU_RGBA16F);
static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_RGBA16()
{
texture_create_upload_read_with_bias<GPU_RGBA16, GPU_DATA_FLOAT>(0.00002f);
}
GPU_TEST(texture_roundtrip__GPU_DATA_FLOAT__GPU_RGBA16);
static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_RGBA32F()
{
texture_create_upload_read_with_bias<GPU_RGBA32F, GPU_DATA_FLOAT>(0.0f);
}
GPU_TEST(texture_roundtrip__GPU_DATA_FLOAT__GPU_RGBA32F);
static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_RG8()
{
texture_create_upload_read_with_bias<GPU_RG8, GPU_DATA_FLOAT>(0.004f);
}
GPU_TEST(texture_roundtrip__GPU_DATA_FLOAT__GPU_RG8);
static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_RG16F()
{
texture_create_upload_read_with_bias<GPU_RG16F, GPU_DATA_FLOAT>(0.9f);
}
GPU_TEST(texture_roundtrip__GPU_DATA_FLOAT__GPU_RG16F);
static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_RG16()
{
texture_create_upload_read_with_bias<GPU_RG16, GPU_DATA_FLOAT>(0.00002f);
}
GPU_TEST(texture_roundtrip__GPU_DATA_FLOAT__GPU_RG16);
static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_RG32F()
{
texture_create_upload_read_with_bias<GPU_RG32F, GPU_DATA_FLOAT>(0.0f);
}
GPU_TEST(texture_roundtrip__GPU_DATA_FLOAT__GPU_RG32F);
static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_R8()
{
texture_create_upload_read_with_bias<GPU_R8, GPU_DATA_FLOAT>(0.004f);
}
GPU_TEST(texture_roundtrip__GPU_DATA_FLOAT__GPU_R8);
static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_R16F()
{
texture_create_upload_read_with_bias<GPU_R16F, GPU_DATA_FLOAT>(0.9f);
}
GPU_TEST(texture_roundtrip__GPU_DATA_FLOAT__GPU_R16F);
static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_R16()
{
texture_create_upload_read_with_bias<GPU_R16, GPU_DATA_FLOAT>(0.00002f);
}
GPU_TEST(texture_roundtrip__GPU_DATA_FLOAT__GPU_R16);
static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_R32F()
{
texture_create_upload_read_with_bias<GPU_R32F, GPU_DATA_FLOAT>(0.0f);
}
GPU_TEST(texture_roundtrip__GPU_DATA_FLOAT__GPU_R32F);
#if RUN_NON_STANDARD_UNIMPLEMENTED
static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_RGB10_A2()
{
texture_create_upload_read_with_bias<GPU_RGB10_A2, GPU_DATA_FLOAT>(0.0f);
}
GPU_TEST(texture_roundtrip__GPU_DATA_FLOAT__GPU_RGB10_A2);
static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_RGB10_A2UI()
{
texture_create_upload_read_with_bias<GPU_RGB10_A2UI, GPU_DATA_FLOAT>(0.0f);
}
GPU_TEST(texture_roundtrip__GPU_DATA_FLOAT__GPU_RGB10_A2UI);
static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_R11F_G11F_B10F()
{
texture_create_upload_read_with_bias<GPU_R11F_G11F_B10F, GPU_DATA_FLOAT>(0.0f);
}
GPU_TEST(texture_roundtrip__GPU_DATA_FLOAT__GPU_R11F_G11F_B10F);
#endif
#if RUN_SRGB_UNIMPLEMENTED
static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_SRGB8_A8()
{
texture_create_upload_read_with_bias<GPU_SRGB8_A8, GPU_DATA_FLOAT>(0.0f);
}
GPU_TEST(texture_roundtrip__GPU_DATA_FLOAT__GPU_SRGB8_A8);
#endif
static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_RGBA8_SNORM()
{
texture_create_upload_read_with_bias<GPU_RGBA8_SNORM, GPU_DATA_FLOAT>(0.004f);
}
GPU_TEST(texture_roundtrip__GPU_DATA_FLOAT__GPU_RGBA8_SNORM);
static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_RGBA16_SNORM()
{
texture_create_upload_read_with_bias<GPU_RGBA16_SNORM, GPU_DATA_FLOAT>(0.00002f);
}
GPU_TEST(texture_roundtrip__GPU_DATA_FLOAT__GPU_RGBA16_SNORM);
#if RUN_UNSUPPORTED
static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_RGB8()
{
texture_create_upload_read_with_bias<GPU_RGB8, GPU_DATA_FLOAT>(0.0f);
}
GPU_TEST(texture_roundtrip__GPU_DATA_FLOAT__GPU_RGB8);
static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_RGB8_SNORM()
{
texture_create_upload_read_with_bias<GPU_RGB8_SNORM, GPU_DATA_FLOAT>(0.0f);
}
GPU_TEST(texture_roundtrip__GPU_DATA_FLOAT__GPU_RGB8_SNORM);
static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_RGB16F()
{
texture_create_upload_read_with_bias<GPU_RGB16F, GPU_DATA_FLOAT>(0.0f);
}
GPU_TEST(texture_roundtrip__GPU_DATA_FLOAT__GPU_RGB16F);
static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_RGB16()
{
texture_create_upload_read_with_bias<GPU_RGB16, GPU_DATA_FLOAT>(0.0f);
}
GPU_TEST(texture_roundtrip__GPU_DATA_FLOAT__GPU_RGB16);
static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_RGB16_SNORM()
{
texture_create_upload_read_with_bias<GPU_RGB16_SNORM, GPU_DATA_FLOAT>(0.0f);
}
GPU_TEST(texture_roundtrip__GPU_DATA_FLOAT__GPU_RGB16_SNORM);
static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_RGB32F()
{
texture_create_upload_read_with_bias<GPU_RGB32F, GPU_DATA_FLOAT>(0.0f);
}
GPU_TEST(texture_roundtrip__GPU_DATA_FLOAT__GPU_RGB32F);
#endif
static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_RG8_SNORM()
{
texture_create_upload_read_with_bias<GPU_RG8_SNORM, GPU_DATA_FLOAT>(0.004f);
}
GPU_TEST(texture_roundtrip__GPU_DATA_FLOAT__GPU_RG8_SNORM);
static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_RG16_SNORM()
{
texture_create_upload_read_with_bias<GPU_RG16_SNORM, GPU_DATA_FLOAT>(0.00002f);
}
GPU_TEST(texture_roundtrip__GPU_DATA_FLOAT__GPU_RG16_SNORM);
static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_R8_SNORM()
{
texture_create_upload_read_with_bias<GPU_R8_SNORM, GPU_DATA_FLOAT>(0.004f);
}
GPU_TEST(texture_roundtrip__GPU_DATA_FLOAT__GPU_R8_SNORM);
static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_R16_SNORM()
{
texture_create_upload_read_with_bias<GPU_R16_SNORM, GPU_DATA_FLOAT>(0.00002f);
}
GPU_TEST(texture_roundtrip__GPU_DATA_FLOAT__GPU_R16_SNORM);
#if RUN_NON_STANDARD_UNIMPLEMENTED
static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_SRGB8_A8_DXT1()
{
texture_create_upload_read_with_bias<GPU_SRGB8_A8_DXT1, GPU_DATA_FLOAT>(0.0f);
}
GPU_TEST(texture_roundtrip__GPU_DATA_FLOAT__GPU_SRGB8_A8_DXT1);
static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_SRGB8_A8_DXT3()
{
texture_create_upload_read_with_bias<GPU_SRGB8_A8_DXT3, GPU_DATA_FLOAT>(0.0f);
}
GPU_TEST(texture_roundtrip__GPU_DATA_FLOAT__GPU_SRGB8_A8_DXT3);
static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_SRGB8_A8_DXT5()
{
texture_create_upload_read_with_bias<GPU_SRGB8_A8_DXT5, GPU_DATA_FLOAT>(0.0f);
}
GPU_TEST(texture_roundtrip__GPU_DATA_FLOAT__GPU_SRGB8_A8_DXT5);
static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_RGBA8_DXT1()
{
texture_create_upload_read_with_bias<GPU_RGBA8_DXT1, GPU_DATA_FLOAT>(0.0f);
}
GPU_TEST(texture_roundtrip__GPU_DATA_FLOAT__GPU_RGBA8_DXT1);
static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_RGBA8_DXT3()
{
texture_create_upload_read_with_bias<GPU_RGBA8_DXT3, GPU_DATA_FLOAT>(0.0f);
}
GPU_TEST(texture_roundtrip__GPU_DATA_FLOAT__GPU_RGBA8_DXT3);
static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_RGBA8_DXT5()
{
texture_create_upload_read_with_bias<GPU_RGBA8_DXT5, GPU_DATA_FLOAT>(0.0f);
}
GPU_TEST(texture_roundtrip__GPU_DATA_FLOAT__GPU_RGBA8_DXT5);
#endif
#if RUN_SRGB_UNIMPLEMENTED
static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_SRGB8()
{
texture_create_upload_read_with_bias<GPU_SRGB8, GPU_DATA_FLOAT>(0.0f);
}
GPU_TEST(texture_roundtrip__GPU_DATA_FLOAT__GPU_SRGB8);
#endif
#if RUN_NON_STANDARD_UNIMPLEMENTED
static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_RGB9_E5()
{
texture_create_upload_read_with_bias<GPU_RGB9_E5, GPU_DATA_FLOAT>(0.0f);
}
GPU_TEST(texture_roundtrip__GPU_DATA_FLOAT__GPU_RGB9_E5);
#endif
#if RUN_UNSUPPORTED
static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_DEPTH_COMPONENT32F()
{
texture_create_upload_read_with_bias<GPU_DEPTH_COMPONENT32F, GPU_DATA_FLOAT>(0.0f);
}
GPU_TEST(texture_roundtrip__GPU_DATA_FLOAT__GPU_DEPTH_COMPONENT32F);
#endif
#if RUN_COMPONENT_UNIMPLEMENTED
static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_DEPTH_COMPONENT24()
{
texture_create_upload_read_with_bias<GPU_DEPTH_COMPONENT24, GPU_DATA_FLOAT>(0.0f);
}
GPU_TEST(texture_roundtrip__GPU_DATA_FLOAT__GPU_DEPTH_COMPONENT24);
static void test_texture_roundtrip__GPU_DATA_FLOAT__GPU_DEPTH_COMPONENT16()
{
texture_create_upload_read_with_bias<GPU_DEPTH_COMPONENT16, GPU_DATA_FLOAT>(0.0f);
}
GPU_TEST(texture_roundtrip__GPU_DATA_FLOAT__GPU_DEPTH_COMPONENT16);
#endif
/* \} */
/* -------------------------------------------------------------------- */
/** \name Roundtrip testing GPU_DATA_HALF_FLOAT
* \{ */
static void test_texture_roundtrip__GPU_DATA_HALF_FLOAT__GPU_RGBA16F()
{
texture_create_upload_read<GPU_RGBA16F, GPU_DATA_HALF_FLOAT, uint16_t>();
}
GPU_TEST(texture_roundtrip__GPU_DATA_HALF_FLOAT__GPU_RGBA16F);
static void test_texture_roundtrip__GPU_DATA_HALF_FLOAT__GPU_RG16F()
{
texture_create_upload_read<GPU_RG16F, GPU_DATA_HALF_FLOAT, uint16_t>();
}
GPU_TEST(texture_roundtrip__GPU_DATA_HALF_FLOAT__GPU_RG16F);
static void test_texture_roundtrip__GPU_DATA_HALF_FLOAT__GPU_R16F()
{
texture_create_upload_read<GPU_R16F, GPU_DATA_HALF_FLOAT, uint16_t>();
}
GPU_TEST(texture_roundtrip__GPU_DATA_HALF_FLOAT__GPU_R16F);
#if RUN_UNSUPPORTED
static void test_texture_roundtrip__GPU_DATA_HALF_FLOAT__GPU_RGB16F()
{
texture_create_upload_read<GPU_RGB16F, GPU_DATA_HALF_FLOAT, uint16_t>();
}
GPU_TEST(texture_roundtrip__GPU_DATA_HALF_FLOAT__GPU_RGB16F);
#endif
/* \} */
/* -------------------------------------------------------------------- */
/** \name Roundtrip testing GPU_DATA_INT
* \{ */
static void test_texture_roundtrip__GPU_DATA_INT__GPU_RGBA8I()
{
texture_create_upload_read<GPU_RGBA8I, GPU_DATA_INT, int32_t>();
}
GPU_TEST(texture_roundtrip__GPU_DATA_INT__GPU_RGBA8I);
static void test_texture_roundtrip__GPU_DATA_INT__GPU_RGBA16I()
{
texture_create_upload_read<GPU_RGBA16I, GPU_DATA_INT, int32_t>();
}
GPU_TEST(texture_roundtrip__GPU_DATA_INT__GPU_RGBA16I);
static void test_texture_roundtrip__GPU_DATA_INT__GPU_RGBA32I()
{
texture_create_upload_read<GPU_RGBA32I, GPU_DATA_INT, int32_t>();
}
GPU_TEST(texture_roundtrip__GPU_DATA_INT__GPU_RGBA32I);
static void test_texture_roundtrip__GPU_DATA_INT__GPU_RG8I()
{
texture_create_upload_read<GPU_RG8I, GPU_DATA_INT, int32_t>();
}
GPU_TEST(texture_roundtrip__GPU_DATA_INT__GPU_RG8I);
static void test_texture_roundtrip__GPU_DATA_INT__GPU_RG16I()
{
texture_create_upload_read<GPU_RG16I, GPU_DATA_INT, int32_t>();
}
GPU_TEST(texture_roundtrip__GPU_DATA_INT__GPU_RG16I);
static void test_texture_roundtrip__GPU_DATA_INT__GPU_RG32I()
{
texture_create_upload_read<GPU_RG32I, GPU_DATA_INT, int32_t>();
}
GPU_TEST(texture_roundtrip__GPU_DATA_INT__GPU_RG32I);
static void test_texture_roundtrip__GPU_DATA_INT__GPU_R8I()
{
texture_create_upload_read<GPU_R8I, GPU_DATA_INT, int32_t>();
}
GPU_TEST(texture_roundtrip__GPU_DATA_INT__GPU_R8I);
static void test_texture_roundtrip__GPU_DATA_INT__GPU_R16I()
{
texture_create_upload_read<GPU_R16I, GPU_DATA_INT, int32_t>();
}
GPU_TEST(texture_roundtrip__GPU_DATA_INT__GPU_R16I);
static void test_texture_roundtrip__GPU_DATA_INT__GPU_R32I()
{
texture_create_upload_read<GPU_R32I, GPU_DATA_INT, int32_t>();
}
GPU_TEST(texture_roundtrip__GPU_DATA_INT__GPU_R32I);
#if RUN_UNSUPPORTED
static void test_texture_roundtrip__GPU_DATA_INT__GPU_RGB8I()
{
texture_create_upload_read<GPU_RGB8I, GPU_DATA_INT, int32_t>();
}
GPU_TEST(texture_roundtrip__GPU_DATA_INT__GPU_RGB8I);
static void test_texture_roundtrip__GPU_DATA_INT__GPU_RGB16I()
{
texture_create_upload_read<GPU_RGB16I, GPU_DATA_INT, int32_t>();
}
GPU_TEST(texture_roundtrip__GPU_DATA_INT__GPU_RGB16I);
static void test_texture_roundtrip__GPU_DATA_INT__GPU_RGB32I()
{
texture_create_upload_read<GPU_RGB32I, GPU_DATA_INT, int32_t>();
}
GPU_TEST(texture_roundtrip__GPU_DATA_INT__GPU_RGB32I);
#endif
/* \} */
/* -------------------------------------------------------------------- */
/** \name Roundtrip testing GPU_DATA_UINT
* \{ */
static void test_texture_roundtrip__GPU_DATA_UINT__GPU_RGBA8UI()
{
texture_create_upload_read<GPU_RGBA8UI, GPU_DATA_UINT, uint32_t>();
}
GPU_TEST(texture_roundtrip__GPU_DATA_UINT__GPU_RGBA8UI);
static void test_texture_roundtrip__GPU_DATA_UINT__GPU_RGBA16UI()
{
texture_create_upload_read<GPU_RGBA16UI, GPU_DATA_UINT, uint32_t>();
}
GPU_TEST(texture_roundtrip__GPU_DATA_UINT__GPU_RGBA16UI);
static void test_texture_roundtrip__GPU_DATA_UINT__GPU_RGBA32UI()
{
texture_create_upload_read<GPU_RGBA32UI, GPU_DATA_UINT, uint32_t>();
}
GPU_TEST(texture_roundtrip__GPU_DATA_UINT__GPU_RGBA32UI);
static void test_texture_roundtrip__GPU_DATA_UINT__GPU_RG8UI()
{
texture_create_upload_read<GPU_RG8UI, GPU_DATA_UINT, uint32_t>();
}
GPU_TEST(texture_roundtrip__GPU_DATA_UINT__GPU_RG8UI);
static void test_texture_roundtrip__GPU_DATA_UINT__GPU_RG16UI()
{
texture_create_upload_read<GPU_RG16UI, GPU_DATA_UINT, uint32_t>();
}
GPU_TEST(texture_roundtrip__GPU_DATA_UINT__GPU_RG16UI);
static void test_texture_roundtrip__GPU_DATA_UINT__GPU_RG32UI()
{
texture_create_upload_read<GPU_RG32UI, GPU_DATA_UINT, uint32_t>();
}
GPU_TEST(texture_roundtrip__GPU_DATA_UINT__GPU_RG32UI);
static void test_texture_roundtrip__GPU_DATA_UINT__GPU_R8UI()
{
texture_create_upload_read<GPU_R8UI, GPU_DATA_UINT, uint32_t>();
}
GPU_TEST(texture_roundtrip__GPU_DATA_UINT__GPU_R8UI);
static void test_texture_roundtrip__GPU_DATA_UINT__GPU_R16UI()
{
texture_create_upload_read<GPU_R16UI, GPU_DATA_UINT, uint32_t>();
}
GPU_TEST(texture_roundtrip__GPU_DATA_UINT__GPU_R16UI);
static void test_texture_roundtrip__GPU_DATA_UINT__GPU_R32UI()
{
texture_create_upload_read<GPU_R32UI, GPU_DATA_UINT, uint32_t>();
}
GPU_TEST(texture_roundtrip__GPU_DATA_UINT__GPU_R32UI);
#if RUN_UNSUPPORTED
static void test_texture_roundtrip__GPU_DATA_UINT__GPU_DEPTH32F_STENCIL8()
{
texture_create_upload_read<GPU_DEPTH32F_STENCIL8, GPU_DATA_UINT, uint32_t>();
}
GPU_TEST(texture_roundtrip__GPU_DATA_UINT__GPU_DEPTH32F_STENCIL8);
static void test_texture_roundtrip__GPU_DATA_UINT__GPU_DEPTH24_STENCIL8()
{
texture_create_upload_read<GPU_DEPTH24_STENCIL8, GPU_DATA_UINT, uint32_t>();
}
GPU_TEST(texture_roundtrip__GPU_DATA_UINT__GPU_DEPTH24_STENCIL8);
#endif
#if RUN_UNSUPPORTED
static void test_texture_roundtrip__GPU_DATA_UINT__GPU_RGB8UI()
{
texture_create_upload_read<GPU_RGB8UI, GPU_DATA_UINT, uint32_t>();
}
GPU_TEST(texture_roundtrip__GPU_DATA_UINT__GPU_RGB8UI);
static void test_texture_roundtrip__GPU_DATA_UINT__GPU_RGB16UI()
{
texture_create_upload_read<GPU_RGB16UI, GPU_DATA_UINT, uint32_t>();
}
GPU_TEST(texture_roundtrip__GPU_DATA_UINT__GPU_RGB16UI);
static void test_texture_roundtrip__GPU_DATA_UINT__GPU_RGB32UI()
{
texture_create_upload_read<GPU_RGB32UI, GPU_DATA_UINT, uint32_t>();
}
GPU_TEST(texture_roundtrip__GPU_DATA_UINT__GPU_RGB32UI);
#endif
#if RUN_COMPONENT_UNIMPLEMENTED
static void test_texture_roundtrip__GPU_DATA_UINT__GPU_DEPTH_COMPONENT32F()
{
texture_create_upload_read<GPU_DEPTH_COMPONENT32F, GPU_DATA_UINT, uint32_t>();
}
GPU_TEST(texture_roundtrip__GPU_DATA_UINT__GPU_DEPTH_COMPONENT32F);
static void test_texture_roundtrip__GPU_DATA_UINT__GPU_DEPTH_COMPONENT24()
{
texture_create_upload_read<GPU_DEPTH_COMPONENT24, GPU_DATA_UINT, uint32_t>();
}
GPU_TEST(texture_roundtrip__GPU_DATA_UINT__GPU_DEPTH_COMPONENT24);
static void test_texture_roundtrip__GPU_DATA_UINT__GPU_DEPTH_COMPONENT16()
{
texture_create_upload_read<GPU_DEPTH_COMPONENT16, GPU_DATA_UINT, uint32_t>();
}
GPU_TEST(texture_roundtrip__GPU_DATA_UINT__GPU_DEPTH_COMPONENT16);
#endif
/* \} */
/* -------------------------------------------------------------------- */
/** \name Roundtrip testing GPU_DATA_UBYTE
* \{ */
static void test_texture_roundtrip__GPU_DATA_UBYTE__GPU_RGBA8UI()
{
texture_create_upload_read<GPU_RGBA8UI, GPU_DATA_UBYTE, uint8_t>();
}
GPU_TEST(texture_roundtrip__GPU_DATA_UBYTE__GPU_RGBA8UI);
static void test_texture_roundtrip__GPU_DATA_UBYTE__GPU_RGBA8()
{
texture_create_upload_read<GPU_RGBA8, GPU_DATA_UBYTE, uint8_t>();
}
GPU_TEST(texture_roundtrip__GPU_DATA_UBYTE__GPU_RGBA8);
static void test_texture_roundtrip__GPU_DATA_UBYTE__GPU_RG8UI()
{
texture_create_upload_read<GPU_RG8UI, GPU_DATA_UBYTE, uint8_t>();
}
GPU_TEST(texture_roundtrip__GPU_DATA_UBYTE__GPU_RG8UI);
static void test_texture_roundtrip__GPU_DATA_UBYTE__GPU_RG8()
{
texture_create_upload_read<GPU_RG8, GPU_DATA_UBYTE, uint8_t>();
}
GPU_TEST(texture_roundtrip__GPU_DATA_UBYTE__GPU_RG8);
static void test_texture_roundtrip__GPU_DATA_UBYTE__GPU_R8UI()
{
texture_create_upload_read<GPU_R8UI, GPU_DATA_UBYTE, uint8_t>();
}
GPU_TEST(texture_roundtrip__GPU_DATA_UBYTE__GPU_R8UI);
static void test_texture_roundtrip__GPU_DATA_UBYTE__GPU_R8()
{
texture_create_upload_read<GPU_R8, GPU_DATA_UBYTE, uint8_t>();
}
GPU_TEST(texture_roundtrip__GPU_DATA_UBYTE__GPU_R8);
#if RUN_SRGB_UNIMPLEMENTED
static void test_texture_roundtrip__GPU_DATA_UBYTE__GPU_SRGB8_A8()
{
texture_create_upload_read<GPU_SRGB8_A8, GPU_DATA_UBYTE, uint8_t>();
}
GPU_TEST(texture_roundtrip__GPU_DATA_UBYTE__GPU_SRGB8_A8);
#endif
#if RUN_UNSUPPORTED
static void test_texture_roundtrip__GPU_DATA_UBYTE__GPU_RGB8I()
{
texture_create_upload_read<GPU_RGB8I, GPU_DATA_UBYTE, uint8_t>();
}
GPU_TEST(texture_roundtrip__GPU_DATA_UBYTE__GPU_RGB8I);
static void test_texture_roundtrip__GPU_DATA_UBYTE__GPU_RGB8()
{
texture_create_upload_read<GPU_RGB8, GPU_DATA_UBYTE, uint8_t>();
}
GPU_TEST(texture_roundtrip__GPU_DATA_UBYTE__GPU_RGB8);
static void test_texture_roundtrip__GPU_DATA_UBYTE__GPU_SRGB8()
{
texture_create_upload_read<GPU_SRGB8, GPU_DATA_UBYTE, uint8_t>();
}
GPU_TEST(texture_roundtrip__GPU_DATA_UBYTE__GPU_SRGB8);
#endif
/* \} */
/* -------------------------------------------------------------------- */
/** \name Roundtrip testing GPU_DATA_UINT_24_8
* \{ */
#if RUN_UNSUPPORTED
static void test_texture_roundtrip__GPU_DATA_UINT_24_8__GPU_DEPTH32F_STENCIL8()
{
texture_create_upload_read<GPU_DEPTH32F_STENCIL8, GPU_DATA_UINT_24_8, void>();
}
GPU_TEST(texture_roundtrip__GPU_DATA_UINT_24_8__GPU_DEPTH32F_STENCIL8);
static void test_texture_roundtrip__GPU_DATA_UINT_24_8__GPU_DEPTH24_STENCIL8()
{
texture_create_upload_read<GPU_DEPTH24_STENCIL8, GPU_DATA_UINT_24_8, void>();
}
GPU_TEST(texture_roundtrip__GPU_DATA_UINT_24_8__GPU_DEPTH24_STENCIL8);
#endif
/* \} */
/* -------------------------------------------------------------------- */
/** \name Roundtrip testing GPU_DATA_10_11_11_REV
* \{ */
static void test_texture_roundtrip__GPU_DATA_10_11_11_REV__GPU_R11F_G11F_B10F()
{
texture_create_upload_read<GPU_R11F_G11F_B10F, GPU_DATA_10_11_11_REV, uint8_t>();
}
GPU_TEST(texture_roundtrip__GPU_DATA_10_11_11_REV__GPU_R11F_G11F_B10F);
/* \} */
/* -------------------------------------------------------------------- */
/** \name Roundtrip testing GPU_DATA_2_10_10_10_REV
* \{ */
static void test_texture_roundtrip__GPU_DATA_2_10_10_10_REV__GPU_RGB10_A2()
{
texture_create_upload_read_pixel<GPU_RGB10_A2, GPU_DATA_2_10_10_10_REV>();
}
GPU_TEST(texture_roundtrip__GPU_DATA_2_10_10_10_REV__GPU_RGB10_A2);
static void test_texture_roundtrip__GPU_DATA_2_10_10_10_REV__GPU_RGB10_A2UI()
{
texture_create_upload_read_pixel<GPU_RGB10_A2UI, GPU_DATA_2_10_10_10_REV>();
}
GPU_TEST(texture_roundtrip__GPU_DATA_2_10_10_10_REV__GPU_RGB10_A2UI);
/* \} */
} // namespace blender::gpu::tests

View File

@ -66,13 +66,14 @@ void VKBackend::compute_dispatch(int groups_x_len, int groups_y_len, int groups_
VKShader *shader = static_cast<VKShader *>(context.shader);
VKCommandBuffer &command_buffer = context.command_buffer_get();
VKPipeline &pipeline = shader->pipeline_get();
VKDescriptorSet &descriptor_set = pipeline.descriptor_set_get();
VKDescriptorSetTracker &descriptor_set = pipeline.descriptor_set_get();
VKPushConstants &push_constants = pipeline.push_constants_get();
push_constants.update(context);
descriptor_set.update(context.device_get());
command_buffer.bind(
descriptor_set, shader->vk_pipeline_layout_get(), VK_PIPELINE_BIND_POINT_COMPUTE);
descriptor_set.update(context);
command_buffer.bind(*descriptor_set.active_descriptor_set(),
shader->vk_pipeline_layout_get(),
VK_PIPELINE_BIND_POINT_COMPUTE);
command_buffer.dispatch(groups_x_len, groups_y_len, groups_z_len);
}

View File

@ -6,6 +6,7 @@
*/
#include "vk_buffer.hh"
#include "vk_context.hh"
namespace blender::gpu {

View File

@ -10,9 +10,9 @@
#include "gpu_context_private.hh"
#include "vk_common.hh"
#include "vk_context.hh"
namespace blender::gpu {
class VKContext;
/**
* Class for handing vulkan buffers (allocation/updating/binding).

View File

@ -32,6 +32,7 @@ void VKCommandBuffer::init(const VkDevice vk_device,
vk_device_ = vk_device;
vk_queue_ = vk_queue;
vk_command_buffer_ = vk_command_buffer;
submission_id_.reset();
if (vk_fence_ == VK_NULL_HANDLE) {
VK_ALLOCATION_CALLBACKS;
@ -102,6 +103,30 @@ void VKCommandBuffer::copy(VKBuffer &dst_buffer,
regions.size(),
regions.data());
}
void VKCommandBuffer::copy(VKTexture &dst_texture,
VKBuffer &src_buffer,
Span<VkBufferImageCopy> regions)
{
vkCmdCopyBufferToImage(vk_command_buffer_,
src_buffer.vk_handle(),
dst_texture.vk_image_handle(),
VK_IMAGE_LAYOUT_GENERAL,
regions.size(),
regions.data());
}
void VKCommandBuffer::clear(VkImage vk_image,
VkImageLayout vk_image_layout,
const VkClearColorValue &vk_clear_color,
Span<VkImageSubresourceRange> ranges)
{
vkCmdClearColorImage(vk_command_buffer_,
vk_image,
vk_image_layout,
&vk_clear_color,
ranges.size(),
ranges.data());
}
void VKCommandBuffer::pipeline_barrier(VkPipelineStageFlags source_stages,
VkPipelineStageFlags destination_stages)
@ -160,6 +185,7 @@ void VKCommandBuffer::submit_encoded_commands()
submit_info.pCommandBuffers = &vk_command_buffer_;
vkQueueSubmit(vk_queue_, 1, &submit_info, vk_fence_);
submission_id_.next();
}
} // namespace blender::gpu

View File

@ -8,6 +8,7 @@
#pragma once
#include "vk_common.hh"
#include "vk_resource_tracker.hh"
#include "BLI_utility_mixins.hh"
@ -27,6 +28,7 @@ class VKCommandBuffer : NonCopyable, NonMovable {
/** Owning handles */
VkFence vk_fence_ = VK_NULL_HANDLE;
VKSubmissionID submission_id_;
public:
virtual ~VKCommandBuffer();
@ -48,9 +50,17 @@ class VKCommandBuffer : NonCopyable, NonMovable {
void dispatch(int groups_x_len, int groups_y_len, int groups_z_len);
/** Copy the contents of a texture MIP level to the dst buffer. */
void copy(VKBuffer &dst_buffer, VKTexture &src_texture, Span<VkBufferImageCopy> regions);
void copy(VKTexture &dst_texture, VKBuffer &src_buffer, Span<VkBufferImageCopy> regions);
void pipeline_barrier(VkPipelineStageFlags source_stages,
VkPipelineStageFlags destination_stages);
void pipeline_barrier(Span<VkImageMemoryBarrier> image_memory_barriers);
/**
* Clear color image resource.
*/
void clear(VkImage vk_image,
VkImageLayout vk_image_layout,
const VkClearColorValue &vk_clear_color,
Span<VkImageSubresourceRange> ranges);
void fill(VKBuffer &buffer, uint32_t data);
/**
@ -59,6 +69,11 @@ class VKCommandBuffer : NonCopyable, NonMovable {
*/
void submit();
const VKSubmissionID &submission_id_get() const
{
return submission_id_;
}
private:
void encode_recorded_commands();
void submit_encoded_commands();

View File

@ -0,0 +1,780 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2023 Blender Foundation. All rights reserved. */
/** \file
* \ingroup gpu
*/
#include "vk_data_conversion.hh"
#include "Imath/half.h"
namespace blender::gpu {
/* -------------------------------------------------------------------- */
/** \name Conversion types
* \{ */
enum class ConversionType {
/** No conversion needed, result can be directly read back to host memory. */
PASS_THROUGH,
FLOAT_TO_UNORM8,
UNORM8_TO_FLOAT,
FLOAT_TO_SNORM8,
SNORM8_TO_FLOAT,
FLOAT_TO_UNORM16,
UNORM16_TO_FLOAT,
FLOAT_TO_SNORM16,
SNORM16_TO_FLOAT,
UI32_TO_UI16,
UI16_TO_UI32,
UI32_TO_UI8,
UI8_TO_UI32,
I32_TO_I16,
I16_TO_I32,
I32_TO_I8,
I8_TO_I32,
/** Convert device 16F to floats. */
HALF_TO_FLOAT,
FLOAT_TO_HALF,
/**
* The requested conversion isn't supported.
*/
UNSUPPORTED,
};
static ConversionType type_of_conversion_float(eGPUTextureFormat device_format)
{
switch (device_format) {
case GPU_RGBA32F:
case GPU_RG32F:
case GPU_R32F:
case GPU_DEPTH_COMPONENT32F:
return ConversionType::PASS_THROUGH;
case GPU_RGBA16F:
case GPU_RG16F:
case GPU_R16F:
case GPU_RGB16F:
return ConversionType::FLOAT_TO_HALF;
case GPU_RGBA8:
case GPU_RG8:
case GPU_R8:
return ConversionType::FLOAT_TO_UNORM8;
case GPU_RGBA8_SNORM:
case GPU_RGB8_SNORM:
case GPU_RG8_SNORM:
case GPU_R8_SNORM:
return ConversionType::FLOAT_TO_SNORM8;
case GPU_RGBA16:
case GPU_RG16:
case GPU_R16:
return ConversionType::FLOAT_TO_UNORM16;
case GPU_RGBA16_SNORM:
case GPU_RGB16_SNORM:
case GPU_RG16_SNORM:
case GPU_R16_SNORM:
return ConversionType::FLOAT_TO_SNORM16;
case GPU_RGB32F: /* GPU_RGB32F Not supported by vendors. */
case GPU_RGBA8UI:
case GPU_RGBA8I:
case GPU_RGBA16UI:
case GPU_RGBA16I:
case GPU_RGBA32UI:
case GPU_RGBA32I:
case GPU_RG8UI:
case GPU_RG8I:
case GPU_RG16UI:
case GPU_RG16I:
case GPU_RG32UI:
case GPU_RG32I:
case GPU_R8UI:
case GPU_R8I:
case GPU_R16UI:
case GPU_R16I:
case GPU_R32UI:
case GPU_R32I:
case GPU_RGB10_A2:
case GPU_RGB10_A2UI:
case GPU_R11F_G11F_B10F:
case GPU_DEPTH32F_STENCIL8:
case GPU_DEPTH24_STENCIL8:
case GPU_SRGB8_A8:
case GPU_RGB8UI:
case GPU_RGB8I:
case GPU_RGB8:
case GPU_RGB16UI:
case GPU_RGB16I:
case GPU_RGB16:
case GPU_RGB32UI:
case GPU_RGB32I:
case GPU_SRGB8_A8_DXT1:
case GPU_SRGB8_A8_DXT3:
case GPU_SRGB8_A8_DXT5:
case GPU_RGBA8_DXT1:
case GPU_RGBA8_DXT3:
case GPU_RGBA8_DXT5:
case GPU_SRGB8:
case GPU_RGB9_E5:
case GPU_DEPTH_COMPONENT24:
case GPU_DEPTH_COMPONENT16:
return ConversionType::UNSUPPORTED;
}
return ConversionType::UNSUPPORTED;
}
static ConversionType type_of_conversion_int(eGPUTextureFormat device_format)
{
switch (device_format) {
case GPU_RGBA32I:
case GPU_RG32I:
case GPU_R32I:
return ConversionType::PASS_THROUGH;
case GPU_RGBA16I:
case GPU_RG16I:
case GPU_R16I:
return ConversionType::I32_TO_I16;
case GPU_RGBA8I:
case GPU_RG8I:
case GPU_R8I:
return ConversionType::I32_TO_I8;
case GPU_RGBA8UI:
case GPU_RGBA8:
case GPU_RGBA16UI:
case GPU_RGBA16F:
case GPU_RGBA16:
case GPU_RGBA32UI:
case GPU_RGBA32F:
case GPU_RG8UI:
case GPU_RG8:
case GPU_RG16UI:
case GPU_RG16F:
case GPU_RG32UI:
case GPU_RG32F:
case GPU_RG16:
case GPU_R8UI:
case GPU_R8:
case GPU_R16UI:
case GPU_R16F:
case GPU_R16:
case GPU_R32UI:
case GPU_R32F:
case GPU_RGB10_A2:
case GPU_RGB10_A2UI:
case GPU_R11F_G11F_B10F:
case GPU_DEPTH32F_STENCIL8:
case GPU_DEPTH24_STENCIL8:
case GPU_SRGB8_A8:
case GPU_RGBA8_SNORM:
case GPU_RGBA16_SNORM:
case GPU_RGB8UI:
case GPU_RGB8I:
case GPU_RGB8:
case GPU_RGB8_SNORM:
case GPU_RGB16UI:
case GPU_RGB16I:
case GPU_RGB16F:
case GPU_RGB16:
case GPU_RGB16_SNORM:
case GPU_RGB32UI:
case GPU_RGB32I:
case GPU_RGB32F:
case GPU_RG8_SNORM:
case GPU_RG16_SNORM:
case GPU_R8_SNORM:
case GPU_R16_SNORM:
case GPU_SRGB8_A8_DXT1:
case GPU_SRGB8_A8_DXT3:
case GPU_SRGB8_A8_DXT5:
case GPU_RGBA8_DXT1:
case GPU_RGBA8_DXT3:
case GPU_RGBA8_DXT5:
case GPU_SRGB8:
case GPU_RGB9_E5:
case GPU_DEPTH_COMPONENT32F:
case GPU_DEPTH_COMPONENT24:
case GPU_DEPTH_COMPONENT16:
return ConversionType::UNSUPPORTED;
}
return ConversionType::UNSUPPORTED;
}
static ConversionType type_of_conversion_uint(eGPUTextureFormat device_format)
{
switch (device_format) {
case GPU_RGBA32UI:
case GPU_RG32UI:
case GPU_R32UI:
return ConversionType::PASS_THROUGH;
case GPU_RGBA16UI:
case GPU_RG16UI:
case GPU_R16UI:
case GPU_RGB16UI:
return ConversionType::UI32_TO_UI16;
case GPU_RGBA8UI:
case GPU_RG8UI:
case GPU_R8UI:
return ConversionType::UI32_TO_UI8;
case GPU_RGBA8I:
case GPU_RGBA8:
case GPU_RGBA16I:
case GPU_RGBA16F:
case GPU_RGBA16:
case GPU_RGBA32I:
case GPU_RGBA32F:
case GPU_RG8I:
case GPU_RG8:
case GPU_RG16I:
case GPU_RG16F:
case GPU_RG16:
case GPU_RG32I:
case GPU_RG32F:
case GPU_R8I:
case GPU_R8:
case GPU_R16I:
case GPU_R16F:
case GPU_R16:
case GPU_R32I:
case GPU_R32F:
case GPU_RGB10_A2:
case GPU_RGB10_A2UI:
case GPU_R11F_G11F_B10F:
case GPU_DEPTH32F_STENCIL8:
case GPU_DEPTH24_STENCIL8:
case GPU_SRGB8_A8:
case GPU_RGBA8_SNORM:
case GPU_RGBA16_SNORM:
case GPU_RGB8UI:
case GPU_RGB8I:
case GPU_RGB8:
case GPU_RGB8_SNORM:
case GPU_RGB16I:
case GPU_RGB16F:
case GPU_RGB16:
case GPU_RGB16_SNORM:
case GPU_RGB32UI:
case GPU_RGB32I:
case GPU_RGB32F:
case GPU_RG8_SNORM:
case GPU_RG16_SNORM:
case GPU_R8_SNORM:
case GPU_R16_SNORM:
case GPU_SRGB8_A8_DXT1:
case GPU_SRGB8_A8_DXT3:
case GPU_SRGB8_A8_DXT5:
case GPU_RGBA8_DXT1:
case GPU_RGBA8_DXT3:
case GPU_RGBA8_DXT5:
case GPU_SRGB8:
case GPU_RGB9_E5:
case GPU_DEPTH_COMPONENT32F:
case GPU_DEPTH_COMPONENT24:
case GPU_DEPTH_COMPONENT16:
return ConversionType::UNSUPPORTED;
}
return ConversionType::UNSUPPORTED;
}
static ConversionType type_of_conversion_half(eGPUTextureFormat device_format)
{
switch (device_format) {
case GPU_RGBA16F:
case GPU_RG16F:
case GPU_R16F:
return ConversionType::PASS_THROUGH;
case GPU_RGBA8UI:
case GPU_RGBA8I:
case GPU_RGBA8:
case GPU_RGBA16UI:
case GPU_RGBA16I:
case GPU_RGBA16:
case GPU_RGBA32UI:
case GPU_RGBA32I:
case GPU_RGBA32F:
case GPU_RG8UI:
case GPU_RG8I:
case GPU_RG8:
case GPU_RG16UI:
case GPU_RG16I:
case GPU_RG16:
case GPU_RG32UI:
case GPU_RG32I:
case GPU_RG32F:
case GPU_R8UI:
case GPU_R8I:
case GPU_R8:
case GPU_R16UI:
case GPU_R16I:
case GPU_R16:
case GPU_R32UI:
case GPU_R32I:
case GPU_R32F:
case GPU_RGB10_A2:
case GPU_RGB10_A2UI:
case GPU_R11F_G11F_B10F:
case GPU_DEPTH32F_STENCIL8:
case GPU_DEPTH24_STENCIL8:
case GPU_SRGB8_A8:
case GPU_RGBA8_SNORM:
case GPU_RGBA16_SNORM:
case GPU_RGB8UI:
case GPU_RGB8I:
case GPU_RGB8:
case GPU_RGB8_SNORM:
case GPU_RGB16UI:
case GPU_RGB16I:
case GPU_RGB16F:
case GPU_RGB16:
case GPU_RGB16_SNORM:
case GPU_RGB32UI:
case GPU_RGB32I:
case GPU_RGB32F:
case GPU_RG8_SNORM:
case GPU_RG16_SNORM:
case GPU_R8_SNORM:
case GPU_R16_SNORM:
case GPU_SRGB8_A8_DXT1:
case GPU_SRGB8_A8_DXT3:
case GPU_SRGB8_A8_DXT5:
case GPU_RGBA8_DXT1:
case GPU_RGBA8_DXT3:
case GPU_RGBA8_DXT5:
case GPU_SRGB8:
case GPU_RGB9_E5:
case GPU_DEPTH_COMPONENT32F:
case GPU_DEPTH_COMPONENT24:
case GPU_DEPTH_COMPONENT16:
return ConversionType::UNSUPPORTED;
}
return ConversionType::UNSUPPORTED;
}
static ConversionType type_of_conversion_ubyte(eGPUTextureFormat device_format)
{
switch (device_format) {
case GPU_RGBA8UI:
case GPU_RGBA8:
case GPU_RG8UI:
case GPU_RG8:
case GPU_R8UI:
case GPU_R8:
return ConversionType::PASS_THROUGH;
case GPU_RGBA8I:
case GPU_RGBA16UI:
case GPU_RGBA16I:
case GPU_RGBA16F:
case GPU_RGBA16:
case GPU_RGBA32UI:
case GPU_RGBA32I:
case GPU_RGBA32F:
case GPU_RG8I:
case GPU_RG16UI:
case GPU_RG16I:
case GPU_RG16F:
case GPU_RG16:
case GPU_RG32UI:
case GPU_RG32I:
case GPU_RG32F:
case GPU_R8I:
case GPU_R16UI:
case GPU_R16I:
case GPU_R16F:
case GPU_R16:
case GPU_R32UI:
case GPU_R32I:
case GPU_R32F:
case GPU_RGB10_A2:
case GPU_RGB10_A2UI:
case GPU_R11F_G11F_B10F:
case GPU_DEPTH32F_STENCIL8:
case GPU_DEPTH24_STENCIL8:
case GPU_SRGB8_A8:
case GPU_RGBA8_SNORM:
case GPU_RGBA16_SNORM:
case GPU_RGB8UI:
case GPU_RGB8I:
case GPU_RGB8:
case GPU_RGB8_SNORM:
case GPU_RGB16UI:
case GPU_RGB16I:
case GPU_RGB16F:
case GPU_RGB16:
case GPU_RGB16_SNORM:
case GPU_RGB32UI:
case GPU_RGB32I:
case GPU_RGB32F:
case GPU_RG8_SNORM:
case GPU_RG16_SNORM:
case GPU_R8_SNORM:
case GPU_R16_SNORM:
case GPU_SRGB8_A8_DXT1:
case GPU_SRGB8_A8_DXT3:
case GPU_SRGB8_A8_DXT5:
case GPU_RGBA8_DXT1:
case GPU_RGBA8_DXT3:
case GPU_RGBA8_DXT5:
case GPU_SRGB8:
case GPU_RGB9_E5:
case GPU_DEPTH_COMPONENT32F:
case GPU_DEPTH_COMPONENT24:
case GPU_DEPTH_COMPONENT16:
return ConversionType::UNSUPPORTED;
}
return ConversionType::UNSUPPORTED;
}
static ConversionType type_of_conversion_r11g11b10(eGPUTextureFormat device_format)
{
if (device_format == GPU_R11F_G11F_B10F) {
return ConversionType::PASS_THROUGH;
}
return ConversionType::UNSUPPORTED;
}
static ConversionType type_of_conversion_r10g10b10a2(eGPUTextureFormat device_format)
{
if (ELEM(device_format, GPU_RGB10_A2, GPU_RGB10_A2UI)) {
return ConversionType::PASS_THROUGH;
}
return ConversionType::UNSUPPORTED;
}
static ConversionType host_to_device(eGPUDataFormat host_format, eGPUTextureFormat device_format)
{
BLI_assert(validate_data_format(device_format, host_format));
switch (host_format) {
case GPU_DATA_FLOAT:
return type_of_conversion_float(device_format);
case GPU_DATA_UINT:
return type_of_conversion_uint(device_format);
case GPU_DATA_INT:
return type_of_conversion_int(device_format);
case GPU_DATA_HALF_FLOAT:
return type_of_conversion_half(device_format);
case GPU_DATA_UBYTE:
return type_of_conversion_ubyte(device_format);
case GPU_DATA_10_11_11_REV:
return type_of_conversion_r11g11b10(device_format);
case GPU_DATA_2_10_10_10_REV:
return type_of_conversion_r10g10b10a2(device_format);
case GPU_DATA_UINT_24_8:
return ConversionType::UNSUPPORTED;
}
return ConversionType::UNSUPPORTED;
}
static ConversionType reversed(ConversionType type)
{
#define CASE_SINGLE(a, b) \
case ConversionType::a##_TO_##b: \
return ConversionType::b##_TO_##a;
#define CASE_PAIR(a, b) \
CASE_SINGLE(a, b) \
CASE_SINGLE(b, a)
switch (type) {
case ConversionType::PASS_THROUGH:
return ConversionType::PASS_THROUGH;
CASE_PAIR(FLOAT, UNORM8)
CASE_PAIR(FLOAT, SNORM8)
CASE_PAIR(FLOAT, UNORM16)
CASE_PAIR(FLOAT, SNORM16)
CASE_PAIR(UI32, UI16)
CASE_PAIR(I32, I16)
CASE_PAIR(UI32, UI8)
CASE_PAIR(I32, I8)
CASE_PAIR(FLOAT, HALF)
case ConversionType::UNSUPPORTED:
return ConversionType::UNSUPPORTED;
}
#undef CASE_PAIR
#undef CASE_SINGLE
return ConversionType::UNSUPPORTED;
}
/* \} */
/* -------------------------------------------------------------------- */
/** \name Data Conversion
* \{ */
template<typename InnerType> struct SignedNormalized {
static_assert(std::is_same<InnerType, uint8_t>() || std::is_same<InnerType, uint16_t>());
InnerType value;
static constexpr int32_t scalar()
{
return (1 << (sizeof(InnerType) * 8 - 1));
}
static constexpr int32_t delta()
{
return (1 << (sizeof(InnerType) * 8 - 1)) - 1;
}
static constexpr int32_t max()
{
return ((1 << (sizeof(InnerType) * 8)) - 1);
}
};
template<typename InnerType> struct UnsignedNormalized {
static_assert(std::is_same<InnerType, uint8_t>() || std::is_same<InnerType, uint16_t>());
InnerType value;
static constexpr int32_t scalar()
{
return (1 << (sizeof(InnerType) * 8)) - 1;
}
static constexpr int32_t max()
{
return ((1 << (sizeof(InnerType) * 8)) - 1);
}
};
template<typename InnerType> struct ComponentValue {
InnerType value;
};
using UI8 = ComponentValue<uint8_t>;
using UI16 = ComponentValue<uint16_t>;
using UI32 = ComponentValue<uint32_t>;
using I8 = ComponentValue<int8_t>;
using I16 = ComponentValue<int16_t>;
using I32 = ComponentValue<int32_t>;
using F32 = ComponentValue<float>;
using F16 = ComponentValue<uint16_t>;
template<typename StorageType>
void convert_component(SignedNormalized<StorageType> &dst, const F32 &src)
{
static constexpr int32_t scalar = SignedNormalized<StorageType>::scalar();
static constexpr int32_t delta = SignedNormalized<StorageType>::delta();
static constexpr int32_t max = SignedNormalized<StorageType>::max();
dst.value = (clamp_i((src.value * scalar + delta), 0, max));
}
template<typename StorageType>
void convert_component(F32 &dst, const SignedNormalized<StorageType> &src)
{
static constexpr int32_t scalar = SignedNormalized<StorageType>::scalar();
static constexpr int32_t delta = SignedNormalized<StorageType>::delta();
dst.value = float(int32_t(src.value) - delta) / scalar;
}
template<typename StorageType>
void convert_component(UnsignedNormalized<StorageType> &dst, const F32 &src)
{
static constexpr int32_t scalar = UnsignedNormalized<StorageType>::scalar();
static constexpr int32_t max = scalar;
dst.value = (clamp_i((src.value * scalar), 0, max));
}
template<typename StorageType>
void convert_component(F32 &dst, const UnsignedNormalized<StorageType> &src)
{
static constexpr int32_t scalar = UnsignedNormalized<StorageType>::scalar();
dst.value = float(src.value) / scalar;
}
/* Copy the contents of src to dst with out performing any actual conversion.*/
template<typename DestinationType, typename SourceType>
void convert_component(DestinationType &dst, const SourceType &src)
{
static_assert(std::is_same<DestinationType, UI8>() || std::is_same<DestinationType, UI16>() ||
std::is_same<DestinationType, UI32>() || std::is_same<DestinationType, I8>() ||
std::is_same<DestinationType, I16>() || std::is_same<DestinationType, I32>());
static_assert(std::is_same<SourceType, UI8>() || std::is_same<SourceType, UI16>() ||
std::is_same<SourceType, UI32>() || std::is_same<SourceType, I8>() ||
std::is_same<SourceType, I16>() || std::is_same<SourceType, I32>());
static_assert(!std::is_same<DestinationType, SourceType>());
dst.value = src.value;
}
static void convert_component(F16 &dst, const F32 &src)
{
dst.value = imath_float_to_half(src.value);
}
static void convert_component(F32 &dst, const F16 &src)
{
dst.value = imath_half_to_float(src.value);
}
/* \} */
template<typename DestinationType, typename SourceType>
void convert_per_component(MutableSpan<DestinationType> dst, Span<SourceType> src)
{
BLI_assert(src.size() == dst.size());
for (int64_t index : IndexRange(src.size())) {
convert_component(dst[index], src[index]);
}
}
template<typename DestinationType, typename SourceType>
void convert_per_component(void *dst_memory,
const void *src_memory,
size_t buffer_size,
eGPUTextureFormat device_format)
{
size_t total_components = to_component_len(device_format) * buffer_size;
Span<SourceType> src = Span<SourceType>(static_cast<const SourceType *>(src_memory),
total_components);
MutableSpan<DestinationType> dst = MutableSpan<DestinationType>(
static_cast<DestinationType *>(dst_memory), total_components);
convert_per_component<DestinationType, SourceType>(dst, src);
}
static void convert_buffer(void *dst_memory,
const void *src_memory,
size_t buffer_size,
eGPUTextureFormat device_format,
ConversionType type)
{
switch (type) {
case ConversionType::UNSUPPORTED:
return;
case ConversionType::PASS_THROUGH:
memcpy(dst_memory, src_memory, buffer_size * to_bytesize(device_format));
return;
case ConversionType::UI32_TO_UI16:
convert_per_component<UI16, UI32>(dst_memory, src_memory, buffer_size, device_format);
break;
case ConversionType::UI16_TO_UI32:
convert_per_component<UI32, UI16>(dst_memory, src_memory, buffer_size, device_format);
break;
case ConversionType::UI32_TO_UI8:
convert_per_component<UI8, UI32>(dst_memory, src_memory, buffer_size, device_format);
break;
case ConversionType::UI8_TO_UI32:
convert_per_component<UI32, UI8>(dst_memory, src_memory, buffer_size, device_format);
break;
case ConversionType::I32_TO_I16:
convert_per_component<I16, I32>(dst_memory, src_memory, buffer_size, device_format);
break;
case ConversionType::I16_TO_I32:
convert_per_component<I32, I16>(dst_memory, src_memory, buffer_size, device_format);
break;
case ConversionType::I32_TO_I8:
convert_per_component<I8, I32>(dst_memory, src_memory, buffer_size, device_format);
break;
case ConversionType::I8_TO_I32:
convert_per_component<I32, I8>(dst_memory, src_memory, buffer_size, device_format);
break;
case ConversionType::FLOAT_TO_SNORM8:
convert_per_component<SignedNormalized<uint8_t>, F32>(
dst_memory, src_memory, buffer_size, device_format);
break;
case ConversionType::SNORM8_TO_FLOAT:
convert_per_component<F32, SignedNormalized<uint8_t>>(
dst_memory, src_memory, buffer_size, device_format);
break;
case ConversionType::FLOAT_TO_SNORM16:
convert_per_component<SignedNormalized<uint16_t>, F32>(
dst_memory, src_memory, buffer_size, device_format);
break;
case ConversionType::SNORM16_TO_FLOAT:
convert_per_component<F32, SignedNormalized<uint16_t>>(
dst_memory, src_memory, buffer_size, device_format);
break;
case ConversionType::FLOAT_TO_UNORM8:
convert_per_component<UnsignedNormalized<uint8_t>, F32>(
dst_memory, src_memory, buffer_size, device_format);
break;
case ConversionType::UNORM8_TO_FLOAT:
convert_per_component<F32, UnsignedNormalized<uint8_t>>(
dst_memory, src_memory, buffer_size, device_format);
break;
case ConversionType::FLOAT_TO_UNORM16:
convert_per_component<UnsignedNormalized<uint16_t>, F32>(
dst_memory, src_memory, buffer_size, device_format);
break;
case ConversionType::UNORM16_TO_FLOAT:
convert_per_component<F32, UnsignedNormalized<uint16_t>>(
dst_memory, src_memory, buffer_size, device_format);
break;
case ConversionType::FLOAT_TO_HALF:
convert_per_component<F16, F32>(dst_memory, src_memory, buffer_size, device_format);
break;
case ConversionType::HALF_TO_FLOAT:
convert_per_component<F32, F16>(dst_memory, src_memory, buffer_size, device_format);
break;
}
}
/* -------------------------------------------------------------------- */
/** \name API
* \{ */
void convert_host_to_device(void *dst_buffer,
const void *src_buffer,
size_t buffer_size,
eGPUDataFormat host_format,
eGPUTextureFormat device_format)
{
ConversionType conversion_type = host_to_device(host_format, device_format);
BLI_assert(conversion_type != ConversionType::UNSUPPORTED);
convert_buffer(dst_buffer, src_buffer, buffer_size, device_format, conversion_type);
}
void convert_device_to_host(void *dst_buffer,
const void *src_buffer,
size_t buffer_size,
eGPUDataFormat host_format,
eGPUTextureFormat device_format)
{
ConversionType conversion_type = reversed(host_to_device(host_format, device_format));
BLI_assert(conversion_type != ConversionType::UNSUPPORTED);
convert_buffer(dst_buffer, src_buffer, buffer_size, device_format, conversion_type);
}
/* \} */
} // namespace blender::gpu

View File

@ -0,0 +1,53 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2023 Blender Foundation. All rights reserved. */
/** \file
* \ingroup gpu
*/
#pragma once
#include "gpu_texture_private.hh"
namespace blender::gpu {
/**
* Convert host buffer to device buffer.
*
* \param dst_buffer: device buffer.
* \param src_buffer: host buffer.
* \param buffer_size: number of pixels to convert from the start of the given buffer.
* \param host_format: format of the host buffer
* \param device_format: format of the device buffer.
*
* \note Will assert when the host_format/device_format combination isn't valid
* (#validate_data_format) or supported. Some combinations aren't supported in Vulkan due to
* platform incompatibility.
*/
void convert_host_to_device(void *dst_buffer,
const void *src_buffer,
size_t buffer_size,
eGPUDataFormat host_format,
eGPUTextureFormat device_format);
/**
* Convert device buffer to host buffer.
*
* \param dst_buffer: host buffer
* \param src_buffer: device buffer.
* \param buffer_size: number of pixels to convert from the start of the given buffer.
* \param host_format: format of the host buffer
* \param device_format: format of the device buffer.
*
* \note Will assert when the host_format/device_format combination isn't valid
* (#validate_data_format) or supported. Some combinations aren't supported in Vulkan due to
* platform incompatibility.
*/
void convert_device_to_host(void *dst_buffer,
const void *src_buffer,
size_t buffer_size,
eGPUDataFormat host_format,
eGPUTextureFormat device_format);
}; // namespace blender::gpu

View File

@ -80,7 +80,8 @@ bool VKDescriptorPools::is_last_pool_active()
return active_pool_index_ == pools_.size() - 1;
}
VKDescriptorSet VKDescriptorPools::allocate(const VkDescriptorSetLayout &descriptor_set_layout)
std::unique_ptr<VKDescriptorSet> VKDescriptorPools::allocate(
const VkDescriptorSetLayout &descriptor_set_layout)
{
VkDescriptorSetAllocateInfo allocate_info = {};
VkDescriptorPool pool = active_pool_get();
@ -102,7 +103,7 @@ VKDescriptorSet VKDescriptorPools::allocate(const VkDescriptorSetLayout &descrip
return allocate(descriptor_set_layout);
}
return VKDescriptorSet(pool, vk_descriptor_set);
return std::make_unique<VKDescriptorSet>(pool, vk_descriptor_set);
}
void VKDescriptorPools::free(VKDescriptorSet &descriptor_set)

View File

@ -47,7 +47,7 @@ class VKDescriptorPools {
void init(const VkDevice vk_device);
VKDescriptorSet allocate(const VkDescriptorSetLayout &descriptor_set_layout);
std::unique_ptr<VKDescriptorSet> allocate(const VkDescriptorSetLayout &descriptor_set_layout);
void free(VKDescriptorSet &descriptor_set);
/**

View File

@ -7,6 +7,7 @@
#include "vk_descriptor_set.hh"
#include "vk_index_buffer.hh"
#include "vk_shader.hh"
#include "vk_storage_buffer.hh"
#include "vk_texture.hh"
#include "vk_uniform_buffer.hh"
@ -17,9 +18,7 @@
namespace blender::gpu {
VKDescriptorSet::VKDescriptorSet(VKDescriptorSet &&other)
: vk_descriptor_pool_(other.vk_descriptor_pool_),
vk_descriptor_set_(other.vk_descriptor_set_),
bindings_(std::move(other.bindings_))
: vk_descriptor_pool_(other.vk_descriptor_pool_), vk_descriptor_set_(other.vk_descriptor_set_)
{
other.mark_freed();
}
@ -40,7 +39,8 @@ void VKDescriptorSet::mark_freed()
vk_descriptor_pool_ = VK_NULL_HANDLE;
}
void VKDescriptorSet::bind(VKStorageBuffer &buffer, const Location location)
void VKDescriptorSetTracker::bind(VKStorageBuffer &buffer,
const VKDescriptorSet::Location location)
{
Binding &binding = ensure_location(location);
binding.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
@ -48,7 +48,8 @@ void VKDescriptorSet::bind(VKStorageBuffer &buffer, const Location location)
binding.buffer_size = buffer.size_in_bytes();
}
void VKDescriptorSet::bind_as_ssbo(VKVertexBuffer &buffer, const Location location)
void VKDescriptorSetTracker::bind_as_ssbo(VKVertexBuffer &buffer,
const VKDescriptorSet::Location location)
{
Binding &binding = ensure_location(location);
binding.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
@ -56,7 +57,8 @@ void VKDescriptorSet::bind_as_ssbo(VKVertexBuffer &buffer, const Location locati
binding.buffer_size = buffer.size_used_get();
}
void VKDescriptorSet::bind(VKUniformBuffer &buffer, const Location location)
void VKDescriptorSetTracker::bind(VKUniformBuffer &buffer,
const VKDescriptorSet::Location location)
{
Binding &binding = ensure_location(location);
binding.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
@ -64,7 +66,8 @@ void VKDescriptorSet::bind(VKUniformBuffer &buffer, const Location location)
binding.buffer_size = buffer.size_in_bytes();
}
void VKDescriptorSet::bind_as_ssbo(VKIndexBuffer &buffer, const Location location)
void VKDescriptorSetTracker::bind_as_ssbo(VKIndexBuffer &buffer,
const VKDescriptorSet::Location location)
{
Binding &binding = ensure_location(location);
binding.type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
@ -72,14 +75,16 @@ void VKDescriptorSet::bind_as_ssbo(VKIndexBuffer &buffer, const Location locatio
binding.buffer_size = buffer.size_get();
}
void VKDescriptorSet::image_bind(VKTexture &texture, const Location location)
void VKDescriptorSetTracker::image_bind(VKTexture &texture,
const VKDescriptorSet::Location location)
{
Binding &binding = ensure_location(location);
binding.type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
binding.vk_image_view = texture.vk_image_view_handle();
}
VKDescriptorSet::Binding &VKDescriptorSet::ensure_location(const Location location)
VKDescriptorSetTracker::Binding &VKDescriptorSetTracker::ensure_location(
const VKDescriptorSet::Location location)
{
for (Binding &binding : bindings_) {
if (binding.location == location) {
@ -93,8 +98,12 @@ VKDescriptorSet::Binding &VKDescriptorSet::ensure_location(const Location locati
return bindings_.last();
}
void VKDescriptorSet::update(VkDevice vk_device)
void VKDescriptorSetTracker::update(VKContext &context)
{
tracked_resource_for(context, !bindings_.is_empty());
std::unique_ptr<VKDescriptorSet> &descriptor_set = active_descriptor_set();
VkDescriptorSet vk_descriptor_set = descriptor_set->vk_handle();
Vector<VkDescriptorBufferInfo> buffer_infos;
Vector<VkWriteDescriptorSet> descriptor_writes;
@ -109,7 +118,7 @@ void VKDescriptorSet::update(VkDevice vk_device)
VkWriteDescriptorSet write_descriptor = {};
write_descriptor.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
write_descriptor.dstSet = vk_descriptor_set_;
write_descriptor.dstSet = vk_descriptor_set;
write_descriptor.dstBinding = binding.location;
write_descriptor.descriptorCount = 1;
write_descriptor.descriptorType = binding.type;
@ -129,7 +138,7 @@ void VKDescriptorSet::update(VkDevice vk_device)
VkWriteDescriptorSet write_descriptor = {};
write_descriptor.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
write_descriptor.dstSet = vk_descriptor_set_;
write_descriptor.dstSet = vk_descriptor_set;
write_descriptor.dstBinding = binding.location;
write_descriptor.descriptorCount = 1;
write_descriptor.descriptorType = binding.type;
@ -141,10 +150,16 @@ void VKDescriptorSet::update(VkDevice vk_device)
"Not all changes have been converted to a write descriptor. Check "
"`Binding::is_buffer` and `Binding::is_image`.");
VkDevice vk_device = context.device_get();
vkUpdateDescriptorSets(
vk_device, descriptor_writes.size(), descriptor_writes.data(), 0, nullptr);
bindings_.clear();
}
std::unique_ptr<VKDescriptorSet> VKDescriptorSetTracker::create_resource(VKContext &context)
{
return context.descriptor_pools_get().allocate(layout_);
}
} // namespace blender::gpu

View File

@ -12,7 +12,10 @@
#include "gpu_shader_private.hh"
#include "vk_buffer.hh"
#include "vk_common.hh"
#include "vk_resource_tracker.hh"
#include "vk_uniform_buffer.hh"
namespace blender::gpu {
class VKIndexBuffer;
@ -21,6 +24,7 @@ class VKStorageBuffer;
class VKTexture;
class VKUniformBuffer;
class VKVertexBuffer;
class VKDescriptorSetTracker;
/**
* In vulkan shader resources (images and buffers) are grouped in descriptor sets.
@ -31,7 +35,6 @@ class VKVertexBuffer;
* to use 2 descriptor sets per shader. One for each #blender::gpu::shader::Frequency.
*/
class VKDescriptorSet : NonCopyable {
struct Binding;
public:
/**
@ -69,42 +72,13 @@ class VKDescriptorSet : NonCopyable {
return binding;
}
friend struct Binding;
friend struct VKDescriptorSetTracker;
friend class VKShaderInterface;
};
private:
struct Binding {
Location location;
VkDescriptorType type;
VkBuffer vk_buffer = VK_NULL_HANDLE;
VkDeviceSize buffer_size = 0;
VkImageView vk_image_view = VK_NULL_HANDLE;
Binding()
{
location.binding = 0;
}
bool is_buffer() const
{
return ELEM(type, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
}
bool is_image() const
{
return ELEM(type, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
}
};
VkDescriptorPool vk_descriptor_pool_ = VK_NULL_HANDLE;
VkDescriptorSet vk_descriptor_set_ = VK_NULL_HANDLE;
/** A list of bindings that needs to be updated. */
Vector<Binding> bindings_;
public:
VKDescriptorSet() = default;
VKDescriptorSet(VkDescriptorPool vk_descriptor_pool, VkDescriptorSet vk_descriptor_set)
@ -131,22 +105,73 @@ class VKDescriptorSet : NonCopyable {
{
return vk_descriptor_pool_;
}
void mark_freed();
};
void bind_as_ssbo(VKVertexBuffer &buffer, Location location);
void bind_as_ssbo(VKIndexBuffer &buffer, Location location);
void bind(VKStorageBuffer &buffer, Location location);
void bind(VKUniformBuffer &buffer, Location location);
void image_bind(VKTexture &texture, Location location);
class VKDescriptorSetTracker : protected VKResourceTracker<VKDescriptorSet> {
friend class VKDescriptorSet;
public:
struct Binding {
VKDescriptorSet::Location location;
VkDescriptorType type;
VkBuffer vk_buffer = VK_NULL_HANDLE;
VkDeviceSize buffer_size = 0;
VkImageView vk_image_view = VK_NULL_HANDLE;
Binding()
{
location.binding = 0;
}
bool is_buffer() const
{
return ELEM(type, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
}
bool is_image() const
{
return ELEM(type, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
}
};
private:
/** A list of bindings that needs to be updated.*/
Vector<Binding> bindings_;
VkDescriptorSetLayout layout_;
public:
VKDescriptorSetTracker()
{
}
VKDescriptorSetTracker(VkDescriptorSetLayout layout) : layout_(layout)
{
}
void bind_as_ssbo(VKVertexBuffer &buffer, VKDescriptorSet::Location location);
void bind_as_ssbo(VKIndexBuffer &buffer, VKDescriptorSet::Location location);
void bind(VKStorageBuffer &buffer, VKDescriptorSet::Location location);
void bind(VKUniformBuffer &buffer, VKDescriptorSet::Location location);
void image_bind(VKTexture &texture, VKDescriptorSet::Location location);
/**
* Update the descriptor set on the device.
*/
void update(VkDevice vk_device);
void update(VKContext &context);
void mark_freed();
std::unique_ptr<VKDescriptorSet> &active_descriptor_set()
{
return active_resource();
}
protected:
std::unique_ptr<VKDescriptorSet> create_resource(VKContext &context) override;
private:
Binding &ensure_location(Location location);
Binding &ensure_location(VKDescriptorSet::Location location);
};
} // namespace blender::gpu

View File

@ -12,10 +12,10 @@
namespace blender::gpu {
VKPipeline::VKPipeline(VkPipeline vk_pipeline,
VKDescriptorSet &&descriptor_set,
VkDescriptorSetLayout vk_descriptor_set_layout,
VKPushConstants &&push_constants)
: vk_pipeline_(vk_pipeline),
descriptor_set_(std::move(descriptor_set)),
descriptor_set_(vk_descriptor_set_layout),
push_constants_(std::move(push_constants))
{
}
@ -56,9 +56,8 @@ VKPipeline VKPipeline::create_compute_pipeline(
return VKPipeline();
}
VKDescriptorSet descriptor_set = context.descriptor_pools_get().allocate(descriptor_set_layout);
VKPushConstants push_constants(&push_constants_layout);
return VKPipeline(vk_pipeline, std::move(descriptor_set), std::move(push_constants));
return VKPipeline(vk_pipeline, descriptor_set_layout, std::move(push_constants));
}
VkPipeline VKPipeline::vk_handle() const

View File

@ -21,7 +21,7 @@ class VKContext;
class VKPipeline : NonCopyable {
VkPipeline vk_pipeline_ = VK_NULL_HANDLE;
VKDescriptorSet descriptor_set_;
VKDescriptorSetTracker descriptor_set_;
VKPushConstants push_constants_;
public:
@ -29,7 +29,7 @@ class VKPipeline : NonCopyable {
virtual ~VKPipeline();
VKPipeline(VkPipeline vk_pipeline,
VKDescriptorSet &&vk_descriptor_set,
VkDescriptorSetLayout vk_descriptor_set_layout,
VKPushConstants &&push_constants);
VKPipeline &operator=(VKPipeline &&other)
{
@ -46,7 +46,7 @@ class VKPipeline : NonCopyable {
VkPipelineLayout &pipeline_layouts,
const VKPushConstants::Layout &push_constants_layout);
VKDescriptorSet &descriptor_set_get()
VKDescriptorSetTracker &descriptor_set_get()
{
return descriptor_set_;
}

View File

@ -7,6 +7,8 @@
#include "vk_pixel_buffer.hh"
#include "vk_context.hh"
namespace blender::gpu {
VKPixelBuffer::VKPixelBuffer(int64_t size) : PixelBuffer(size)

View File

@ -7,6 +7,7 @@
#include "vk_push_constants.hh"
#include "vk_backend.hh"
#include "vk_context.hh"
#include "vk_memory_layout.hh"
#include "vk_shader.hh"
#include "vk_shader_interface.hh"
@ -103,24 +104,12 @@ VKPushConstants::VKPushConstants() = default;
VKPushConstants::VKPushConstants(const Layout *layout) : layout_(layout)
{
data_ = MEM_mallocN(layout->size_in_bytes(), __func__);
switch (layout_->storage_type_get()) {
case StorageType::UNIFORM_BUFFER:
uniform_buffer_ = new VKUniformBuffer(layout_->size_in_bytes(), __func__);
break;
case StorageType::PUSH_CONSTANTS:
case StorageType::NONE:
break;
}
}
VKPushConstants::VKPushConstants(VKPushConstants &&other) : layout_(other.layout_)
{
data_ = other.data_;
other.data_ = nullptr;
uniform_buffer_ = other.uniform_buffer_;
other.uniform_buffer_ = nullptr;
}
VKPushConstants::~VKPushConstants()
@ -129,9 +118,6 @@ VKPushConstants::~VKPushConstants()
MEM_freeN(data_);
data_ = nullptr;
}
delete uniform_buffer_;
uniform_buffer_ = nullptr;
}
VKPushConstants &VKPushConstants::operator=(VKPushConstants &&other)
@ -141,9 +127,6 @@ VKPushConstants &VKPushConstants::operator=(VKPushConstants &&other)
data_ = other.data_;
other.data_ = nullptr;
uniform_buffer_ = other.uniform_buffer_;
other.uniform_buffer_ = nullptr;
return *this;
}
@ -155,7 +138,7 @@ void VKPushConstants::update(VKContext &context)
BLI_assert_msg(&pipeline.push_constants_get() == this,
"Invalid state detected. Push constants doesn't belong to the active shader of "
"the given context.");
VKDescriptorSet &descriptor_set = pipeline.descriptor_set_get();
VKDescriptorSetTracker &descriptor_set = pipeline.descriptor_set_get();
switch (layout_get().storage_type_get()) {
case VKPushConstants::StorageType::NONE:
@ -167,7 +150,7 @@ void VKPushConstants::update(VKContext &context)
case VKPushConstants::StorageType::UNIFORM_BUFFER:
update_uniform_buffer();
descriptor_set.bind(uniform_buffer_get(), layout_get().descriptor_set_location_get());
descriptor_set.bind(*uniform_buffer_get(), layout_get().descriptor_set_location_get());
break;
}
}
@ -175,16 +158,22 @@ void VKPushConstants::update(VKContext &context)
void VKPushConstants::update_uniform_buffer()
{
BLI_assert(layout_->storage_type_get() == StorageType::UNIFORM_BUFFER);
BLI_assert(uniform_buffer_ != nullptr);
BLI_assert(data_ != nullptr);
uniform_buffer_->update(data_);
VKContext &context = *VKContext::get();
std::unique_ptr<VKUniformBuffer> &uniform_buffer = tracked_resource_for(context, is_dirty_);
uniform_buffer->update(data_);
is_dirty_ = false;
}
VKUniformBuffer &VKPushConstants::uniform_buffer_get()
std::unique_ptr<VKUniformBuffer> &VKPushConstants::uniform_buffer_get()
{
BLI_assert(layout_->storage_type_get() == StorageType::UNIFORM_BUFFER);
BLI_assert(uniform_buffer_ != nullptr);
return *uniform_buffer_;
return active_resource();
}
std::unique_ptr<VKUniformBuffer> VKPushConstants::create_resource(VKContext & /*context*/)
{
return std::make_unique<VKUniformBuffer>(layout_->size_in_bytes(), __func__);
}
} // namespace blender::gpu

View File

@ -43,7 +43,7 @@ class VKContext;
* It should also keep track of the submissions in order to reuse the allocated
* data.
*/
class VKPushConstants : NonCopyable {
class VKPushConstants : VKResourceTracker<VKUniformBuffer> {
public:
/** Different methods to store push constants. */
enum class StorageType {
@ -151,7 +151,7 @@ class VKPushConstants : NonCopyable {
private:
const Layout *layout_ = nullptr;
void *data_ = nullptr;
VKUniformBuffer *uniform_buffer_ = nullptr;
bool is_dirty_ = false;
public:
VKPushConstants();
@ -171,6 +171,11 @@ class VKPushConstants : NonCopyable {
return *layout_;
}
/**
* Part of Resource Tracking API is called when new resource is needed.
*/
std::unique_ptr<VKUniformBuffer> create_resource(VKContext &context) override;
/**
* Get the reference to the active data.
*
@ -209,6 +214,7 @@ class VKPushConstants : NonCopyable {
layout_->size_in_bytes(),
"Tried to write outside the push constant allocated memory.");
memcpy(dst, input_data, comp_len * array_size * sizeof(T));
is_dirty_ = true;
return;
}
@ -222,6 +228,7 @@ class VKPushConstants : NonCopyable {
src += comp_len;
dst += 4;
}
is_dirty_ = true;
}
/**
@ -243,7 +250,7 @@ class VKPushConstants : NonCopyable {
*
* Only valid when storage type = StorageType::UNIFORM_BUFFER.
*/
VKUniformBuffer &uniform_buffer_get();
std::unique_ptr<VKUniformBuffer> &uniform_buffer_get();
};
} // namespace blender::gpu

View File

@ -0,0 +1,23 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2023 Blender Foundation. All rights reserved. */
/** \file
* \ingroup gpu
*/
#include "vk_resource_tracker.hh"
#include "vk_context.hh"
namespace blender::gpu {
bool VKSubmissionTracker::is_changed(VKContext &context)
{
VKCommandBuffer &command_buffer = context.command_buffer_get();
const VKSubmissionID &current_id = command_buffer.submission_id_get();
if (last_known_id_ != current_id) {
last_known_id_ = current_id;
return true;
}
return false;
}
} // namespace blender::gpu

View File

@ -0,0 +1,177 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2023 Blender Foundation. All rights reserved. */
/** \file
* \ingroup gpu
*/
#pragma once
#include "BLI_utility_mixins.hh"
#include "BLI_vector.hh"
#include "vk_common.hh"
namespace blender::gpu {
class VKContext;
class VKCommandBuffer;
/**
* In vulkan multiple commands can be in flight simultaneously.
*
* These commands can share the same resources like descriptor sets
* or push constants. When between commands these resources are updated
* a new version of these resources should be created.
*
* When a resource is updated it should check the submission id of the
* command buffer. If it is different, then the resource can be reused.
* If the submission id is the same a new version of the resource to now
* intervene with other commands that uses the resource.
*
* VKSubmissionID is the identifier to keep track if a new submission is
* being recorded.
*/
struct VKSubmissionID {
private:
int64_t id_ = -1;
public:
VKSubmissionID() = default;
private:
/**
* Reset the submission id.
*
* This should only be called during initialization of the command buffer.
* As it leads to undesired behavior after resources are already tracking
* the submission id.
*/
void reset()
{
id_ = 0;
}
/**
* Change the submission id.
*
* Is called when submitting a command buffer to the queue. In this case resource
* known that the next time it is used that it can free its sub resources used by
* the previous submission.
*/
void next()
{
id_++;
}
public:
const VKSubmissionID &operator=(const VKSubmissionID &other)
{
id_ = other.id_;
return *this;
}
bool operator==(const VKSubmissionID &other)
{
return id_ == other.id_;
}
bool operator!=(const VKSubmissionID &other)
{
return id_ != other.id_;
}
friend class VKCommandBuffer;
};
/**
* Submission tracker keeps track of the last known submission id of the
* command buffer.
*/
class VKSubmissionTracker {
VKSubmissionID last_known_id_;
public:
/**
* Check if the submission_id has changed since the last time it was called
* on this VKSubmissionTracker.
*/
bool is_changed(VKContext &context);
};
/**
* VKResourceTracker will keep track of resources.
*/
template<typename Resource> class VKResourceTracker : NonCopyable {
VKSubmissionTracker submission_tracker_;
Vector<std::unique_ptr<Resource>> tracked_resources_;
protected:
VKResourceTracker<Resource>() = default;
VKResourceTracker<Resource>(VKResourceTracker<Resource> &&other)
: submission_tracker_(other.submission_tracker_),
tracked_resources_(std::move(other.tracked_resources_))
{
}
VKResourceTracker<Resource> &operator=(VKResourceTracker<Resource> &&other)
{
submission_tracker_ = other.submission_tracker_;
tracked_resources_ = std::move(other.tracked_resources_);
return *this;
}
virtual ~VKResourceTracker()
{
free_tracked_resources();
}
/**
* Get a resource what can be used by the resource tracker.
*
* When a different submission was detected all previous resources
* will be freed and a new resource will be returned.
*
* When still in the same submission and we need to update the resource
* (is_dirty=true) then a new resource will be returned. Otherwise
* the previous used resource will be used.
*
* When no resources exists, a new resource will be created.
*
* The resource given back is owned by this resource tracker. And
* the resource should not be stored outside this class as it might
* be destroyed when the next submission is detected.
*/
std::unique_ptr<Resource> &tracked_resource_for(VKContext &context, const bool is_dirty)
{
if (submission_tracker_.is_changed(context)) {
free_tracked_resources();
tracked_resources_.append(create_resource(context));
}
else if (is_dirty || tracked_resources_.is_empty()) {
tracked_resources_.append(create_resource(context));
}
return active_resource();
}
/**
* Callback to create a new resource. Can be called by the `tracked_resource_for` method.
*/
virtual std::unique_ptr<Resource> create_resource(VKContext &context) = 0;
/**
* Return the active resource of the tracker.
*/
std::unique_ptr<Resource> &active_resource()
{
BLI_assert(!tracked_resources_.is_empty());
return tracked_resources_.last();
}
private:
void free_tracked_resources()
{
tracked_resources_.clear();
}
};
} // namespace blender::gpu

View File

@ -9,10 +9,13 @@
#include "vk_buffer.hh"
#include "vk_context.hh"
#include "vk_data_conversion.hh"
#include "vk_memory.hh"
#include "vk_shader.hh"
#include "vk_shader_interface.hh"
#include "BLI_math_vector.hh"
#include "BKE_global.h"
namespace blender::gpu {
@ -34,8 +37,64 @@ void VKTexture::copy_to(Texture * /*tex*/)
{
}
void VKTexture::clear(eGPUDataFormat /*format*/, const void * /*data*/)
template<typename T> void copy_color(T dst[4], const T *src)
{
dst[0] = src[0];
dst[1] = src[1];
dst[2] = src[2];
dst[3] = src[3];
}
static VkClearColorValue to_vk_clear_color_value(eGPUDataFormat format, const void *data)
{
VkClearColorValue result = {0.0f};
switch (format) {
case GPU_DATA_FLOAT: {
const float *float_data = static_cast<const float *>(data);
copy_color<float>(result.float32, float_data);
break;
}
case GPU_DATA_INT: {
const int32_t *int_data = static_cast<const int32_t *>(data);
copy_color<int32_t>(result.int32, int_data);
break;
}
case GPU_DATA_UINT: {
const uint32_t *uint_data = static_cast<const uint32_t *>(data);
copy_color<uint32_t>(result.uint32, uint_data);
break;
}
case GPU_DATA_HALF_FLOAT:
case GPU_DATA_UBYTE:
case GPU_DATA_UINT_24_8:
case GPU_DATA_10_11_11_REV:
case GPU_DATA_2_10_10_10_REV: {
BLI_assert_unreachable();
break;
}
}
return result;
}
void VKTexture::clear(eGPUDataFormat format, const void *data)
{
if (!is_allocated()) {
allocate();
}
VKContext &context = *VKContext::get();
VKCommandBuffer &command_buffer = context.command_buffer_get();
VkClearColorValue clear_color = to_vk_clear_color_value(format, data);
VkImageSubresourceRange range = {0};
range.aspectMask = to_vk_image_aspect_flag_bits(format_);
range.levelCount = VK_REMAINING_MIP_LEVELS;
range.layerCount = VK_REMAINING_ARRAY_LAYERS;
command_buffer.clear(
vk_image_, VK_IMAGE_LAYOUT_GENERAL, clear_color, Span<VkImageSubresourceRange>(&range, 1));
}
void VKTexture::swizzle_set(const char /*swizzle_mask*/[4])
@ -79,22 +138,41 @@ void *VKTexture::read(int mip, eGPUDataFormat format)
command_buffer.submit();
void *data = MEM_mallocN(host_memory_size, __func__);
/* TODO: add conversion when data format is different. */
BLI_assert_msg(device_memory_size == host_memory_size,
"Memory data conversions not implemented yet");
staging_buffer.read(data);
convert_device_to_host(data, staging_buffer.mapped_memory_get(), sample_len, format, format_);
return data;
}
void VKTexture::update_sub(int /*mip*/,
int /*offset*/[3],
int /*extent*/[3],
eGPUDataFormat /*format*/,
const void * /*data*/)
void VKTexture::update_sub(
int mip, int offset[3], int extent[3], eGPUDataFormat format, const void *data)
{
if (!is_allocated()) {
allocate();
}
/* Vulkan images cannot be directly mapped to host memory and requires a staging buffer. */
VKContext &context = *VKContext::get();
VKBuffer staging_buffer;
size_t sample_len = extent[0] * extent[1] * extent[2];
size_t device_memory_size = sample_len * to_bytesize(format_);
staging_buffer.create(
context, device_memory_size, GPU_USAGE_DEVICE_ONLY, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
convert_host_to_device(staging_buffer.mapped_memory_get(), data, sample_len, format, format_);
VkBufferImageCopy region = {};
region.imageExtent.width = extent[0];
region.imageExtent.height = extent[1];
region.imageExtent.depth = extent[2];
region.imageOffset.x = offset[0];
region.imageOffset.y = offset[1];
region.imageOffset.z = offset[2];
region.imageSubresource.aspectMask = to_vk_image_aspect_flag_bits(format_);
region.imageSubresource.mipLevel = mip;
region.imageSubresource.layerCount = 1;
VKCommandBuffer &command_buffer = context.command_buffer_get();
command_buffer.copy(*this, staging_buffer, Span<VkBufferImageCopy>(&region, 1));
command_buffer.submit();
}
void VKTexture::update_sub(int /*offset*/[3],
@ -115,6 +193,8 @@ bool VKTexture::init_internal()
/* Initialization can only happen after the usage is known. By the current API this isn't set
* at this moment, so we cannot initialize here. The initialization is postponed until the
* allocation of the texture on the device. */
/* TODO: return false when texture format isn't supported. */
return true;
}
@ -152,12 +232,12 @@ bool VKTexture::allocate()
image_info.format = to_vk_format(format_);
image_info.tiling = VK_IMAGE_TILING_LINEAR;
image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
image_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT |
VK_IMAGE_USAGE_STORAGE_BIT;
image_info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT;
image_info.samples = VK_SAMPLE_COUNT_1_BIT;
VkResult result;
if (G.debug &= G_DEBUG_GPU) {
if (G.debug & G_DEBUG_GPU) {
VkImageFormatProperties image_format = {};
result = vkGetPhysicalDeviceImageFormatProperties(context.physical_device_get(),
image_info.format,

View File

@ -7,13 +7,15 @@
#pragma once
#include "BLI_utility_mixins.hh"
#include "gpu_uniform_buffer_private.hh"
#include "vk_buffer.hh"
namespace blender::gpu {
class VKUniformBuffer : public UniformBuf {
class VKUniformBuffer : public UniformBuf, NonCopyable {
VKBuffer buffer_;
public:

View File

@ -676,12 +676,7 @@ ImBuf *imb_loadtarga(const uchar *mem, size_t mem_size, int flags, char colorspa
cmap[count] = cp_data;
}
size = 0;
for (int cmap_index = cmap_max - 1; cmap_index > 0; cmap_index >>= 1) {
size++;
}
ibuf->planes = size;
ibuf->planes = tga.mapbits;
if (tga.mapbits != 32) { /* Set alpha bits. */
cmap[0] &= BIG_LONG(0x00ffffffl);
}

View File

@ -332,7 +332,7 @@ static void rna_ColorRamp_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *
WM_main_add_notifier(NC_LINESTYLE, linestyle);
break;
}
/* ColorRamp for particle display is owned by the object (see #54422) */
/* Color Ramp for particle display is owned by the object (see #54422) */
case ID_OB:
case ID_PA: {
ParticleSettings *part = (ParticleSettings *)ptr->owner_id;
@ -979,7 +979,7 @@ static void rna_def_color_ramp_element_api(BlenderRNA *brna, PropertyRNA *cprop)
/* TODO: make these functions generic in `texture.c`. */
func = RNA_def_function(srna, "new", "rna_ColorRampElement_new");
RNA_def_function_ui_description(func, "Add element to ColorRamp");
RNA_def_function_ui_description(func, "Add element to Color Ramp");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
parm = RNA_def_float(
func, "position", 0.0f, 0.0f, 1.0f, "Position", "Position to add element", 0.0f, 1.0f);
@ -989,7 +989,7 @@ static void rna_def_color_ramp_element_api(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_function_return(func, parm);
func = RNA_def_function(srna, "remove", "rna_ColorRampElement_remove");
RNA_def_function_ui_description(func, "Delete element from ColorRamp");
RNA_def_function_ui_description(func, "Delete element from Color Ramp");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
parm = RNA_def_pointer(func, "element", "ColorRampElement", "", "Element to remove");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
@ -1069,14 +1069,14 @@ static void rna_def_color_ramp(BlenderRNA *brna)
# endif
func = RNA_def_function(srna, "evaluate", "rna_ColorRamp_eval");
RNA_def_function_ui_description(func, "Evaluate ColorRamp");
RNA_def_function_ui_description(func, "Evaluate Color Ramp");
parm = RNA_def_float(func,
"position",
1.0f,
0.0f,
1.0f,
"Position",
"Evaluate ColorRamp at position",
"Evaluate Color Ramp at position",
0.0f,
1.0f);
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);

View File

@ -26,7 +26,7 @@ DefNode(Node, NODE_REROUTE, 0, "REROUT
DefNode(ShaderNode, SH_NODE_RGB, 0, "RGB", RGB, "RGB", "A color picker")
DefNode(ShaderNode, SH_NODE_VALUE, 0, "VALUE", Value, "Value", "Used to Input numerical values to other nodes in the tree")
DefNode(ShaderNode, SH_NODE_MIX_RGB_LEGACY, def_mix_rgb, "MIX_RGB", MixRGB, "MixRGB", "Mix two input colors")
DefNode(ShaderNode, SH_NODE_VALTORGB, def_colorramp, "VALTORGB", ValToRGB, "ColorRamp", "Map values to colors with the use of a gradient")
DefNode(ShaderNode, SH_NODE_VALTORGB, def_colorramp, "VALTORGB", ValToRGB, "Color Ramp", "Map values to colors with the use of a gradient")
DefNode(ShaderNode, SH_NODE_RGBTOBW, 0, "RGBTOBW", RGBToBW, "RGB to BW", "Convert a color's luminance to a grayscale value")
DefNode(ShaderNode, SH_NODE_SHADERTORGB, 0, "SHADERTORGB", ShaderToRGB, "Shader to RGB", "Convert rendering effect (such as light and shadow) to color. Typically used for non-photorealistic rendering, to apply additional effects on the output of BSDFs.\nNote: only supported for Eevee")
DefNode(ShaderNode, SH_NODE_NORMAL, 0, "NORMAL", Normal, "Normal", "Generate a normal vector and a dot product")
@ -128,7 +128,7 @@ DefNode(CompositorNode, CMP_NODE_VIEWER, def_cmp_viewer, "VIEWER
DefNode(CompositorNode, CMP_NODE_RGB, 0, "RGB", RGB, "RGB", "" )
DefNode(CompositorNode, CMP_NODE_VALUE, 0, "VALUE", Value, "Value", "" )
DefNode(CompositorNode, CMP_NODE_MIX_RGB, def_mix_rgb, "MIX_RGB", MixRGB, "Mix", "" )
DefNode(CompositorNode, CMP_NODE_VALTORGB, def_colorramp, "VALTORGB", ValToRGB, "ColorRamp", "" )
DefNode(CompositorNode, CMP_NODE_VALTORGB, def_colorramp, "VALTORGB", ValToRGB, "Color Ramp", "" )
DefNode(CompositorNode, CMP_NODE_RGBTOBW, 0, "RGBTOBW", RGBToBW, "RGB to BW", "" )
DefNode(CompositorNode, CMP_NODE_NORMAL, 0, "NORMAL", Normal, "Normal", "" )
DefNode(CompositorNode, CMP_NODE_CURVE_VEC, def_vector_curve, "CURVE_VEC", CurveVec, "Vector Curves", "" )
@ -231,7 +231,7 @@ DefNode(TextureNode, TEX_NODE_BRICKS, def_tex_bricks, "BRICKS
DefNode(TextureNode, TEX_NODE_MATH, def_math, "MATH", Math, "Math", "" )
DefNode(TextureNode, TEX_NODE_MIX_RGB, def_mix_rgb, "MIX_RGB", MixRGB, "Mix RGB", "" )
DefNode(TextureNode, TEX_NODE_RGBTOBW, 0, "RGBTOBW", RGBToBW, "RGB to BW", "" )
DefNode(TextureNode, TEX_NODE_VALTORGB, def_colorramp, "VALTORGB", ValToRGB, "ColorRamp", "" )
DefNode(TextureNode, TEX_NODE_VALTORGB, def_colorramp, "VALTORGB", ValToRGB, "Color Ramp", "" )
DefNode(TextureNode, TEX_NODE_IMAGE, def_tex_image, "IMAGE", Image, "Image", "" )
DefNode(TextureNode, TEX_NODE_CURVE_RGB, def_rgb_curve, "CURVE_RGB", CurveRGB, "RGB Curves", "" )
DefNode(TextureNode, TEX_NODE_INVERT, 0, "INVERT", Invert, "Invert", "" )

View File

@ -135,7 +135,7 @@ void register_node_type_cmp_valtorgb()
static bNodeType ntype;
cmp_node_type_base(&ntype, CMP_NODE_VALTORGB, "ColorRamp", NODE_CLASS_CONVERTER);
cmp_node_type_base(&ntype, CMP_NODE_VALTORGB, "Color Ramp", NODE_CLASS_CONVERTER);
ntype.declare = file_ns::cmp_node_valtorgb_declare;
node_type_size(&ntype, 240, 200, 320);
ntype.initfunc = file_ns::node_composit_init_valtorgb;

View File

@ -136,7 +136,7 @@ void register_node_type_sh_valtorgb()
static bNodeType ntype;
sh_fn_node_type_base(&ntype, SH_NODE_VALTORGB, "ColorRamp", NODE_CLASS_CONVERTER);
sh_fn_node_type_base(&ntype, SH_NODE_VALTORGB, "Color Ramp", NODE_CLASS_CONVERTER);
ntype.declare = file_ns::sh_node_valtorgb_declare;
ntype.initfunc = file_ns::node_shader_init_valtorgb;
node_type_size_preset(&ntype, NODE_SIZE_LARGE);

View File

@ -47,7 +47,7 @@ void register_node_type_tex_valtorgb(void)
{
static bNodeType ntype;
tex_node_type_base(&ntype, TEX_NODE_VALTORGB, "ColorRamp", NODE_CLASS_CONVERTER);
tex_node_type_base(&ntype, TEX_NODE_VALTORGB, "Color Ramp", NODE_CLASS_CONVERTER);
node_type_socket_templates(&ntype, valtorgb_in, valtorgb_out);
node_type_size_preset(&ntype, NODE_SIZE_LARGE);
ntype.initfunc = valtorgb_init;

View File

@ -526,7 +526,7 @@ static int py_to_array(PyObject *seq,
// totdim = RNA_property_array_dimension(ptr, prop, dim_size); /* UNUSED */
const int flag = RNA_property_flag(prop);
/* Use #ParameterDynAlloc which defines it's own array length. */
/* Use #ParameterDynAlloc which defines its own array length. */
const bool prop_is_param_dyn_alloc = param_data && (flag & PROP_DYNAMIC);
if (validate_array(seq,

View File

@ -129,6 +129,11 @@ typedef enum eWM_CapabilitiesFlag {
WM_CAPABILITY_CURSOR_WARP = (1 << 0),
/** Ability to access window positions & move them. */
WM_CAPABILITY_WINDOW_POSITION = (1 << 1),
/**
* The windowing system supports a separate primary clipboard
* (typically set when interactively selecting text).
*/
WM_CAPABILITY_PRIMARY_CLIPBOARD = (1 << 2),
} eWM_CapabilitiesFlag;
eWM_CapabilitiesFlag WM_capabilities_flag(void);

View File

@ -129,7 +129,7 @@ wmGizmoGroupTypeRef *WM_gizmogrouptype_append_and_link(wmGizmoMapType *gzmap_typ
*/
static void gizmogrouptype_free(wmGizmoGroupType *gzgt)
{
/* Python gizmo group, allocates it's own string. */
/* Python gizmo group, allocates its own string. */
if (gzgt->rna_ext.srna) {
MEM_freeN((void *)gzgt->idname);
}

View File

@ -106,7 +106,7 @@ void WM_gizmotype_append_ptr(void (*gtfunc)(struct wmGizmoType *, void *), void
void WM_gizmotype_free_ptr(wmGizmoType *gzt)
{
/* Python gizmo, allocates it's own string. */
/* Python gizmo, allocates its own string. */
if (gzt->rna_ext.srna) {
MEM_freeN((void *)gzt->idname);
}

View File

@ -1149,7 +1149,7 @@ static void wm_operator_finished(bContext *C,
}
}
else if (has_undo_step) {
/* An undo step was added but the operator wasn't registered (and won't register it's self),
/* An undo step was added but the operator wasn't registered (and won't register itself),
* therefor a redo panel wouldn't redo this action but the previous registered action,
* causing the "redo" to remove/loose this operator. See: #101743.
* Register check is needed so nested operator calls don't clear the HUD. See: #103587. */

View File

@ -1112,7 +1112,7 @@ void wm_homefile_read_ex(bContext *C,
const bool use_userdef = params_homefile->use_userdef;
bool use_factory_settings = params_homefile->use_factory_settings;
/* Currently this only impacts preferences as it doesn't make much sense to keep the default
* startup open in the case the app-template doesn't happen to define it's own startup.
* startup open in the case the app-template doesn't happen to define its own startup.
* Unlike preferences where we might want to only reset the app-template part of the preferences
* so as not to reset the preferences for all other Blender instances, see: #96427. */
const bool use_factory_settings_app_template_only =
@ -1604,7 +1604,7 @@ static void wm_history_file_update(void)
*
* - An image is saved to the thumbnail cache, sized at #PREVIEW_RENDER_LARGE_HEIGHT.
*
* - A smaller thumbnail is stored in the `.blend` file it's self, sized at #BLEN_THUMB_SIZE.
* - A smaller thumbnail is stored in the `.blend` file itself, sized at #BLEN_THUMB_SIZE.
* The size is kept small to prevent thumbnails bloating the size of `.blend` files.
*
* The this thumbnail will be extracted if the file is shared or the local thumbnail cache

View File

@ -187,7 +187,7 @@ static void operatortype_ghash_free_cb(wmOperatorType *ot)
}
if (ot->rna_ext.srna) {
/* A Python operator, allocates it's own string. */
/* A Python operator, allocates its own string. */
MEM_freeN((void *)ot->idname);
}

View File

@ -1834,6 +1834,10 @@ eWM_CapabilitiesFlag WM_capabilities_flag(void)
if (GHOST_SupportsWindowPosition()) {
flag |= WM_CAPABILITY_WINDOW_POSITION;
}
if (GHOST_SupportsPrimaryClipboard()) {
flag |= WM_CAPABILITY_PRIMARY_CLIPBOARD;
}
return flag;
}

View File

@ -20,6 +20,10 @@ endif()
get_property(_test_libs GLOBAL PROPERTY BLENDER_TEST_LIBS)
if(WIN32 OR APPLE)
# Windows and macOS set target_link_options after target creation.
#
# Still need to ensure dependency between the test libraries and the blender_test binary, so that
# the latter one is re-linked when the test library is re-compiled.
list(APPEND TEST_LIBS ${_test_libs})
elseif(UNIX)
list(APPEND TEST_LIBS "-Wl,--whole-archive" ${_test_libs} "-Wl,--no-whole-archive")
else()

View File

@ -234,7 +234,7 @@ class TestPropArrayDynamicAssign(unittest.TestCase):
class TestPropArrayDynamicArg(unittest.TestCase):
"""
Index array, a dynamic array argument which defines it's own length.
Index array, a dynamic array argument which defines its own length.
"""
dims = 8

View File

@ -418,7 +418,7 @@ def main() -> None:
source_paths_include=(".",),
source_paths_exclude=(
# Directories:
# This is an exception, it has it's own CMake files we do not maintain.
# This is an exception, it has its own CMake files we do not maintain.
"./extern/audaspace",
"./extern/quadriflow/3rd/lemon-1.3.1",
),
@ -428,7 +428,7 @@ def main() -> None:
source_paths_include=(".",),
source_paths_exclude=(
# Directories:
# This is an exception, it has it's own CMake files we do not maintain.
# This is an exception, it has its own CMake files we do not maintain.
"./extern",
"./scripts/addons_contrib",
# Just data.

View File

@ -40,7 +40,7 @@
}
##----------------------------------------------------------------------##
# Python Calls aren't so useful unless we're debugging Python it's self
# Python Calls aren't so useful unless we're debugging Python itself
# _PyObject_Free
{