Curves: Add edit mode operator to set attribute values #105076

Merged
Hans Goudey merged 9 commits from HooglyBoogly/blender:curves-attribute-set into main 2023-10-17 12:35:50 +02:00
41 changed files with 589 additions and 275 deletions
Showing only changes of commit 3c14f2c675 - Show all commits

View File

@ -1826,7 +1826,10 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, uint msg, WPARAM wParam,
if (!window->m_mousePresent) { if (!window->m_mousePresent) {
WINTAB_PRINTF("HWND %p mouse enter\n", window->getHWND()); WINTAB_PRINTF("HWND %p mouse enter\n", window->getHWND());
TRACKMOUSEEVENT tme = {sizeof(tme)}; TRACKMOUSEEVENT tme = {sizeof(tme)};
tme.dwFlags = TME_LEAVE; /* Request WM_MOUSELEAVE message when the cursor leaves the client area, and
* WM_MOUSEHOVER message after 50ms when in the client area. */
tme.dwFlags = TME_LEAVE | TME_HOVER;
tme.dwHoverTime = 50;
tme.hwndTrack = hwnd; tme.hwndTrack = hwnd;
TrackMouseEvent(&tme); TrackMouseEvent(&tme);
window->m_mousePresent = true; window->m_mousePresent = true;
@ -1843,6 +1846,35 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, uint msg, WPARAM wParam,
break; break;
} }
case WM_MOUSEHOVER: {
/* Mouse Tracking is now off. TrackMouseEvent restarts in MouseMove. */
window->m_mousePresent = false;
/* Auto-focus only occurs within Blender windows, not with _other_ applications. */
HWND old_hwnd = ::GetFocus();
if (hwnd != old_hwnd) {
HWND new_parent = ::GetParent(hwnd);
HWND old_parent = ::GetParent(old_hwnd);
if (hwnd == old_parent || old_hwnd == new_parent) {
/* Child to its parent, parent to its child. */
::SetFocus(hwnd);
}
else if (new_parent != HWND_DESKTOP && new_parent == old_parent) {
/* Between siblings of same parent. */
::SetFocus(hwnd);
}
else if (!new_parent && !old_parent) {
/* Between main windows that don't overlap. */
RECT new_rect, old_rect, dest_rect;
::GetWindowRect(hwnd, &new_rect);
::GetWindowRect(old_hwnd, &old_rect);
if (!IntersectRect(&dest_rect, &new_rect, &old_rect)) {
::SetFocus(hwnd);
}
}
}
break;
}
case WM_MOUSEWHEEL: { case WM_MOUSEWHEEL: {
/* The WM_MOUSEWHEEL message is sent to the focus window /* The WM_MOUSEWHEEL message is sent to the focus window
* when the mouse wheel is rotated. The DefWindowProc * when the mouse wheel is rotated. The DefWindowProc

View File

@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-or-later # SPDX-License-Identifier: GPL-2.0-or-later
import bpy import bpy
from bpy.types import Panel, Menu from bpy.types import Panel, Menu, UIList
from rna_prop_ui import PropertyPanel from rna_prop_ui import PropertyPanel
from bl_ui.properties_animviz import ( from bl_ui.properties_animviz import (
@ -91,6 +91,16 @@ class DATA_MT_bone_group_context_menu(Menu):
layout.operator("pose.group_sort", icon='SORTALPHA') layout.operator("pose.group_sort", icon='SORTALPHA')
class DATA_UL_bone_groups(UIList):
def draw_item(self, _context, layout, _data, item, _icon, _active_data, _active_propname, _index):
layout.prop(item, "name", text="", emboss=False, icon='GROUP_BONE')
if item.is_custom_color_set or item.color_set == 'DEFAULT':
layout.prop(item, "color_set", icon_only=True, icon="COLOR")
else:
layout.prop(item, "color_set", icon_only=True)
class DATA_PT_bone_groups(ArmatureButtonsPanel, Panel): class DATA_PT_bone_groups(ArmatureButtonsPanel, Panel):
bl_label = "Bone Groups" bl_label = "Bone Groups"
bl_options = {'DEFAULT_CLOSED'} bl_options = {'DEFAULT_CLOSED'}
@ -111,8 +121,9 @@ class DATA_PT_bone_groups(ArmatureButtonsPanel, Panel):
rows = 1 rows = 1
if group: if group:
rows = 4 rows = 4
row.template_list( row.template_list(
"UI_UL_list", "DATA_UL_bone_groups",
"bone_groups", "bone_groups",
pose, pose,
"bone_groups", "bone_groups",
@ -121,6 +132,7 @@ class DATA_PT_bone_groups(ArmatureButtonsPanel, Panel):
rows=rows, rows=rows,
) )
col = row.column(align=True) col = row.column(align=True)
col.operator("pose.group_add", icon='ADD', text="") col.operator("pose.group_add", icon='ADD', text="")
col.operator("pose.group_remove", icon='REMOVE', text="") col.operator("pose.group_remove", icon='REMOVE', text="")
@ -130,17 +142,20 @@ class DATA_PT_bone_groups(ArmatureButtonsPanel, Panel):
col.operator("pose.group_move", icon='TRIA_UP', text="").direction = 'UP' col.operator("pose.group_move", icon='TRIA_UP', text="").direction = 'UP'
col.operator("pose.group_move", icon='TRIA_DOWN', text="").direction = 'DOWN' col.operator("pose.group_move", icon='TRIA_DOWN', text="").direction = 'DOWN'
split = layout.split() if group.is_custom_color_set:
col = layout.column()
split = col.split(factor=0.4)
col = split.column()
col.prop(group, "color_set")
if group.color_set:
col = split.column() col = split.column()
sub = col.row(align=True) row = col.row()
sub.enabled = group.is_custom_color_set # only custom colors are editable row.alignment = 'RIGHT'
sub.prop(group.colors, "normal", text="") row.label(text="Custom Colors")
sub.prop(group.colors, "select", text="")
sub.prop(group.colors, "active", text="") col = split.column(align=True)
row = col.row(align=True)
row.prop(group.colors, "normal", text="")
row.prop(group.colors, "select", text="")
row.prop(group.colors, "active", text="")
row = layout.row() row = layout.row()
@ -258,6 +273,7 @@ classes = (
DATA_PT_skeleton, DATA_PT_skeleton,
DATA_MT_bone_group_context_menu, DATA_MT_bone_group_context_menu,
DATA_PT_bone_groups, DATA_PT_bone_groups,
DATA_UL_bone_groups,
DATA_PT_motion_paths, DATA_PT_motion_paths,
DATA_PT_motion_paths_display, DATA_PT_motion_paths_display,
DATA_PT_display, DATA_PT_display,

View File

@ -1091,17 +1091,6 @@ static void blf_glyph_calc_rect(rcti *rect, GlyphBLF *g, const int x, const int
rect->ymax = rect->ymin - g->dims[1]; rect->ymax = rect->ymin - g->dims[1];
} }
static void blf_glyph_calc_rect_test(rcti *rect, GlyphBLF *g, const int x, const int y)
{
/* Intentionally check with `g->advance`, because this is the
* width used by BLF_width. This allows that the text slightly
* overlaps the clipping border to achieve better alignment. */
rect->xmin = x;
rect->xmax = rect->xmin + MIN2(ft_pix_to_int(g->advance_x), g->dims[0]);
rect->ymin = y;
rect->ymax = rect->ymin - g->dims[1];
}
static void blf_glyph_calc_rect_shadow( static void blf_glyph_calc_rect_shadow(
rcti *rect, GlyphBLF *g, const int x, const int y, FontBLF *font) rcti *rect, GlyphBLF *g, const int x, const int y, FontBLF *font)
{ {
@ -1213,9 +1202,10 @@ void blf_glyph_draw(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, const int x,
if (font->flags & BLF_CLIPPING) { if (font->flags & BLF_CLIPPING) {
rcti rect_test; rcti rect_test;
blf_glyph_calc_rect_test(&rect_test, g, x, y); rect_test.xmin = x + font->pos[0] + g->pos[0] + 1;
BLI_rcti_translate(&rect_test, font->pos[0], font->pos[1]); rect_test.xmax = rect_test.xmin + g->dims[0] - 2;
rect_test.ymin = y + font->pos[1];
rect_test.ymax = rect_test.ymin + g->pos[1];
if (!BLI_rcti_inside_rcti(&font->clip_rec, &rect_test)) { if (!BLI_rcti_inside_rcti(&font->clip_rec, &rect_test)) {
return; return;
} }

View File

@ -250,6 +250,88 @@ int BKE_object_data_transfer_dttype_to_srcdst_index(const int dtdata_type)
/* ********** */ /* ********** */
/**
* When transfering color attributes, also transfer the active color attribute string.
* If a match can't be found, use the first color layer that can be found (to ensure a valid string
* is set).
*/
static void data_transfer_mesh_attributes_transfer_active_color_string(
Mesh *mesh_dst, Mesh *mesh_src, const eAttrDomainMask mask_domain, const int data_type)
{
if (mesh_dst->active_color_attribute) {
return;
}
const char *active_color_src = BKE_id_attributes_active_color_name(&mesh_src->id);
if ((data_type == CD_PROP_COLOR) &&
!BKE_id_attribute_search(&mesh_src->id, active_color_src, CD_MASK_PROP_COLOR, ATTR_DOMAIN_MASK_COLOR)) {
return;
}
else if ((data_type == CD_PROP_BYTE_COLOR) &&
!BKE_id_attribute_search(&mesh_src->id, active_color_src, CD_MASK_PROP_BYTE_COLOR, ATTR_DOMAIN_MASK_COLOR)) {
return;
}
if ((data_type == CD_PROP_COLOR) &&
BKE_id_attribute_search(&mesh_dst->id, active_color_src, CD_MASK_PROP_COLOR, ATTR_DOMAIN_MASK_COLOR)) {
mesh_dst->active_color_attribute = BLI_strdup(active_color_src);
}
else if ((data_type == CD_PROP_BYTE_COLOR) &&
BKE_id_attribute_search(&mesh_dst->id, active_color_src, CD_MASK_PROP_BYTE_COLOR, ATTR_DOMAIN_MASK_COLOR)) {
mesh_dst->active_color_attribute = BLI_strdup(active_color_src);
}
else {
CustomDataLayer *first_color_layer = BKE_id_attribute_from_index(
&mesh_dst->id, 0, mask_domain, CD_MASK_COLOR_ALL);
if (first_color_layer != nullptr) {
mesh_dst->active_color_attribute = BLI_strdup(first_color_layer->name);
}
}
}
/**
* When transfering color attributes, also transfer the default color attribute string.
* If a match cant be found, use the first color layer that can be found (to ensure a valid string
* is set).
*/
static void data_transfer_mesh_attributes_transfer_default_color_string(
Mesh *mesh_dst, Mesh *mesh_src, const eAttrDomainMask mask_domain, const int data_type)
{
if (mesh_dst->default_color_attribute) {
return;
}
const char *default_color_src = BKE_id_attributes_default_color_name(&mesh_src->id);
if ((data_type == CD_PROP_COLOR) &&
!BKE_id_attribute_search(&mesh_src->id, default_color_src, CD_MASK_PROP_COLOR, ATTR_DOMAIN_MASK_COLOR)) {
return;
}
else if ((data_type == CD_PROP_BYTE_COLOR) &&
!BKE_id_attribute_search(&mesh_src->id, default_color_src, CD_MASK_PROP_BYTE_COLOR, ATTR_DOMAIN_MASK_COLOR)) {
return;
}
if ((data_type == CD_PROP_COLOR) &&
BKE_id_attribute_search(&mesh_dst->id, default_color_src, CD_MASK_PROP_COLOR, ATTR_DOMAIN_MASK_COLOR)) {
mesh_dst->default_color_attribute = BLI_strdup(default_color_src);
}
else if ((data_type == CD_PROP_BYTE_COLOR) &&
BKE_id_attribute_search(&mesh_dst->id, default_color_src, CD_MASK_PROP_BYTE_COLOR, ATTR_DOMAIN_MASK_COLOR)) {
mesh_dst->default_color_attribute = BLI_strdup(default_color_src);
}
else {
CustomDataLayer *first_color_layer = BKE_id_attribute_from_index(
&mesh_dst->id, 0, mask_domain, CD_MASK_COLOR_ALL);
if (first_color_layer != nullptr) {
mesh_dst->default_color_attribute = BLI_strdup(first_color_layer->name);
}
}
}
/* ********** */
/* Generic pre/post processing, only used by custom loop normals currently. */ /* Generic pre/post processing, only used by custom loop normals currently. */
static void data_transfer_dtdata_type_preprocess(Mesh *me_src, static void data_transfer_dtdata_type_preprocess(Mesh *me_src,
@ -1124,6 +1206,14 @@ void BKE_object_data_transfer_layout(struct Depsgraph *depsgraph,
fromlayers, fromlayers,
tolayers, tolayers,
nullptr); nullptr);
/* Make sure we have active/defaut color layers if none existed before.
* Use the active/defaut from src (if it was transferred), otherwise the first. */
if (ELEM(cddata_type, CD_PROP_COLOR, CD_PROP_BYTE_COLOR)) {
data_transfer_mesh_attributes_transfer_active_color_string(
me_dst, me_src, ATTR_DOMAIN_MASK_POINT, cddata_type);
data_transfer_mesh_attributes_transfer_default_color_string(
me_dst, me_src, ATTR_DOMAIN_MASK_POINT, cddata_type);
}
} }
if (DT_DATATYPE_IS_EDGE(dtdata_type)) { if (DT_DATATYPE_IS_EDGE(dtdata_type)) {
const int num_elem_dst = me_dst->totedge; const int num_elem_dst = me_dst->totedge;
@ -1164,6 +1254,14 @@ void BKE_object_data_transfer_layout(struct Depsgraph *depsgraph,
fromlayers, fromlayers,
tolayers, tolayers,
nullptr); nullptr);
/* Make sure we have active/defaut color layers if none existed before.
* Use the active/defaut from src (if it was transferred), otherwise the first. */
if (ELEM(cddata_type, CD_PROP_COLOR, CD_PROP_BYTE_COLOR)) {
data_transfer_mesh_attributes_transfer_active_color_string(
me_dst, me_src, ATTR_DOMAIN_MASK_CORNER, cddata_type);
data_transfer_mesh_attributes_transfer_default_color_string(
me_dst, me_src, ATTR_DOMAIN_MASK_CORNER, cddata_type);
}
} }
if (DT_DATATYPE_IS_POLY(dtdata_type)) { if (DT_DATATYPE_IS_POLY(dtdata_type)) {
const int num_elem_dst = me_dst->totpoly; const int num_elem_dst = me_dst->totpoly;

View File

@ -102,7 +102,7 @@ Closure closure_eval(ClosureTranslucent translucent)
} }
CLOSURE_EVAL_FUNCTION_DECLARE_1(GlossyBSDF, Glossy) CLOSURE_EVAL_FUNCTION_DECLARE_1(GlossyBSDF, Glossy)
Closure closure_eval(ClosureReflection reflection) Closure closure_eval(ClosureReflection reflection, const bool do_output_ssr)
{ {
/* Glue with the old system. */ /* Glue with the old system. */
CLOSURE_VARS_DECLARE_1(Glossy); CLOSURE_VARS_DECLARE_1(Glossy);
@ -113,12 +113,22 @@ Closure closure_eval(ClosureReflection reflection)
CLOSURE_EVAL_FUNCTION_1(GlossyBSDF, Glossy); CLOSURE_EVAL_FUNCTION_1(GlossyBSDF, Glossy);
Closure closure = CLOSURE_DEFAULT; Closure closure = CLOSURE_DEFAULT;
if (!output_ssr(reflection)) {
bool output_radiance = true;
if (do_output_ssr) {
output_radiance = !output_ssr(reflection);
}
if (output_radiance) {
closure.radiance += out_Glossy_0.radiance * reflection.color * reflection.weight; closure.radiance += out_Glossy_0.radiance * reflection.color * reflection.weight;
} }
return closure; return closure;
} }
Closure closure_eval(ClosureReflection reflection)
{
return closure_eval(reflection, true);
}
CLOSURE_EVAL_FUNCTION_DECLARE_1(RefractionBSDF, Refraction) CLOSURE_EVAL_FUNCTION_DECLARE_1(RefractionBSDF, Refraction)
Closure closure_eval(ClosureRefraction refraction) Closure closure_eval(ClosureRefraction refraction)
{ {
@ -155,6 +165,13 @@ Closure closure_eval(ClosureTransparency transparency)
CLOSURE_EVAL_FUNCTION_DECLARE_2(GlassBSDF, Glossy, Refraction) CLOSURE_EVAL_FUNCTION_DECLARE_2(GlassBSDF, Glossy, Refraction)
Closure closure_eval(ClosureReflection reflection, ClosureRefraction refraction) Closure closure_eval(ClosureReflection reflection, ClosureRefraction refraction)
{ {
#if defined(DO_SPLIT_CLOSURE_EVAL)
Closure closure = closure_eval(refraction);
Closure closure_reflection = closure_eval(reflection);
closure.radiance += closure_reflection.radiance;
return closure;
#else
/* Glue with the old system. */ /* Glue with the old system. */
CLOSURE_VARS_DECLARE_2(Glossy, Refraction); CLOSURE_VARS_DECLARE_2(Glossy, Refraction);
@ -172,12 +189,19 @@ Closure closure_eval(ClosureReflection reflection, ClosureRefraction refraction)
closure.radiance += out_Glossy_0.radiance * reflection.color * reflection.weight; closure.radiance += out_Glossy_0.radiance * reflection.color * reflection.weight;
} }
return closure; return closure;
#endif
} }
/* Dielectric BSDF */ /* Dielectric BSDF */
CLOSURE_EVAL_FUNCTION_DECLARE_2(DielectricBSDF, Diffuse, Glossy) CLOSURE_EVAL_FUNCTION_DECLARE_2(DielectricBSDF, Diffuse, Glossy)
Closure closure_eval(ClosureDiffuse diffuse, ClosureReflection reflection) Closure closure_eval(ClosureDiffuse diffuse, ClosureReflection reflection)
{ {
#if defined(DO_SPLIT_CLOSURE_EVAL)
Closure closure = closure_eval(diffuse);
Closure closure_reflection = closure_eval(reflection);
closure.radiance += closure_reflection.radiance;
return closure;
#else
/* Glue with the old system. */ /* Glue with the old system. */
CLOSURE_VARS_DECLARE_2(Diffuse, Glossy); CLOSURE_VARS_DECLARE_2(Diffuse, Glossy);
@ -198,6 +222,7 @@ Closure closure_eval(ClosureDiffuse diffuse, ClosureReflection reflection)
closure.radiance += out_Glossy_1.radiance * reflection.color * reflection.weight; closure.radiance += out_Glossy_1.radiance * reflection.color * reflection.weight;
} }
return closure; return closure;
#endif
} }
/* Specular BSDF */ /* Specular BSDF */
@ -206,6 +231,13 @@ Closure closure_eval(ClosureDiffuse diffuse,
ClosureReflection reflection, ClosureReflection reflection,
ClosureReflection clearcoat) ClosureReflection clearcoat)
{ {
#if defined(DO_SPLIT_CLOSURE_EVAL)
Closure closure = closure_eval(diffuse);
Closure closure_reflection = closure_eval(reflection);
Closure closure_clearcoat = closure_eval(clearcoat, false);
closure.radiance += closure_reflection.radiance + closure_clearcoat.radiance;
return closure;
#else
/* Glue with the old system. */ /* Glue with the old system. */
CLOSURE_VARS_DECLARE_3(Diffuse, Glossy, Glossy); CLOSURE_VARS_DECLARE_3(Diffuse, Glossy, Glossy);
@ -229,6 +261,7 @@ Closure closure_eval(ClosureDiffuse diffuse,
closure.radiance += out_Glossy_1.radiance * reflection.color * reflection.weight; closure.radiance += out_Glossy_1.radiance * reflection.color * reflection.weight;
} }
return closure; return closure;
#endif
} }
/* Principled BSDF */ /* Principled BSDF */
@ -238,6 +271,15 @@ Closure closure_eval(ClosureDiffuse diffuse,
ClosureReflection clearcoat, ClosureReflection clearcoat,
ClosureRefraction refraction) ClosureRefraction refraction)
{ {
#if defined(DO_SPLIT_CLOSURE_EVAL)
Closure closure = closure_eval(diffuse);
Closure closure_reflection = closure_eval(reflection);
Closure closure_clearcoat = closure_eval(clearcoat, false);
Closure closure_refraction = closure_eval(refraction);
closure.radiance += closure_reflection.radiance + closure_clearcoat.radiance +
closure_refraction.radiance;
return closure;
#else
/* Glue with the old system. */ /* Glue with the old system. */
CLOSURE_VARS_DECLARE_4(Diffuse, Glossy, Glossy, Refraction); CLOSURE_VARS_DECLARE_4(Diffuse, Glossy, Glossy, Refraction);
@ -263,11 +305,18 @@ Closure closure_eval(ClosureDiffuse diffuse,
closure.radiance += out_Glossy_1.radiance * reflection.color * reflection.weight; closure.radiance += out_Glossy_1.radiance * reflection.color * reflection.weight;
} }
return closure; return closure;
#endif
} }
CLOSURE_EVAL_FUNCTION_DECLARE_2(PrincipledBSDFMetalClearCoat, Glossy, Glossy) CLOSURE_EVAL_FUNCTION_DECLARE_2(PrincipledBSDFMetalClearCoat, Glossy, Glossy)
Closure closure_eval(ClosureReflection reflection, ClosureReflection clearcoat) Closure closure_eval(ClosureReflection reflection, ClosureReflection clearcoat)
{ {
#if defined(DO_SPLIT_CLOSURE_EVAL)
Closure closure = closure_eval(clearcoat);
Closure closure_reflection = closure_eval(reflection);
closure.radiance += closure_reflection.radiance;
return closure;
#else
/* Glue with the old system. */ /* Glue with the old system. */
CLOSURE_VARS_DECLARE_2(Glossy, Glossy); CLOSURE_VARS_DECLARE_2(Glossy, Glossy);
@ -284,6 +333,7 @@ Closure closure_eval(ClosureReflection reflection, ClosureReflection clearcoat)
closure.radiance += out_Glossy_0.radiance * reflection.color * reflection.weight; closure.radiance += out_Glossy_0.radiance * reflection.color * reflection.weight;
} }
return closure; return closure;
#endif
} }
/* Not supported for surface shaders. */ /* Not supported for surface shaders. */

View File

@ -16,6 +16,14 @@ typedef struct CommonUniformBlock CommonUniformBlock;
# endif # endif
#endif #endif
/* NOTE: AMD-based macOS platforms experience performance and correctness issues with EEVEE
* material closure evaluation. Using singular closure evaluation, rather than the compound
* function calls reduces register overflow, by limiting the simultaneous number of live
* registers used by the virtual GPU function stack. */
#if (defined(GPU_METAL) && defined(GPU_ATI))
# define DO_SPLIT_CLOSURE_EVAL 1
#endif
struct CommonUniformBlock { struct CommonUniformBlock {
mat4 pastViewProjectionMatrix; mat4 pastViewProjectionMatrix;
vec4 hizUvScale; /* To correct mip level texel misalignment */ vec4 hizUvScale; /* To correct mip level texel misalignment */

View File

@ -6532,6 +6532,8 @@ void UI_but_string_info_get(bContext *C, uiBut *but, ...)
va_list args; va_list args;
uiStringInfo *si; uiStringInfo *si;
PointerRNA *opptr = UI_but_operator_ptr_get(but);
const EnumPropertyItem *items = nullptr, *item = nullptr; const EnumPropertyItem *items = nullptr, *item = nullptr;
int totitems; int totitems;
bool free_items = false; bool free_items = false;
@ -6610,10 +6612,13 @@ void UI_but_string_info_get(bContext *C, uiBut *but, ...)
} }
else if (but->optype) { else if (but->optype) {
if (type == BUT_GET_RNA_LABEL) { if (type == BUT_GET_RNA_LABEL) {
tmp = BLI_strdup(WM_operatortype_name(but->optype, but->opptr)); tmp = BLI_strdup(WM_operatortype_name(but->optype, opptr));
} }
else { else {
tmp = WM_operatortype_description(C, but->optype, but->opptr); bContextStore *previous_ctx = CTX_store_get(C);
CTX_store_set(C, but->context);
tmp = WM_operatortype_description(C, but->optype, opptr);
CTX_store_set(C, previous_ctx);
} }
} }
else if (ELEM(but->type, UI_BTYPE_MENU, UI_BTYPE_PULLDOWN, UI_BTYPE_POPOVER)) { else if (ELEM(but->type, UI_BTYPE_MENU, UI_BTYPE_PULLDOWN, UI_BTYPE_POPOVER)) {
@ -6696,7 +6701,6 @@ void UI_but_string_info_get(bContext *C, uiBut *but, ...)
int(ui_but_value_get(but)); int(ui_but_value_get(but));
} }
else if (but->optype) { else if (but->optype) {
PointerRNA *opptr = UI_but_operator_ptr_get(but);
wmOperatorType *ot = but->optype; wmOperatorType *ot = but->optype;
/* So the context is passed to `itemf` functions. */ /* So the context is passed to `itemf` functions. */

View File

@ -970,9 +970,9 @@ static void min_distance_edit_draw(bContext *C, int /*x*/, int /*y*/, void *cust
const uint pos3d = GPU_vertformat_attr_add(format3d, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); const uint pos3d = GPU_vertformat_attr_add(format3d, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
const uint col3d = GPU_vertformat_attr_add(format3d, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); const uint col3d = GPU_vertformat_attr_add(format3d, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
const uint siz3d = GPU_vertformat_attr_add(format3d, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA); immBindBuiltinProgram(GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR);
immUniform1f("size", 4.0f);
immBegin(GPU_PRIM_POINTS, points_wo.size()); immBegin(GPU_PRIM_POINTS, points_wo.size());
float3 brush_origin_wo = math::transform_point(op_data.curves_to_world_mat, op_data.pos_cu); float3 brush_origin_wo = math::transform_point(op_data.curves_to_world_mat, op_data.pos_cu);
@ -990,6 +990,7 @@ static void min_distance_edit_draw(bContext *C, int /*x*/, int /*y*/, void *cust
const float dist_to_point_re = math::distance(pos_re, brush_origin_re); const float dist_to_point_re = math::distance(pos_re, brush_origin_re);
const float alpha = 1.0f - ((dist_to_point_re - dist_to_inner_border_re) / alpha_border_re); const float alpha = 1.0f - ((dist_to_point_re - dist_to_inner_border_re) / alpha_border_re);
immAttr1f(siz3d, 3.0f);
immAttr4f(col3d, 0.9f, 0.9f, 0.9f, alpha); immAttr4f(col3d, 0.9f, 0.9f, 0.9f, alpha);
immVertex3fv(pos3d, pos_wo); immVertex3fv(pos3d, pos_wo);
} }

View File

@ -456,6 +456,22 @@ static int node_add_group_asset_invoke(bContext *C, wmOperator *op, const wmEven
return OPERATOR_FINISHED; return OPERATOR_FINISHED;
} }
static char *node_add_group_asset_get_description(struct bContext *C,
struct wmOperatorType * /*op*/,
struct PointerRNA * /*values*/)
{
bool is_valid;
const AssetHandle handle = CTX_wm_asset_handle(C, &is_valid);
if (!is_valid) {
return nullptr;
}
const AssetMetaData &asset_data = *ED_asset_handle_get_metadata(&handle);
if (!asset_data.description) {
return nullptr;
}
return BLI_strdup(asset_data.description);
}
void NODE_OT_add_group_asset(wmOperatorType *ot) void NODE_OT_add_group_asset(wmOperatorType *ot)
{ {
ot->name = "Add Node Group Asset"; ot->name = "Add Node Group Asset";
@ -464,6 +480,7 @@ void NODE_OT_add_group_asset(wmOperatorType *ot)
ot->invoke = node_add_group_asset_invoke; ot->invoke = node_add_group_asset_invoke;
ot->poll = node_add_group_poll; ot->poll = node_add_group_poll;
ot->get_description = node_add_group_asset_get_description;
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
} }

View File

@ -1106,6 +1106,7 @@ static void draw_rotation_guide(const RegionView3D *rv3d)
/* -- draw rotation center -- */ /* -- draw rotation center -- */
immBindBuiltinProgram(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA); immBindBuiltinProgram(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA);
immUniform1f("size", 7.0f); immUniform1f("size", 7.0f);
immUniform4fv("color", float4(color));
immBegin(GPU_PRIM_POINTS, 1); immBegin(GPU_PRIM_POINTS, 1);
immAttr4ubv(col, color); immAttr4ubv(col, color);
immVertex3fv(pos, o); immVertex3fv(pos, o);

View File

@ -154,6 +154,12 @@ struct RealizeCurveInfo {
* curves. * curves.
*/ */
VArray<int> resolution; VArray<int> resolution;
/**
* The resolution attribute must be filled with the default value if it does not exist on some
* curves.
*/
Span<float> nurbs_weight;
}; };
/** Start indices in the final output curves data-block. */ /** Start indices in the final output curves data-block. */
@ -208,6 +214,7 @@ struct AllCurvesInfo {
bool create_handle_postion_attributes = false; bool create_handle_postion_attributes = false;
bool create_radius_attribute = false; bool create_radius_attribute = false;
bool create_resolution_attribute = false; bool create_resolution_attribute = false;
bool create_nurbs_weight_attribute = false;
}; };
/** Collects all tasks that need to be executed to realize all instances. */ /** Collects all tasks that need to be executed to realize all instances. */
@ -1159,6 +1166,7 @@ static OrderedAttributes gather_generic_curve_attributes_to_propagate(
attributes_to_propagate); attributes_to_propagate);
attributes_to_propagate.remove("position"); attributes_to_propagate.remove("position");
attributes_to_propagate.remove("radius"); attributes_to_propagate.remove("radius");
attributes_to_propagate.remove("nurbs_weight");
attributes_to_propagate.remove("resolution"); attributes_to_propagate.remove("resolution");
attributes_to_propagate.remove("handle_right"); attributes_to_propagate.remove("handle_right");
attributes_to_propagate.remove("handle_left"); attributes_to_propagate.remove("handle_left");
@ -1220,20 +1228,20 @@ static AllCurvesInfo preprocess_curves(const GeometrySet &geometry_set,
} }
} }
/* Retrieve the radius attribute, if it exists. */
if (attributes.contains("radius")) { if (attributes.contains("radius")) {
curve_info.radius = curve_info.radius =
attributes.lookup<float>("radius", ATTR_DOMAIN_POINT).get_internal_span(); attributes.lookup<float>("radius", ATTR_DOMAIN_POINT).get_internal_span();
info.create_radius_attribute = true; info.create_radius_attribute = true;
} }
if (attributes.contains("nurbs_weight")) {
/* Retrieve the resolution attribute, if it exists. */ curve_info.nurbs_weight =
attributes.lookup<float>("nurbs_weight", ATTR_DOMAIN_POINT).get_internal_span();
info.create_nurbs_weight_attribute = true;
}
curve_info.resolution = curves.resolution(); curve_info.resolution = curves.resolution();
if (attributes.contains("resolution")) { if (attributes.contains("resolution")) {
info.create_resolution_attribute = true; info.create_resolution_attribute = true;
} }
/* Retrieve handle position attributes, if they exist. */
if (attributes.contains("handle_right")) { if (attributes.contains("handle_right")) {
curve_info.handle_left = curve_info.handle_left =
attributes.lookup<float3>("handle_left", ATTR_DOMAIN_POINT).get_internal_span(); attributes.lookup<float3>("handle_left", ATTR_DOMAIN_POINT).get_internal_span();
@ -1255,6 +1263,7 @@ static void execute_realize_curve_task(const RealizeInstancesOptions &options,
MutableSpan<float3> all_handle_left, MutableSpan<float3> all_handle_left,
MutableSpan<float3> all_handle_right, MutableSpan<float3> all_handle_right,
MutableSpan<float> all_radii, MutableSpan<float> all_radii,
MutableSpan<float> all_nurbs_weights,
MutableSpan<int> all_resolutions) MutableSpan<int> all_resolutions)
{ {
const RealizeCurveInfo &curves_info = *task.curve_info; const RealizeCurveInfo &curves_info = *task.curve_info;
@ -1285,14 +1294,20 @@ static void execute_realize_curve_task(const RealizeInstancesOptions &options,
} }
} }
/* Copy radius attribute with 1.0 default if it doesn't exist. */ auto copy_point_span_with_default =
[&](const Span<float> src, MutableSpan<float> all_dst, const float value) {
if (src.is_empty()) {
all_dst.slice(dst_point_range).fill(value);
}
else {
all_dst.slice(dst_point_range).copy_from(src);
}
};
if (all_curves_info.create_radius_attribute) { if (all_curves_info.create_radius_attribute) {
if (curves_info.radius.is_empty()) { copy_point_span_with_default(curves_info.radius, all_radii, 1.0f);
all_radii.slice(dst_point_range).fill(1.0f); }
} if (all_curves_info.create_nurbs_weight_attribute) {
else { copy_point_span_with_default(curves_info.nurbs_weight, all_nurbs_weights, 1.0f);
all_radii.slice(dst_point_range).copy_from(curves_info.radius);
}
} }
if (all_curves_info.create_resolution_attribute) { if (all_curves_info.create_resolution_attribute) {
@ -1385,13 +1400,15 @@ static void execute_realize_curve_tasks(const RealizeInstancesOptions &options,
ATTR_DOMAIN_POINT); ATTR_DOMAIN_POINT);
} }
/* Prepare radius attribute if necessary. */
SpanAttributeWriter<float> radius; SpanAttributeWriter<float> radius;
if (all_curves_info.create_radius_attribute) { if (all_curves_info.create_radius_attribute) {
radius = dst_attributes.lookup_or_add_for_write_only_span<float>("radius", ATTR_DOMAIN_POINT); radius = dst_attributes.lookup_or_add_for_write_only_span<float>("radius", ATTR_DOMAIN_POINT);
} }
SpanAttributeWriter<float> nurbs_weight;
/* Prepare resolution attribute if necessary. */ if (all_curves_info.create_nurbs_weight_attribute) {
nurbs_weight = dst_attributes.lookup_or_add_for_write_only_span<float>("nurbs_weight",
ATTR_DOMAIN_POINT);
}
SpanAttributeWriter<int> resolution; SpanAttributeWriter<int> resolution;
if (all_curves_info.create_resolution_attribute) { if (all_curves_info.create_resolution_attribute) {
resolution = dst_attributes.lookup_or_add_for_write_only_span<int>("resolution", resolution = dst_attributes.lookup_or_add_for_write_only_span<int>("resolution",
@ -1412,6 +1429,7 @@ static void execute_realize_curve_tasks(const RealizeInstancesOptions &options,
handle_left.span, handle_left.span,
handle_right.span, handle_right.span,
radius.span, radius.span,
nurbs_weight.span,
resolution.span); resolution.span);
} }
}); });
@ -1432,6 +1450,7 @@ static void execute_realize_curve_tasks(const RealizeInstancesOptions &options,
point_ids.finish(); point_ids.finish();
radius.finish(); radius.finish();
resolution.finish(); resolution.finish();
nurbs_weight.finish();
handle_left.finish(); handle_left.finish();
handle_right.finish(); handle_right.finish();
} }

View File

@ -308,24 +308,23 @@ static bke::CurvesGeometry convert_curves_to_bezier(
dst_curves.resize(dst_offsets.last(), dst_curves.curves_num()); dst_curves.resize(dst_offsets.last(), dst_curves.curves_num());
const OffsetIndices dst_points_by_curve = dst_curves.points_by_curve(); const OffsetIndices dst_points_by_curve = dst_curves.points_by_curve();
bke::MutableAttributeAccessor dst_attributes = dst_curves.attributes_for_write();
MutableSpan<float3> dst_positions = dst_curves.positions_for_write(); MutableSpan<float3> dst_positions = dst_curves.positions_for_write();
MutableSpan<float3> dst_handles_l = dst_curves.handle_positions_left_for_write(); MutableSpan<float3> dst_handles_l = dst_curves.handle_positions_left_for_write();
MutableSpan<float3> dst_handles_r = dst_curves.handle_positions_right_for_write(); MutableSpan<float3> dst_handles_r = dst_curves.handle_positions_right_for_write();
MutableSpan<int8_t> dst_types_l = dst_curves.handle_types_left_for_write(); MutableSpan<int8_t> dst_types_l = dst_curves.handle_types_left_for_write();
MutableSpan<int8_t> dst_types_r = dst_curves.handle_types_right_for_write(); MutableSpan<int8_t> dst_types_r = dst_curves.handle_types_right_for_write();
MutableSpan<float> dst_weights = dst_curves.nurbs_weights_for_write(); Set<std::string> attributes_to_skip = {
bke::MutableAttributeAccessor dst_attributes = dst_curves.attributes_for_write(); "position", "handle_type_left", "handle_type_right", "handle_right", "handle_left"};
if (!dst_curves.has_curve_with_type(CURVE_TYPE_NURBS)) {
attributes_to_skip.add_new("nurbs_weight");
}
Vector<bke::AttributeTransferData> generic_attributes = bke::retrieve_attributes_for_transfer( Vector<bke::AttributeTransferData> generic_attributes = bke::retrieve_attributes_for_transfer(
src_attributes, src_attributes,
dst_attributes, dst_attributes,
ATTR_DOMAIN_MASK_POINT, ATTR_DOMAIN_MASK_POINT,
propagation_info, propagation_info,
{"position", attributes_to_skip);
"handle_type_left",
"handle_type_right",
"handle_right",
"handle_left",
"nurbs_weight"});
auto catmull_rom_to_bezier = [&](IndexMask selection) { auto catmull_rom_to_bezier = [&](IndexMask selection) {
bke::curves::fill_points<int8_t>( bke::curves::fill_points<int8_t>(
@ -396,7 +395,6 @@ static bke::CurvesGeometry convert_curves_to_bezier(
dst_points_by_curve, selection, BEZIER_HANDLE_ALIGN, dst_types_l); dst_points_by_curve, selection, BEZIER_HANDLE_ALIGN, dst_types_l);
bke::curves::fill_points<int8_t>( bke::curves::fill_points<int8_t>(
dst_points_by_curve, selection, BEZIER_HANDLE_ALIGN, dst_types_r); dst_points_by_curve, selection, BEZIER_HANDLE_ALIGN, dst_types_r);
bke::curves::fill_points<float>(dst_points_by_curve, selection, 0.0f, dst_weights);
threading::parallel_for(selection.index_range(), 64, [&](IndexRange range) { threading::parallel_for(selection.index_range(), 64, [&](IndexRange range) {
for (const int i : selection.slice(range)) { for (const int i : selection.slice(range)) {
@ -513,7 +511,7 @@ static bke::CurvesGeometry convert_curves_to_nurbs(
"nurbs_weight"}); "nurbs_weight"});
auto fill_weights_if_necessary = [&](const IndexMask selection) { auto fill_weights_if_necessary = [&](const IndexMask selection) {
if (!src_curves.nurbs_weights().is_empty()) { if (src_attributes.contains("nurbs_weight")) {
bke::curves::fill_points( bke::curves::fill_points(
dst_points_by_curve, selection, 1.0f, dst_curves.nurbs_weights_for_write()); dst_points_by_curve, selection, 1.0f, dst_curves.nurbs_weights_for_write());
} }

View File

@ -951,14 +951,16 @@ void GPU_material_compile(GPUMaterial *mat)
* As PSOs do not always match for default shaders, we limit warming for PSO * As PSOs do not always match for default shaders, we limit warming for PSO
* configurations to ensure compile time remains fast, as these first * configurations to ensure compile time remains fast, as these first
* entries will be the most commonly used PSOs. As not all PSOs are necessarily * entries will be the most commonly used PSOs. As not all PSOs are necessarily
* required immediately, this limit should remain low (1-3 at most). * required immediately, this limit should remain low (1-3 at most). */
* */
if (mat->default_mat != NULL && mat->default_mat != mat) { if (mat->default_mat != NULL && mat->default_mat != mat) {
if (mat->default_mat->pass != NULL) { if (mat->default_mat->pass != NULL) {
GPUShader *parent_sh = GPU_pass_shader_get(mat->default_mat->pass); GPUShader *parent_sh = GPU_pass_shader_get(mat->default_mat->pass);
if (parent_sh) { if (parent_sh) {
GPU_shader_set_parent(sh, parent_sh); /* Skip warming if cached pass is identical to the default material. */
GPU_shader_warm_cache(sh, 1); if (mat->default_mat->pass != mat->pass && parent_sh != sh) {
GPU_shader_set_parent(sh, parent_sh);
GPU_shader_warm_cache(sh, 1);
}
} }
} }
} }

View File

@ -225,7 +225,7 @@ static void test_gpu_shader_compute_ssbo()
EXPECT_NE(shader, nullptr); EXPECT_NE(shader, nullptr);
GPU_shader_bind(shader); GPU_shader_bind(shader);
/* Construct IBO. */ /* Construct SSBO. */
GPUStorageBuf *ssbo = GPU_storagebuf_create_ex( GPUStorageBuf *ssbo = GPU_storagebuf_create_ex(
SIZE * sizeof(uint32_t), nullptr, GPU_USAGE_DEVICE_ONLY, __func__); SIZE * sizeof(uint32_t), nullptr, GPU_USAGE_DEVICE_ONLY, __func__);
GPU_storagebuf_bind(ssbo, GPU_shader_get_ssbo_binding(shader, "data_out")); GPU_storagebuf_bind(ssbo, GPU_shader_get_ssbo_binding(shader, "data_out"));

View File

@ -119,6 +119,10 @@ void VKDescriptorSet::update(VkDevice vk_device)
descriptor_writes.append(write_descriptor); descriptor_writes.append(write_descriptor);
} }
BLI_assert_msg(image_infos.size() + buffer_infos.size() == descriptor_writes.size(),
"Not all changes have been converted to a write descriptor. Check "
"`Binding::is_buffer` and `Binding::is_image`.");
vkUpdateDescriptorSets( vkUpdateDescriptorSets(
vk_device, descriptor_writes.size(), descriptor_writes.data(), 0, nullptr); vk_device, descriptor_writes.size(), descriptor_writes.data(), 0, nullptr);

View File

@ -15,10 +15,11 @@
#include "vk_common.hh" #include "vk_common.hh"
namespace blender::gpu { namespace blender::gpu {
class VKStorageBuffer;
class VKVertexBuffer;
class VKIndexBuffer; class VKIndexBuffer;
class VKShaderInterface;
class VKStorageBuffer;
class VKTexture; class VKTexture;
class VKVertexBuffer;
/** /**
* In vulkan shader resources (images and buffers) are grouped in descriptor sets. * In vulkan shader resources (images and buffers) are grouped in descriptor sets.
@ -26,7 +27,7 @@ class VKTexture;
* The resources inside a descriptor set can be updated and bound per set. * The resources inside a descriptor set can be updated and bound per set.
* *
* Currently Blender only supports a single descriptor set per shader, but it is planned to be able * Currently Blender only supports a single descriptor set per shader, but it is planned to be able
* to use 2 descriptor sets per shader. Only for each #blender::gpu::shader::Frequency. * to use 2 descriptor sets per shader. One for each #blender::gpu::shader::Frequency.
*/ */
class VKDescriptorSet : NonCopyable { class VKDescriptorSet : NonCopyable {
struct Binding; struct Binding;
@ -50,9 +51,12 @@ class VKDescriptorSet : NonCopyable {
*/ */
uint32_t binding; uint32_t binding;
Location() = default; Location(uint32_t binding) : binding(binding)
{
}
public: public:
Location() = default;
Location(const ShaderInput *shader_input) : binding(shader_input->location) Location(const ShaderInput *shader_input) : binding(shader_input->location)
{ {
} }
@ -68,6 +72,7 @@ class VKDescriptorSet : NonCopyable {
} }
friend struct Binding; friend struct Binding;
friend class VKShaderInterface;
}; };
private: private:

View File

@ -24,9 +24,9 @@ void VKIndexBuffer::bind_as_ssbo(uint binding)
VKShader *shader = static_cast<VKShader *>(context.shader); VKShader *shader = static_cast<VKShader *>(context.shader);
const VKShaderInterface &shader_interface = shader->interface_get(); const VKShaderInterface &shader_interface = shader->interface_get();
const ShaderInput *shader_input = shader_interface.shader_input_get( const VKDescriptorSet::Location location = shader_interface.descriptor_set_location(
shader::ShaderCreateInfo::Resource::BindType::STORAGE_BUFFER, binding); shader::ShaderCreateInfo::Resource::BindType::STORAGE_BUFFER, binding);
shader->pipeline_get().descriptor_set_get().bind_as_ssbo(*this, shader_input); shader->pipeline_get().descriptor_set_get().bind_as_ssbo(*this, location);
} }
void VKIndexBuffer::read(uint32_t *data) const void VKIndexBuffer::read(uint32_t *data) const

View File

@ -326,10 +326,10 @@ static std::ostream &print_qualifier(std::ostream &os, const Qualifier &qualifie
} }
static void print_resource(std::ostream &os, static void print_resource(std::ostream &os,
const ShaderInput &shader_input, const VKDescriptorSet::Location location,
const ShaderCreateInfo::Resource &res) const ShaderCreateInfo::Resource &res)
{ {
os << "layout(binding = " << shader_input.location; os << "layout(binding = " << static_cast<uint32_t>(location);
if (res.bind_type == ShaderCreateInfo::Resource::BindType::IMAGE) { if (res.bind_type == ShaderCreateInfo::Resource::BindType::IMAGE) {
os << ", " << to_string(res.image.format); os << ", " << to_string(res.image.format);
} }
@ -379,12 +379,8 @@ static void print_resource(std::ostream &os,
const VKShaderInterface &shader_interface, const VKShaderInterface &shader_interface,
const ShaderCreateInfo::Resource &res) const ShaderCreateInfo::Resource &res)
{ {
const ShaderInput *shader_input = shader_interface.shader_input_get(res); const VKDescriptorSet::Location location = shader_interface.descriptor_set_location(res);
if (shader_input == nullptr) { print_resource(os, location, res);
BLI_assert_msg(shader_input, "Cannot find shader input for resource");
return;
}
print_resource(os, *shader_input, res);
} }
static void print_resource_alias(std::ostream &os, const ShaderCreateInfo::Resource &res) static void print_resource_alias(std::ostream &os, const ShaderCreateInfo::Resource &res)
@ -860,10 +856,10 @@ static VkDescriptorType descriptor_type(const shader::ShaderCreateInfo::Resource
} }
static VkDescriptorSetLayoutBinding create_descriptor_set_layout_binding( static VkDescriptorSetLayoutBinding create_descriptor_set_layout_binding(
const ShaderInput &shader_input, const shader::ShaderCreateInfo::Resource &resource) const VKDescriptorSet::Location location, const shader::ShaderCreateInfo::Resource &resource)
{ {
VkDescriptorSetLayoutBinding binding = {}; VkDescriptorSetLayoutBinding binding = {};
binding.binding = shader_input.location; binding.binding = location;
binding.descriptorType = descriptor_type(resource); binding.descriptorType = descriptor_type(resource);
binding.descriptorCount = 1; binding.descriptorCount = 1;
binding.stageFlags = VK_SHADER_STAGE_ALL; binding.stageFlags = VK_SHADER_STAGE_ALL;
@ -878,13 +874,8 @@ static void add_descriptor_set_layout_bindings(
Vector<VkDescriptorSetLayoutBinding> &r_bindings) Vector<VkDescriptorSetLayoutBinding> &r_bindings)
{ {
for (const shader::ShaderCreateInfo::Resource &resource : resources) { for (const shader::ShaderCreateInfo::Resource &resource : resources) {
const ShaderInput *shader_input = interface.shader_input_get(resource); const VKDescriptorSet::Location location = interface.descriptor_set_location(resource);
if (shader_input == nullptr) { r_bindings.append(create_descriptor_set_layout_binding(location, resource));
BLI_assert_msg(shader_input, "Cannot find shader input for resource.");
continue;
}
r_bindings.append(create_descriptor_set_layout_binding(*shader_input, resource));
} }
} }
@ -1033,12 +1024,6 @@ std::string VKShader::vertex_interface_declare(const shader::ShaderCreateInfo &i
ss << "layout(location = " << attr.index << ") "; ss << "layout(location = " << attr.index << ") ";
ss << "in " << to_string(attr.type) << " " << attr.name << ";\n"; ss << "in " << to_string(attr.type) << " " << attr.name << ";\n";
} }
/* NOTE(D4490): Fix a bug where shader without any vertex attributes do not behave correctly.
*/
if (GPU_type_matches_ex(GPU_DEVICE_APPLE, GPU_OS_MAC, GPU_DRIVER_ANY, GPU_BACKEND_OPENGL) &&
info.vertex_inputs_.is_empty()) {
ss << "in float gpu_dummy_workaround;\n";
}
ss << "\n/* Interfaces. */\n"; ss << "\n/* Interfaces. */\n";
int location = 0; int location = 0;
for (const StageInterfaceInfo *iface : info.vertex_out_interfaces_) { for (const StageInterfaceInfo *iface : info.vertex_out_interfaces_) {

View File

@ -41,7 +41,7 @@ void VKShaderInterface::init(const shader::ShaderCreateInfo &info)
} }
} }
/* Make sure that the image slots don't overlap with the sampler slots.*/ /* Make sure that the image slots don't overlap with the sampler slots.*/
image_offset_ += 1; image_offset_++;
int32_t input_tot_len = ubo_len_ + uniform_len_ + ssbo_len_; int32_t input_tot_len = ubo_len_ + uniform_len_ + ssbo_len_;
inputs_ = static_cast<ShaderInput *>( inputs_ = static_cast<ShaderInput *>(
@ -51,14 +51,11 @@ void VKShaderInterface::init(const shader::ShaderCreateInfo &info)
name_buffer_ = (char *)MEM_mallocN(info.interface_names_size_, "name_buffer"); name_buffer_ = (char *)MEM_mallocN(info.interface_names_size_, "name_buffer");
uint32_t name_buffer_offset = 0; uint32_t name_buffer_offset = 0;
int location = 0;
/* Uniform blocks */ /* Uniform blocks */
for (const ShaderCreateInfo::Resource &res : all_resources) { for (const ShaderCreateInfo::Resource &res : all_resources) {
if (res.bind_type == ShaderCreateInfo::Resource::BindType::UNIFORM_BUFFER) { if (res.bind_type == ShaderCreateInfo::Resource::BindType::UNIFORM_BUFFER) {
copy_input_name(input, res.image.name, name_buffer_, name_buffer_offset); copy_input_name(input, res.image.name, name_buffer_, name_buffer_offset);
input->location = location++; input->location = input->binding = res.slot;
input->binding = res.slot;
input++; input++;
} }
} }
@ -67,14 +64,12 @@ void VKShaderInterface::init(const shader::ShaderCreateInfo &info)
for (const ShaderCreateInfo::Resource &res : all_resources) { for (const ShaderCreateInfo::Resource &res : all_resources) {
if (res.bind_type == ShaderCreateInfo::Resource::BindType::SAMPLER) { if (res.bind_type == ShaderCreateInfo::Resource::BindType::SAMPLER) {
copy_input_name(input, res.sampler.name, name_buffer_, name_buffer_offset); copy_input_name(input, res.sampler.name, name_buffer_, name_buffer_offset);
input->location = location++; input->location = input->binding = res.slot;
input->binding = res.slot;
input++; input++;
} }
else if (res.bind_type == ShaderCreateInfo::Resource::BindType::IMAGE) { else if (res.bind_type == ShaderCreateInfo::Resource::BindType::IMAGE) {
copy_input_name(input, res.image.name, name_buffer_, name_buffer_offset); copy_input_name(input, res.image.name, name_buffer_, name_buffer_offset);
input->location = location++; input->location = input->binding = res.slot + image_offset_;
input->binding = res.slot + image_offset_;
input++; input++;
} }
} }
@ -83,13 +78,57 @@ void VKShaderInterface::init(const shader::ShaderCreateInfo &info)
for (const ShaderCreateInfo::Resource &res : all_resources) { for (const ShaderCreateInfo::Resource &res : all_resources) {
if (res.bind_type == ShaderCreateInfo::Resource::BindType::STORAGE_BUFFER) { if (res.bind_type == ShaderCreateInfo::Resource::BindType::STORAGE_BUFFER) {
copy_input_name(input, res.storagebuf.name, name_buffer_, name_buffer_offset); copy_input_name(input, res.storagebuf.name, name_buffer_, name_buffer_offset);
input->location = location++; input->location = input->binding = res.slot;
input->binding = res.slot;
input++; input++;
} }
} }
sort_inputs(); sort_inputs();
/* Determine the descriptor set locations after the inputs have been sorted.*/
descriptor_set_locations_ = Array<VKDescriptorSet::Location>(input_tot_len);
uint32_t descriptor_set_location = 0;
for (ShaderCreateInfo::Resource &res : all_resources) {
const ShaderInput *input = shader_input_get(res);
descriptor_set_location_update(input, descriptor_set_location++);
}
}
static int32_t shader_input_index(const ShaderInput *shader_inputs,
const ShaderInput *shader_input)
{
int32_t index = (shader_input - shader_inputs);
return index;
}
void VKShaderInterface::descriptor_set_location_update(const ShaderInput *shader_input,
const VKDescriptorSet::Location location)
{
int32_t index = shader_input_index(inputs_, shader_input);
descriptor_set_locations_[index] = location;
}
const VKDescriptorSet::Location VKShaderInterface::descriptor_set_location(
const ShaderInput *shader_input) const
{
int32_t index = shader_input_index(inputs_, shader_input);
return descriptor_set_locations_[index];
}
const VKDescriptorSet::Location VKShaderInterface::descriptor_set_location(
const shader::ShaderCreateInfo::Resource &resource) const
{
const ShaderInput *shader_input = shader_input_get(resource);
BLI_assert(shader_input);
return descriptor_set_location(shader_input);
}
const VKDescriptorSet::Location VKShaderInterface::descriptor_set_location(
const shader::ShaderCreateInfo::Resource::BindType &bind_type, int binding) const
{
const ShaderInput *shader_input = shader_input_get(bind_type, binding);
BLI_assert(shader_input);
return descriptor_set_location(shader_input);
} }
const ShaderInput *VKShaderInterface::shader_input_get( const ShaderInput *VKShaderInterface::shader_input_get(

View File

@ -7,9 +7,13 @@
#pragma once #pragma once
#include "BLI_array.hh"
#include "gpu_shader_create_info.hh" #include "gpu_shader_create_info.hh"
#include "gpu_shader_interface.hh" #include "gpu_shader_interface.hh"
#include "vk_descriptor_set.hh"
namespace blender::gpu { namespace blender::gpu {
class VKShaderInterface : public ShaderInterface { class VKShaderInterface : public ShaderInterface {
private: private:
@ -21,11 +25,19 @@ class VKShaderInterface : public ShaderInterface {
* overlapping. * overlapping.
*/ */
uint32_t image_offset_ = 0; uint32_t image_offset_ = 0;
Array<VKDescriptorSet::Location> descriptor_set_locations_;
public: public:
VKShaderInterface() = default; VKShaderInterface() = default;
void init(const shader::ShaderCreateInfo &info); void init(const shader::ShaderCreateInfo &info);
const VKDescriptorSet::Location descriptor_set_location(
const shader::ShaderCreateInfo::Resource &resource) const;
const VKDescriptorSet::Location descriptor_set_location(
const shader::ShaderCreateInfo::Resource::BindType &bind_type, int binding) const;
private:
/** /**
* Retrieve the shader input for the given resource. * Retrieve the shader input for the given resource.
* *
@ -35,5 +47,9 @@ class VKShaderInterface : public ShaderInterface {
const ShaderInput *shader_input_get(const shader::ShaderCreateInfo::Resource &resource) const; const ShaderInput *shader_input_get(const shader::ShaderCreateInfo::Resource &resource) const;
const ShaderInput *shader_input_get( const ShaderInput *shader_input_get(
const shader::ShaderCreateInfo::Resource::BindType &bind_type, int binding) const; const shader::ShaderCreateInfo::Resource::BindType &bind_type, int binding) const;
const VKDescriptorSet::Location descriptor_set_location(const ShaderInput *shader_input) const;
void descriptor_set_location_update(const ShaderInput *shader_input,
const VKDescriptorSet::Location location);
}; };
} // namespace blender::gpu } // namespace blender::gpu

View File

@ -34,9 +34,9 @@ void VKStorageBuffer::bind(int slot)
} }
VKShader *shader = static_cast<VKShader *>(context.shader); VKShader *shader = static_cast<VKShader *>(context.shader);
const VKShaderInterface &shader_interface = shader->interface_get(); const VKShaderInterface &shader_interface = shader->interface_get();
const ShaderInput *shader_input = shader_interface.shader_input_get( const VKDescriptorSet::Location location = shader_interface.descriptor_set_location(
shader::ShaderCreateInfo::Resource::BindType::STORAGE_BUFFER, slot); shader::ShaderCreateInfo::Resource::BindType::STORAGE_BUFFER, slot);
shader->pipeline_get().descriptor_set_get().bind(*this, shader_input); shader->pipeline_get().descriptor_set_get().bind(*this, location);
} }
void VKStorageBuffer::unbind() void VKStorageBuffer::unbind()

View File

@ -227,8 +227,9 @@ void VKTexture::image_bind(int binding)
} }
VKContext &context = *VKContext::get(); VKContext &context = *VKContext::get();
VKShader *shader = static_cast<VKShader *>(context.shader); VKShader *shader = static_cast<VKShader *>(context.shader);
VKDescriptorSet::Location location(shader->interface_get().shader_input_get( const VKShaderInterface &shader_interface = shader->interface_get();
shader::ShaderCreateInfo::Resource::BindType::IMAGE, binding)); const VKDescriptorSet::Location location = shader_interface.descriptor_set_location(
shader::ShaderCreateInfo::Resource::BindType::IMAGE, binding);
shader->pipeline_get().descriptor_set_get().image_bind(*this, location); shader->pipeline_get().descriptor_set_get().image_bind(*this, location);
} }

View File

@ -27,9 +27,9 @@ void VKVertexBuffer::bind_as_ssbo(uint binding)
VKShader *shader = static_cast<VKShader *>(context.shader); VKShader *shader = static_cast<VKShader *>(context.shader);
const VKShaderInterface &shader_interface = shader->interface_get(); const VKShaderInterface &shader_interface = shader->interface_get();
const ShaderInput *shader_input = shader_interface.shader_input_get( const VKDescriptorSet::Location location = shader_interface.descriptor_set_location(
shader::ShaderCreateInfo::Resource::BindType::STORAGE_BUFFER, binding); shader::ShaderCreateInfo::Resource::BindType::STORAGE_BUFFER, binding);
shader->pipeline_get().descriptor_set_get().bind_as_ssbo(*this, shader_input); shader->pipeline_get().descriptor_set_get().bind_as_ssbo(*this, location);
} }
void VKVertexBuffer::bind_as_texture(uint /*binding*/) void VKVertexBuffer::bind_as_texture(uint /*binding*/)

View File

@ -491,6 +491,8 @@ void MeshImporter::allocate_poly_data(COLLADAFW::Mesh *collada_mesh, Mesh *me)
} }
BKE_id_attributes_active_color_set( BKE_id_attributes_active_color_set(
&me->id, CustomData_get_layer_name(&me->ldata, CD_PROP_BYTE_COLOR, 0)); &me->id, CustomData_get_layer_name(&me->ldata, CD_PROP_BYTE_COLOR, 0));
BKE_id_attributes_default_color_set(
&me->id, CustomData_get_layer_name(&me->ldata, CD_PROP_BYTE_COLOR, 0));
} }
} }
} }

View File

@ -475,12 +475,19 @@ static USDPrimReader *get_usd_reader(CacheReader *reader,
return usd_reader; return usd_reader;
} }
USDMeshReadParams create_mesh_read_params(const double motion_sample_time, const int read_flags)
{
USDMeshReadParams params = {};
params.motion_sample_time = motion_sample_time;
params.read_flags = read_flags;
return params;
}
struct Mesh *USD_read_mesh(struct CacheReader *reader, struct Mesh *USD_read_mesh(struct CacheReader *reader,
struct Object *ob, struct Object *ob,
struct Mesh *existing_mesh, struct Mesh *existing_mesh,
const double time, const USDMeshReadParams params,
const char **err_str, const char **err_str)
const int read_flag)
{ {
USDGeomReader *usd_reader = dynamic_cast<USDGeomReader *>(get_usd_reader(reader, ob, err_str)); USDGeomReader *usd_reader = dynamic_cast<USDGeomReader *>(get_usd_reader(reader, ob, err_str));
@ -488,7 +495,7 @@ struct Mesh *USD_read_mesh(struct CacheReader *reader,
return nullptr; return nullptr;
} }
return usd_reader->read_mesh(existing_mesh, time, read_flag, err_str); return usd_reader->read_mesh(existing_mesh, params, err_str);
} }
bool USD_mesh_topology_changed(CacheReader *reader, bool USD_mesh_topology_changed(CacheReader *reader,

View File

@ -162,8 +162,7 @@ void USDCurvesReader::read_curve_sample(Curve *cu, const double motionSampleTime
} }
Mesh *USDCurvesReader::read_mesh(struct Mesh *existing_mesh, Mesh *USDCurvesReader::read_mesh(struct Mesh *existing_mesh,
const double motionSampleTime, const USDMeshReadParams params,
const int /* read_flag */,
const char ** /* err_str */) const char ** /* err_str */)
{ {
if (!curve_prim_) { if (!curve_prim_) {
@ -176,11 +175,11 @@ Mesh *USDCurvesReader::read_mesh(struct Mesh *existing_mesh,
pxr::VtIntArray usdCounts; pxr::VtIntArray usdCounts;
vertexAttr.Get(&usdCounts, motionSampleTime); vertexAttr.Get(&usdCounts, params.motion_sample_time);
int num_subcurves = usdCounts.size(); int num_subcurves = usdCounts.size();
pxr::VtVec3fArray usdPoints; pxr::VtVec3fArray usdPoints;
pointsAttr.Get(&usdPoints, motionSampleTime); pointsAttr.Get(&usdPoints, params.motion_sample_time);
int vertex_idx = 0; int vertex_idx = 0;
int curve_idx; int curve_idx;
@ -204,7 +203,7 @@ Mesh *USDCurvesReader::read_mesh(struct Mesh *existing_mesh,
if (!same_topology) { if (!same_topology) {
BKE_nurbList_free(&curve->nurb); BKE_nurbList_free(&curve->nurb);
read_curve_sample(curve, motionSampleTime); read_curve_sample(curve, params.motion_sample_time);
} }
else { else {
Nurb *nurbs = static_cast<Nurb *>(curve->nurb.first); Nurb *nurbs = static_cast<Nurb *>(curve->nurb.first);

View File

@ -36,8 +36,7 @@ class USDCurvesReader : public USDGeomReader {
void read_curve_sample(Curve *cu, double motionSampleTime); void read_curve_sample(Curve *cu, double motionSampleTime);
Mesh *read_mesh(struct Mesh *existing_mesh, Mesh *read_mesh(struct Mesh *existing_mesh,
double motionSampleTime, USDMeshReadParams params,
int read_flag,
const char **err_str) override; const char **err_str) override;
}; };

View File

@ -20,8 +20,7 @@ class USDGeomReader : public USDXformReader {
} }
virtual Mesh *read_mesh(struct Mesh *existing_mesh, virtual Mesh *read_mesh(struct Mesh *existing_mesh,
double motionSampleTime, USDMeshReadParams params,
int read_flag,
const char **err_str) = 0; const char **err_str) = 0;
virtual bool topology_changed(const Mesh * /* existing_mesh */, double /* motionSampleTime */) virtual bool topology_changed(const Mesh * /* existing_mesh */, double /* motionSampleTime */)

View File

@ -194,8 +194,9 @@ void USDMeshReader::read_object_data(Main *bmain, const double motionSampleTime)
Mesh *mesh = (Mesh *)object_->data; Mesh *mesh = (Mesh *)object_->data;
is_initial_load_ = true; is_initial_load_ = true;
Mesh *read_mesh = this->read_mesh( const USDMeshReadParams params = create_mesh_read_params(motionSampleTime, import_params_.mesh_read_flag);
mesh, motionSampleTime, import_params_.mesh_read_flag, nullptr);
Mesh *read_mesh = this->read_mesh(mesh, params, nullptr);
is_initial_load_ = false; is_initial_load_ = false;
if (read_mesh != mesh) { if (read_mesh != mesh) {
@ -222,7 +223,7 @@ void USDMeshReader::read_object_data(Main *bmain, const double motionSampleTime)
} }
USDXformReader::read_object_data(bmain, motionSampleTime); USDXformReader::read_object_data(bmain, motionSampleTime);
} } // namespace blender::io::usd
bool USDMeshReader::valid() const bool USDMeshReader::valid() const
{ {
@ -767,8 +768,7 @@ void USDMeshReader::readFaceSetsSample(Main *bmain, Mesh *mesh, const double mot
} }
Mesh *USDMeshReader::read_mesh(Mesh *existing_mesh, Mesh *USDMeshReader::read_mesh(Mesh *existing_mesh,
const double motionSampleTime, const USDMeshReadParams params,
const int read_flag,
const char ** /* err_str */) const char ** /* err_str */)
{ {
if (!mesh_prim_) { if (!mesh_prim_) {
@ -785,7 +785,7 @@ Mesh *USDMeshReader::read_mesh(Mesh *existing_mesh,
std::vector<pxr::TfToken> uv_tokens; std::vector<pxr::TfToken> uv_tokens;
/* Currently we only handle UV primvars. */ /* Currently we only handle UV primvars. */
if (read_flag & MOD_MESHSEQ_READ_UV) { if (params.read_flags & MOD_MESHSEQ_READ_UV) {
std::vector<pxr::UsdGeomPrimvar> primvars = primvarsAPI.GetPrimvars(); std::vector<pxr::UsdGeomPrimvar> primvars = primvarsAPI.GetPrimvars();
@ -838,9 +838,9 @@ Mesh *USDMeshReader::read_mesh(Mesh *existing_mesh,
* the topology is consistent, as in the Alembic importer. */ * the topology is consistent, as in the Alembic importer. */
ImportSettings settings; ImportSettings settings;
settings.read_flag |= read_flag; settings.read_flag |= params.read_flags;
if (topology_changed(existing_mesh, motionSampleTime)) { if (topology_changed(existing_mesh, params.motion_sample_time)) {
new_mesh = true; new_mesh = true;
active_mesh = BKE_mesh_new_nomain_from_template( active_mesh = BKE_mesh_new_nomain_from_template(
existing_mesh, positions_.size(), 0, 0, face_indices_.size(), face_counts_.size()); existing_mesh, positions_.size(), 0, 0, face_indices_.size(), face_counts_.size());
@ -850,7 +850,7 @@ Mesh *USDMeshReader::read_mesh(Mesh *existing_mesh,
} }
} }
read_mesh_sample(&settings, active_mesh, motionSampleTime, new_mesh || is_initial_load_); read_mesh_sample(&settings, active_mesh, params.motion_sample_time, new_mesh || is_initial_load_);
if (new_mesh) { if (new_mesh) {
/* Here we assume that the number of materials doesn't change, i.e. that /* Here we assume that the number of materials doesn't change, i.e. that
@ -862,7 +862,7 @@ Mesh *USDMeshReader::read_mesh(Mesh *existing_mesh,
bke::MutableAttributeAccessor attributes = active_mesh->attributes_for_write(); bke::MutableAttributeAccessor attributes = active_mesh->attributes_for_write();
bke::SpanAttributeWriter<int> material_indices = bke::SpanAttributeWriter<int> material_indices =
attributes.lookup_or_add_for_write_span<int>("material_index", ATTR_DOMAIN_FACE); attributes.lookup_or_add_for_write_span<int>("material_index", ATTR_DOMAIN_FACE);
assign_facesets_to_material_indices(motionSampleTime, material_indices.span, &mat_map); assign_facesets_to_material_indices(params.motion_sample_time, material_indices.span, &mat_map);
material_indices.finish(); material_indices.finish();
} }
} }

View File

@ -49,8 +49,7 @@ class USDMeshReader : public USDGeomReader {
void read_object_data(Main *bmain, double motionSampleTime) override; void read_object_data(Main *bmain, double motionSampleTime) override;
struct Mesh *read_mesh(struct Mesh *existing_mesh, struct Mesh *read_mesh(struct Mesh *existing_mesh,
double motionSampleTime, USDMeshReadParams params,
int read_flag,
const char **err_str) override; const char **err_str) override;
bool topology_changed(const Mesh *existing_mesh, double motionSampleTime) override; bool topology_changed(const Mesh *existing_mesh, double motionSampleTime) override;

View File

@ -165,8 +165,7 @@ void USDNurbsReader::read_curve_sample(Curve *cu, const double motionSampleTime)
} }
Mesh *USDNurbsReader::read_mesh(struct Mesh * /* existing_mesh */, Mesh *USDNurbsReader::read_mesh(struct Mesh * /* existing_mesh */,
const double motionSampleTime, const USDMeshReadParams params,
const int /* read_flag */,
const char ** /* err_str */) const char ** /* err_str */)
{ {
pxr::UsdGeomCurves curve_prim_(prim_); pxr::UsdGeomCurves curve_prim_(prim_);
@ -177,11 +176,11 @@ Mesh *USDNurbsReader::read_mesh(struct Mesh * /* existing_mesh */,
pxr::VtIntArray usdCounts; pxr::VtIntArray usdCounts;
vertexAttr.Get(&usdCounts, motionSampleTime); vertexAttr.Get(&usdCounts, params.motion_sample_time);
int num_subcurves = usdCounts.size(); int num_subcurves = usdCounts.size();
pxr::VtVec3fArray usdPoints; pxr::VtVec3fArray usdPoints;
pointsAttr.Get(&usdPoints, motionSampleTime); pointsAttr.Get(&usdPoints, params.motion_sample_time);
int vertex_idx = 0; int vertex_idx = 0;
int curve_idx; int curve_idx;
@ -205,7 +204,7 @@ Mesh *USDNurbsReader::read_mesh(struct Mesh * /* existing_mesh */,
if (!same_topology) { if (!same_topology) {
BKE_nurbList_free(&curve->nurb); BKE_nurbList_free(&curve->nurb);
read_curve_sample(curve, motionSampleTime); read_curve_sample(curve, params.motion_sample_time);
} }
else { else {
Nurb *nurbs = static_cast<Nurb *>(curve->nurb.first); Nurb *nurbs = static_cast<Nurb *>(curve->nurb.first);

View File

@ -36,8 +36,7 @@ class USDNurbsReader : public USDGeomReader {
void read_curve_sample(Curve *cu, double motionSampleTime); void read_curve_sample(Curve *cu, double motionSampleTime);
Mesh *read_mesh(struct Mesh *existing_mesh, Mesh *read_mesh(struct Mesh *existing_mesh,
double motionSampleTime, USDMeshReadParams params,
int read_flag,
const char **err_str) override; const char **err_str) override;
}; };

View File

@ -45,9 +45,10 @@ void USDShapeReader::create_object(Main *bmain, double /*motionSampleTime*/)
void USDShapeReader::read_object_data(Main *bmain, double motionSampleTime) void USDShapeReader::read_object_data(Main *bmain, double motionSampleTime)
{ {
const USDMeshReadParams params = create_mesh_read_params(motionSampleTime,
import_params_.mesh_read_flag);
Mesh *mesh = (Mesh *)object_->data; Mesh *mesh = (Mesh *)object_->data;
Mesh *read_mesh = this->read_mesh( Mesh *read_mesh = this->read_mesh(mesh, params, nullptr);
mesh, motionSampleTime, import_params_.mesh_read_flag, nullptr);
if (read_mesh != mesh) { if (read_mesh != mesh) {
BKE_mesh_nomain_to_mesh(read_mesh, mesh, object_); BKE_mesh_nomain_to_mesh(read_mesh, mesh, object_);
@ -124,8 +125,7 @@ bool USDShapeReader::read_mesh_values(double motionSampleTime,
} }
Mesh *USDShapeReader::read_mesh(struct Mesh *existing_mesh, Mesh *USDShapeReader::read_mesh(struct Mesh *existing_mesh,
double motionSampleTime, const USDMeshReadParams params,
int /*read_flag*/,
const char ** /*err_str*/) const char ** /*err_str*/)
{ {
pxr::VtIntArray face_indices; pxr::VtIntArray face_indices;
@ -136,7 +136,8 @@ Mesh *USDShapeReader::read_mesh(struct Mesh *existing_mesh,
} }
/* Should have a good set of data by this point-- copy over. */ /* Should have a good set of data by this point-- copy over. */
Mesh *active_mesh = mesh_from_prim(existing_mesh, motionSampleTime, face_indices, face_counts); Mesh *active_mesh = mesh_from_prim(
existing_mesh, params.motion_sample_time, face_indices, face_counts);
if (active_mesh == existing_mesh) { if (active_mesh == existing_mesh) {
return existing_mesh; return existing_mesh;
} }

View File

@ -48,8 +48,7 @@ class USDShapeReader : public USDGeomReader {
void create_object(Main *bmain, double /*motionSampleTime*/) override; void create_object(Main *bmain, double /*motionSampleTime*/) override;
void read_object_data(Main *bmain, double motionSampleTime) override; void read_object_data(Main *bmain, double motionSampleTime) override;
Mesh *read_mesh(Mesh *existing_mesh, Mesh *read_mesh(Mesh *existing_mesh,
double motionSampleTime, USDMeshReadParams params,
int /*read_flag*/,
const char ** /*err_str*/) override; const char ** /*err_str*/) override;
bool is_time_varying(); bool is_time_varying();

View File

@ -86,6 +86,16 @@ struct USDImportParams {
bool import_all_materials; bool import_all_materials;
}; };
/* This struct is in place to store the mesh sequence parameters needed when reading a data from a
* usd file for the mesh sequence cache.
*/
typedef struct USDMeshReadParams {
double motion_sample_time; /* USD TimeCode in frames. */
int read_flags; /* MOD_MESHSEQ_xxx value that is set from MeshSeqCacheModifierData.read_flag. */
} USDMeshReadParams;
USDMeshReadParams create_mesh_read_params(double motion_sample_time, int read_flags);
/* The USD_export takes a as_background_job parameter, and returns a boolean. /* The USD_export takes a as_background_job parameter, and returns a boolean.
* *
* When as_background_job=true, returns false immediately after scheduling * When as_background_job=true, returns false immediately after scheduling
@ -121,9 +131,8 @@ void USD_get_transform(struct CacheReader *reader, float r_mat[4][4], float time
struct Mesh *USD_read_mesh(struct CacheReader *reader, struct Mesh *USD_read_mesh(struct CacheReader *reader,
struct Object *ob, struct Object *ob,
struct Mesh *existing_mesh, struct Mesh *existing_mesh,
double time, USDMeshReadParams params,
const char **err_str, const char **err_str);
int read_flag);
bool USD_mesh_topology_changed(struct CacheReader *reader, bool USD_mesh_topology_changed(struct CacheReader *reader,
const struct Object *ob, const struct Object *ob,

View File

@ -401,6 +401,7 @@ void MeshFromGeometry::create_colors(Mesh *mesh)
CustomDataLayer *color_layer = BKE_id_attribute_new( CustomDataLayer *color_layer = BKE_id_attribute_new(
&mesh->id, "Color", CD_PROP_COLOR, ATTR_DOMAIN_POINT, nullptr); &mesh->id, "Color", CD_PROP_COLOR, ATTR_DOMAIN_POINT, nullptr);
BKE_id_attributes_active_color_set(&mesh->id, color_layer->name); BKE_id_attributes_active_color_set(&mesh->id, color_layer->name);
BKE_id_attributes_default_color_set(&mesh->id, color_layer->name);
float4 *colors = (float4 *)color_layer->data; float4 *colors = (float4 *)color_layer->data;
int offset = mesh_geometry_.vertex_index_min_ - block.start_vertex_index; int offset = mesh_geometry_.vertex_index_min_ - block.start_vertex_index;
for (int i = 0, n = mesh_geometry_.get_vertex_count(); i != n; ++i) { for (int i = 0, n = mesh_geometry_.get_vertex_count(); i != n; ++i) {

View File

@ -2292,6 +2292,13 @@ static PointerRNA rna_Mesh_vertex_color_new(struct Mesh *me,
if (index != -1) { if (index != -1) {
ldata = rna_mesh_ldata_helper(me); ldata = rna_mesh_ldata_helper(me);
cdl = &ldata->layers[CustomData_get_layer_index_n(ldata, CD_PROP_BYTE_COLOR, index)]; cdl = &ldata->layers[CustomData_get_layer_index_n(ldata, CD_PROP_BYTE_COLOR, index)];
if (!me->active_color_attribute) {
me->active_color_attribute = BLI_strdup(cdl->name);
}
if (!me->default_color_attribute) {
me->default_color_attribute = BLI_strdup(cdl->name);
}
} }
RNA_pointer_create(&me->id, &RNA_MeshLoopColorLayer, cdl, &ptr); RNA_pointer_create(&me->id, &RNA_MeshLoopColorLayer, cdl, &ptr);

View File

@ -245,12 +245,13 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
# endif # endif
break; break;
} }
case CACHEFILE_TYPE_USD: case CACHEFILE_TYPE_USD: {
# ifdef WITH_USD # ifdef WITH_USD
result = USD_read_mesh( const USDMeshReadParams params = create_mesh_read_params(time * FPS, mcmd->read_flag);
mcmd->reader, ctx->object, mesh, time * FPS, &err_str, mcmd->read_flag); result = USD_read_mesh(mcmd->reader, ctx->object, mesh, params, &err_str);
# endif # endif
break; break;
}
case CACHE_FILE_TYPE_INVALID: case CACHE_FILE_TYPE_INVALID:
break; break;
} }

View File

@ -834,15 +834,21 @@ static void initialize_group_input(NodesModifierData &nmd,
} }
} }
static const lf::FunctionNode &find_viewer_lf_node(const bNode &viewer_bnode) static const lf::FunctionNode *find_viewer_lf_node(const bNode &viewer_bnode)
{ {
return *blender::nodes::ensure_geometry_nodes_lazy_function_graph(viewer_bnode.owner_tree()) if (const blender::nodes::GeometryNodesLazyFunctionGraphInfo *lf_graph_info =
->mapping.viewer_node_map.lookup(&viewer_bnode); blender::nodes::ensure_geometry_nodes_lazy_function_graph(viewer_bnode.owner_tree())) {
return lf_graph_info->mapping.viewer_node_map.lookup_default(&viewer_bnode, nullptr);
}
return nullptr;
} }
static const lf::FunctionNode &find_group_lf_node(const bNode &group_bnode) static const lf::FunctionNode *find_group_lf_node(const bNode &group_bnode)
{ {
return *blender::nodes::ensure_geometry_nodes_lazy_function_graph(group_bnode.owner_tree()) if (const blender::nodes::GeometryNodesLazyFunctionGraphInfo *lf_graph_info =
->mapping.group_node_map.lookup(&group_bnode); blender::nodes::ensure_geometry_nodes_lazy_function_graph(group_bnode.owner_tree())) {
return lf_graph_info->mapping.group_node_map.lookup_default(&group_bnode, nullptr);
}
return nullptr;
} }
static void find_side_effect_nodes_for_viewer_path( static void find_side_effect_nodes_for_viewer_path(
@ -888,15 +894,22 @@ static void find_side_effect_nodes_for_viewer_path(
if (found_viewer_node == nullptr) { if (found_viewer_node == nullptr) {
return; return;
} }
const lf::FunctionNode *lf_viewer_node = find_viewer_lf_node(*found_viewer_node);
if (lf_viewer_node == nullptr) {
return;
}
/* Not only mark the viewer node as having side effects, but also all group nodes it is contained /* Not only mark the viewer node as having side effects, but also all group nodes it is contained
* in. */ * in. */
r_side_effect_nodes.add_non_duplicates(compute_context_builder.hash(), r_side_effect_nodes.add_non_duplicates(compute_context_builder.hash(), lf_viewer_node);
&find_viewer_lf_node(*found_viewer_node));
compute_context_builder.pop(); compute_context_builder.pop();
while (!compute_context_builder.is_empty()) { while (!compute_context_builder.is_empty()) {
r_side_effect_nodes.add_non_duplicates(compute_context_builder.hash(), const lf::FunctionNode *lf_group_node = find_group_lf_node(*group_node_stack.pop());
&find_group_lf_node(*group_node_stack.pop())); if (lf_group_node == nullptr) {
return;
}
r_side_effect_nodes.add_non_duplicates(compute_context_builder.hash(), lf_group_node);
compute_context_builder.pop(); compute_context_builder.pop();
} }
} }

View File

@ -45,6 +45,31 @@ static Array<float> accumulated_lengths_curve_domain(const bke::CurvesGeometry &
return lengths; return lengths;
} }
static Array<float> calculate_curve_parameters(const bke::CurvesGeometry &curves)
{
const VArray<bool> cyclic = curves.cyclic();
Array<float> lengths = accumulated_lengths_curve_domain(curves);
const int last_index = curves.curves_num() - 1;
const float total_length = lengths.last() + curves.evaluated_length_total_for_curve(
last_index, cyclic[last_index]);
if (total_length > 0.0f) {
const float factor = 1.0f / total_length;
for (float &value : lengths) {
value *= factor;
}
}
else {
/* It is arbitrary what to do in those rare cases when all the points are
* in the same position. In this case we are just arbitrarily giving a valid
* value in the range based on the curve index. */
for (const int i : lengths.index_range()) {
lengths[i] = i / (lengths.size() - 1.0f);
}
}
return lengths;
}
/** /**
* Return the length of each control point along each curve, starting at zero for the first point. * Return the length of each control point along each curve, starting at zero for the first point.
* Importantly, this is different than the length at each evaluated point. The implementation is * Importantly, this is different than the length at each evaluated point. The implementation is
@ -55,7 +80,9 @@ static Array<float> accumulated_lengths_curve_domain(const bke::CurvesGeometry &
* - NURBS Curves: Treat the control points as if they were a poly curve, because there * - NURBS Curves: Treat the control points as if they were a poly curve, because there
* is no obvious mapping from each control point to a specific evaluated point. * is no obvious mapping from each control point to a specific evaluated point.
*/ */
static Array<float> curve_length_point_domain(const bke::CurvesGeometry &curves) static Array<float> calculate_point_lengths(
const bke::CurvesGeometry &curves,
const FunctionRef<void(MutableSpan<float>, float)> postprocess_lengths_for_curve)
{ {
curves.ensure_evaluated_lengths(); curves.ensure_evaluated_lengths();
const OffsetIndices points_by_curve = curves.points_by_curve(); const OffsetIndices points_by_curve = curves.points_by_curve();
@ -68,26 +95,31 @@ static Array<float> curve_length_point_domain(const bke::CurvesGeometry &curves)
threading::parallel_for(curves.curves_range(), 128, [&](IndexRange range) { threading::parallel_for(curves.curves_range(), 128, [&](IndexRange range) {
for (const int i_curve : range) { for (const int i_curve : range) {
const IndexRange points = points_by_curve[i_curve]; const IndexRange points = points_by_curve[i_curve];
const Span<float> evaluated_lengths = curves.evaluated_lengths_for_curve(i_curve, const bool is_cyclic = cyclic[i_curve];
cyclic[i_curve]); const Span<float> evaluated_lengths = curves.evaluated_lengths_for_curve(i_curve, is_cyclic);
MutableSpan<float> lengths = result.as_mutable_span().slice(points); MutableSpan<float> lengths = result.as_mutable_span().slice(points);
lengths.first() = 0.0f; lengths.first() = 0.0f;
float total;
switch (types[i_curve]) { switch (types[i_curve]) {
case CURVE_TYPE_CATMULL_ROM: { case CURVE_TYPE_CATMULL_ROM: {
const int resolution = resolutions[i_curve]; const int resolution = resolutions[i_curve];
for (const int i : IndexRange(points.size()).drop_back(1)) { for (const int i : IndexRange(points.size()).drop_back(1)) {
lengths[i + 1] = evaluated_lengths[resolution * (i + 1) - 1]; lengths[i + 1] = evaluated_lengths[resolution * (i + 1) - 1];
} }
total = evaluated_lengths.last();
break; break;
} }
case CURVE_TYPE_POLY: case CURVE_TYPE_POLY:
lengths.drop_front(1).copy_from(evaluated_lengths.take_front(lengths.size() - 1)); lengths.drop_front(1).copy_from(evaluated_lengths.take_front(lengths.size() - 1));
total = evaluated_lengths.last();
break; break;
case CURVE_TYPE_BEZIER: { case CURVE_TYPE_BEZIER: {
const Span<int> offsets = curves.bezier_evaluated_offsets_for_curve(i_curve); const Span<int> offsets = curves.bezier_evaluated_offsets_for_curve(i_curve);
for (const int i : IndexRange(points.size()).drop_back(1)) { for (const int i : IndexRange(points.size()).drop_back(1)) {
lengths[i + 1] = evaluated_lengths[offsets[i + 1] - 1]; lengths[i + 1] = evaluated_lengths[offsets[i + 1] - 1];
} }
total = evaluated_lengths.last();
break; break;
} }
case CURVE_TYPE_NURBS: { case CURVE_TYPE_NURBS: {
@ -98,115 +130,44 @@ static Array<float> curve_length_point_domain(const bke::CurvesGeometry &curves)
length += math::distance(positions[i], positions[i + 1]); length += math::distance(positions[i], positions[i + 1]);
} }
lengths.last() = length; lengths.last() = length;
if (is_cyclic) {
length += math::distance(positions.first(), positions.last());
}
total = length;
break; break;
} }
} }
postprocess_lengths_for_curve(lengths, total);
} }
}); });
return result; return result;
} }
static VArray<float> construct_curve_parameter_varray(const bke::CurvesGeometry &curves, static void convert_lengths_to_factors(MutableSpan<float> lengths, const float total_curve_length)
const IndexMask /*mask*/,
const eAttrDomain domain)
{ {
const VArray<bool> cyclic = curves.cyclic(); if (total_curve_length > 0.0f) {
const float factor = 1.0f / total_curve_length;
if (domain == ATTR_DOMAIN_POINT) { for (float &value : lengths.drop_front(1)) {
Array<float> result = curve_length_point_domain(curves); value *= factor;
MutableSpan<float> lengths = result.as_mutable_span();
const OffsetIndices points_by_curve = curves.points_by_curve();
threading::parallel_for(curves.curves_range(), 1024, [&](IndexRange range) {
for (const int i_curve : range) {
MutableSpan<float> curve_lengths = lengths.slice(points_by_curve[i_curve]);
const float total_length = curve_lengths.last();
if (total_length > 0.0f) {
const float factor = 1.0f / total_length;
for (float &value : curve_lengths) {
value *= factor;
}
}
else if (curve_lengths.size() == 1) {
/* The curve is a single point. */
curve_lengths[0] = 0.0f;
}
else {
/* It is arbitrary what to do in those rare cases when all the points are
* in the same position. In this case we are just arbitrarily giving a valid
* value in the range based on the point index. */
for (const int i : curve_lengths.index_range()) {
curve_lengths[i] = i / (curve_lengths.size() - 1.0f);
}
}
}
});
return VArray<float>::ForContainer(std::move(result));
}
if (domain == ATTR_DOMAIN_CURVE) {
Array<float> lengths = accumulated_lengths_curve_domain(curves);
const int last_index = curves.curves_num() - 1;
const float total_length = lengths.last() + curves.evaluated_length_total_for_curve(
last_index, cyclic[last_index]);
if (total_length > 0.0f) {
const float factor = 1.0f / total_length;
for (float &value : lengths) {
value *= factor;
}
} }
else { }
/* It is arbitrary what to do in those rare cases when all the points are else if (lengths.size() == 1) {
* in the same position. In this case we are just arbitrarily giving a valid /* The curve is a single point. */
* value in the range based on the curve index. */ lengths[0] = 0.0f;
for (const int i : lengths.index_range()) { }
lengths[i] = i / (lengths.size() - 1.0f); else {
} /* It is arbitrary what to do in those rare cases when all the
* points are in the same position. In this case we are just
* arbitrarily giving a valid
* value in the range based on the point index. */
for (const int i : lengths.index_range()) {
lengths[i] = i / (lengths.size() - 1.0f);
} }
return VArray<float>::ForContainer(std::move(lengths));
} }
return {};
} }
static Array<float> calculate_point_parameters(const bke::CurvesGeometry &curves)
static VArray<float> construct_curve_length_parameter_varray(const bke::CurvesGeometry &curves,
const IndexMask /*mask*/,
const eAttrDomain domain)
{ {
curves.ensure_evaluated_lengths(); return calculate_point_lengths(curves, convert_lengths_to_factors);
if (domain == ATTR_DOMAIN_POINT) {
Array<float> lengths = curve_length_point_domain(curves);
return VArray<float>::ForContainer(std::move(lengths));
}
if (domain == ATTR_DOMAIN_CURVE) {
Array<float> lengths = accumulated_lengths_curve_domain(curves);
return VArray<float>::ForContainer(std::move(lengths));
}
return {};
}
static VArray<int> construct_index_on_spline_varray(const bke::CurvesGeometry &curves,
const IndexMask /*mask*/,
const eAttrDomain domain)
{
if (domain == ATTR_DOMAIN_POINT) {
Array<int> result(curves.points_num());
MutableSpan<int> span = result.as_mutable_span();
const OffsetIndices points_by_curve = curves.points_by_curve();
threading::parallel_for(curves.curves_range(), 1024, [&](IndexRange range) {
for (const int i_curve : range) {
MutableSpan<int> indices = span.slice(points_by_curve[i_curve]);
for (const int i : indices.index_range()) {
indices[i] = i;
}
}
});
return VArray<int>::ForContainer(std::move(result));
}
return {};
} }
class CurveParameterFieldInput final : public bke::CurvesFieldInput { class CurveParameterFieldInput final : public bke::CurvesFieldInput {
@ -218,14 +179,21 @@ class CurveParameterFieldInput final : public bke::CurvesFieldInput {
GVArray get_varray_for_context(const bke::CurvesGeometry &curves, GVArray get_varray_for_context(const bke::CurvesGeometry &curves,
const eAttrDomain domain, const eAttrDomain domain,
IndexMask mask) const final const IndexMask /*mask*/) const final
{ {
return construct_curve_parameter_varray(curves, mask, domain); switch (domain) {
case ATTR_DOMAIN_POINT:
return VArray<float>::ForContainer(calculate_point_parameters(curves));
case ATTR_DOMAIN_CURVE:
return VArray<float>::ForContainer(calculate_curve_parameters(curves));
default:
BLI_assert_unreachable();
return {};
}
} }
uint64_t hash() const override uint64_t hash() const override
{ {
/* Some random constant hash. */
return 29837456298; return 29837456298;
} }
@ -245,14 +213,22 @@ class CurveLengthParameterFieldInput final : public bke::CurvesFieldInput {
GVArray get_varray_for_context(const bke::CurvesGeometry &curves, GVArray get_varray_for_context(const bke::CurvesGeometry &curves,
const eAttrDomain domain, const eAttrDomain domain,
IndexMask mask) const final const IndexMask /*mask*/) const final
{ {
return construct_curve_length_parameter_varray(curves, mask, domain); switch (domain) {
case ATTR_DOMAIN_POINT:
return VArray<float>::ForContainer(calculate_point_lengths(
curves, [](MutableSpan<float> /*lengths*/, const float /*total*/) {}));
case ATTR_DOMAIN_CURVE:
return VArray<float>::ForContainer(accumulated_lengths_curve_domain(curves));
default:
BLI_assert_unreachable();
return {};
}
} }
uint64_t hash() const override uint64_t hash() const override
{ {
/* Some random constant hash. */
return 345634563454; return 345634563454;
} }
@ -271,14 +247,26 @@ class IndexOnSplineFieldInput final : public bke::CurvesFieldInput {
GVArray get_varray_for_context(const bke::CurvesGeometry &curves, GVArray get_varray_for_context(const bke::CurvesGeometry &curves,
const eAttrDomain domain, const eAttrDomain domain,
IndexMask mask) const final const IndexMask /*mask*/) const final
{ {
return construct_index_on_spline_varray(curves, mask, domain); if (domain != ATTR_DOMAIN_POINT) {
return {};
}
Array<int> result(curves.points_num());
const OffsetIndices points_by_curve = curves.points_by_curve();
threading::parallel_for(curves.curves_range(), 1024, [&](IndexRange range) {
for (const int i_curve : range) {
MutableSpan<int> indices = result.as_mutable_span().slice(points_by_curve[i_curve]);
for (const int i : indices.index_range()) {
indices[i] = i;
}
}
});
return VArray<int>::ForContainer(std::move(result));
} }
uint64_t hash() const override uint64_t hash() const override
{ {
/* Some random constant hash. */
return 4536246522; return 4536246522;
} }

View File

@ -3669,22 +3669,26 @@ static void wm_paintcursor_test(bContext *C, const wmEvent *event)
} }
} }
static void wm_event_drag_and_drop_test(wmWindowManager *wm, wmWindow *win, wmEvent *event) static eHandlerActionFlag wm_event_drag_and_drop_test(wmWindowManager *wm,
wmWindow *win,
wmEvent *event)
{ {
bScreen *screen = WM_window_get_active_screen(win); bScreen *screen = WM_window_get_active_screen(win);
if (BLI_listbase_is_empty(&wm->drags)) { if (BLI_listbase_is_empty(&wm->drags)) {
return; return WM_HANDLER_CONTINUE;
} }
if (event->type == MOUSEMOVE || ISKEYMODIFIER(event->type)) { if (event->type == MOUSEMOVE || ISKEYMODIFIER(event->type)) {
screen->do_draw_drag = true; screen->do_draw_drag = true;
} }
else if (event->type == EVT_ESCKEY) { else if (ELEM(event->type, EVT_ESCKEY, RIGHTMOUSE)) {
wm_drags_exit(wm, win); wm_drags_exit(wm, win);
WM_drag_free_list(&wm->drags); WM_drag_free_list(&wm->drags);
screen->do_draw_drag = true; screen->do_draw_drag = true;
return WM_HANDLER_BREAK;
} }
else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
event->type = EVT_DROP; event->type = EVT_DROP;
@ -3703,6 +3707,8 @@ static void wm_event_drag_and_drop_test(wmWindowManager *wm, wmWindow *win, wmEv
/* Restore cursor (disabled, see `wm_dragdrop.cc`) */ /* Restore cursor (disabled, see `wm_dragdrop.cc`) */
// WM_cursor_modal_restore(win); // WM_cursor_modal_restore(win);
} }
return WM_HANDLER_CONTINUE;
} }
/** /**
@ -4025,7 +4031,7 @@ void wm_event_do_handlers(bContext *C)
} }
/* Check dragging, creates new event or frees, adds draw tag. */ /* Check dragging, creates new event or frees, adds draw tag. */
wm_event_drag_and_drop_test(wm, win, event); action |= wm_event_drag_and_drop_test(wm, win, event);
if ((action & WM_HANDLER_BREAK) == 0) { if ((action & WM_HANDLER_BREAK) == 0) {
/* NOTE: setting sub-window active should be done here, /* NOTE: setting sub-window active should be done here,