Selection: Remove limit on number of items which can be selected at once #112491

Merged
Jesse Yurkovich merged 10 commits from deadpin/blender:fixselection into main 2023-11-30 21:27:23 +01:00

This removes the long-standing static limit for the selection buffer in
favor of a dynamic approach.

It replaces the static array with our Vector type where the inline
buffer provides parity with existing code while also providing the
ability to grow as necessary.

Fixes #102487, #109178, #112350, #112493, and blender/blender-manual#102485


Notes

In many instances a single GPUSelectionBuffer is reused across multiple calls to the selection system and multiple hit-count calculations. This means that the APIs returning "hit" counts must continue to do so as we can't depend only on the .size of the buffer. It also means that we have to be careful to slice out the relevant hit segments in places like mixed_bones_object_selectbuffer where work needs to occur only on the new hits.

We can shrink the 2500 inline buffer down if we like now, though we've been fine with the amount of stack space consumed so far.

Unfortunately, even after this change, the 32-bit selection_id itself imposes an ultimate limit. It is constructed as follows:
[3-bit bone mask | 13-bit bone id | 16-bit object id]
Which means:

  • Only 8192 bones are selectable (#106542)
  • Only 65535 objects are selectable (#104008)

That said, this change will allow many more scenarios to work reliably.

This removes the long-standing static limit for the selection buffer in favor of a dynamic approach. It replaces the static array with our Vector type where the inline buffer provides parity with existing code while also providing the ability to grow as necessary. Fixes #102487, #109178, #112350, #112493, and https://projects.blender.org/blender/blender-manual/issues/102485 ---- Notes In many instances a single GPUSelectionBuffer is reused across multiple calls to the selection system and multiple hit-count calculations. This means that the APIs returning "hit" counts must continue to do so as we can't depend only on the .size of the buffer. It also means that we have to be careful to `slice` out the relevant hit segments in places like `mixed_bones_object_selectbuffer` where work needs to occur only on the new hits. We can shrink the 2500 inline buffer down if we like now, though we've been fine with the amount of stack space consumed so far. Unfortunately, even after this change, the 32-bit selection_id itself imposes an ultimate limit. It is constructed as follows: `[3-bit bone mask | 13-bit bone id | 16-bit object id]` Which means: - Only 8192 bones are selectable (#106542) - Only 65535 objects are selectable (#104008) That said, this change will allow many more scenarios to work reliably.
Jesse Yurkovich added 4 commits 2023-09-18 03:07:57 +02:00
Jesse Yurkovich added the
Module
Modeling
label 2023-09-18 04:07:02 +02:00
Jesse Yurkovich added 1 commit 2023-09-18 07:55:58 +02:00
Jesse Yurkovich requested review from Campbell Barton 2023-09-19 20:52:55 +02:00
Jesse Yurkovich requested review from Clément Foucault 2023-09-19 20:52:55 +02:00
Clément Foucault requested changes 2023-09-28 15:23:36 +02:00
Clément Foucault left a comment
Member

Spotted a few errors and compilation error in debug build. Here is the changes I did to make it working.

I think it's a nice addition. I think inline buffer size was motivated by the speed of the sorting / processing of the result hits. I don't know how much relevant this is nowadays. Maybe Campbell has more insight on this.

I'm just unsure about removing the extern "C" guard in the header. Maybe it is better to rename it to .hh so it's clear it is a C++ only header. But then the patch would get a bit noisy. So better do that afterwards.

Spotted a few errors and compilation error in debug build. Here is the changes I did to make it working. I think it's a nice addition. I think inline buffer size was motivated by the speed of the sorting / processing of the result hits. I don't know how much relevant this is nowadays. Maybe Campbell has more insight on this. I'm just unsure about removing the `extern "C"` guard in the header. Maybe it is better to rename it to `.hh` so it's clear it is a C++ only header. But then the patch would get a bit noisy. So better do that afterwards.
@ -637,3 +640,3 @@
{
const int ofs = hits12;
memcpy(buffer, buffer + ofs, hits5 * sizeof(*buffer));
results.copy_from(results.slice(ofs, hits5)); /* Shift results to beginning. */

These are incorrect. It should be
results.slice(0, hits5).copy_from(results.slice(ofs, hits5));
Same goes for the other 2 copy_from in this patch.

These are incorrect. It should be `results.slice(0, hits5).copy_from(results.slice(ofs, hits5));` Same goes for the other 2 `copy_from` in this patch.
deadpin marked this conversation as resolved
@ -706,25 +705,20 @@ static EditBone *get_nearest_editbonepoint(
ofs = hits12;

Warning: Unused variable

Warning: Unused variable
deadpin marked this conversation as resolved
@ -614,3 +614,3 @@
for (int i = 0; i < hits; i++, buf_iter++) {
for (const GPUSelectResult &result : hit_results) {
BLI_assert(buf_iter->id != -1);

Should be BLI_assert(result.id != -1);

Should be `BLI_assert(result.id != -1);`
deadpin marked this conversation as resolved
Jesse Yurkovich added 2 commits 2023-09-28 21:10:47 +02:00
Author
Member

Thanks for that review! I did miss those .copy_froms...

Yes, I'll plan on changing the header afterwards to .hh

Thanks for that review! I did miss those .copy_froms... Yes, I'll plan on changing the header afterwards to `.hh`
Clément Foucault approved these changes 2023-09-28 23:57:00 +02:00
First-time contributor

will this be available as a fix for 4.0?

will this be available as a fix for 4.0?
Jesse Yurkovich added 1 commit 2023-11-15 23:35:58 +01:00
Campbell Barton reviewed 2023-11-30 10:52:55 +01:00
Campbell Barton left a comment
Owner

Generally very nice, only some minor details.

  • The Span<GPUSelectResult> declarations which aren´t modified should be made const.
  • There is an outdated reference to MAXPICKELEMS in comments which should be removed.
Generally very nice, only some minor details. - The `Span<GPUSelectResult>` declarations which aren´t modified should be made `const`. - There is an outdated reference to `MAXPICKELEMS` in comments which should be removed.
Campbell Barton approved these changes 2023-11-30 11:10:37 +01:00
Campbell Barton left a comment
Owner

Minor requests, accepting.

Minor requests, accepting.
@ -273,3 +262,1 @@
if (buffer_src->id != select_id) {
if (buffer_dst != buffer_src) {
memcpy(buffer_dst, buffer_src, sizeof(GPUSelectResult));
int64_t index_src = 0;

These can be int, the range is easily enough and used elsewhere with selection indices.

These can be `int`, the range is easily enough and used elsewhere with selection indices.
deadpin marked this conversation as resolved
@ -678,3 +666,1 @@
hits++;
}
BLI_assert(hits < maxhits);
g_pick_state.buffer->storage.append({depth_data[i].id, depth_data[i].depth});

Since the size is known ahead of time, reserve then use append_unchecked to avoid re-allocation.

Since the size is known ahead of time, reserve then use `append_unchecked` to avoid re-allocation.
deadpin marked this conversation as resolved

The Span declarations which aren´t modified should be made const.

The Span type itself is const. From the Span header doc:

An blender::Span<T> references an array that is owned by someone else. It is just a
pointer and a size. Since the memory is not owned, Span should not be used to transfer
ownership. The array cannot be modified through the Span. However, if T is a non-const
pointer, the pointed-to elements can be modified.

So I guess this is not important. MutableSpan is what should be used when the data is modified.

> The Span<GPUSelectResult> declarations which aren´t modified should be made const. The `Span` type itself is const. From the Span header doc: > An `blender::Span<T>` references an array that is owned by someone else. It is just a pointer and a size. Since the memory is not owned, Span should not be used to transfer ownership. The array cannot be modified through the Span. However, if T is a non-const pointer, the pointed-to elements can be modified. So I guess this is not important. `MutableSpan` is what should be used when the data is modified.
Author
Member

I see now that const Span is used quite often so I can make the change here as well. Making it const basically prevents cases where someone could re-assign the Span itself.

I see now that `const Span` is used quite often so I can make the change here as well. Making it const basically prevents cases where someone could re-assign the Span itself.
Jesse Yurkovich added 2 commits 2023-11-30 20:02:46 +01:00
Author
Member

@blender-bot build

@blender-bot build
Clément Foucault approved these changes 2023-11-30 20:11:04 +01:00
Jesse Yurkovich merged commit abf59eb23a into main 2023-11-30 21:27:23 +01:00
Jesse Yurkovich deleted branch fixselection 2023-11-30 21:27:25 +01:00
Sign in to join this conversation.
No Label
Interest
Alembic
Interest
Animation & Rigging
Interest
Asset Browser
Interest
Asset Browser Project Overview
Interest
Audio
Interest
Automated Testing
Interest
Blender Asset Bundle
Interest
BlendFile
Interest
Collada
Interest
Compatibility
Interest
Compositing
Interest
Core
Interest
Cycles
Interest
Dependency Graph
Interest
Development Management
Interest
EEVEE
Interest
EEVEE & Viewport
Interest
Freestyle
Interest
Geometry Nodes
Interest
Grease Pencil
Interest
ID Management
Interest
Images & Movies
Interest
Import Export
Interest
Line Art
Interest
Masking
Interest
Metal
Interest
Modeling
Interest
Modifiers
Interest
Motion Tracking
Interest
Nodes & Physics
Interest
OpenGL
Interest
Overlay
Interest
Overrides
Interest
Performance
Interest
Physics
Interest
Pipeline, Assets & IO
Interest
Platforms, Builds & Tests
Interest
Python API
Interest
Render & Cycles
Interest
Render Pipeline
Interest
Sculpt, Paint & Texture
Interest
Text Editor
Interest
Translations
Interest
Triaging
Interest
Undo
Interest
USD
Interest
User Interface
Interest
UV Editing
Interest
VFX & Video
Interest
Video Sequencer
Interest
Virtual Reality
Interest
Vulkan
Interest
Wayland
Interest
Workbench
Interest: X11
Legacy
Blender 2.8 Project
Legacy
Milestone 1: Basic, Local Asset Browser
Legacy
OpenGL Error
Meta
Good First Issue
Meta
Papercut
Meta
Retrospective
Meta
Security
Module
Animation & Rigging
Module
Core
Module
Development Management
Module
EEVEE & Viewport
Module
Grease Pencil
Module
Modeling
Module
Nodes & Physics
Module
Pipeline, Assets & IO
Module
Platforms, Builds & Tests
Module
Python API
Module
Render & Cycles
Module
Sculpt, Paint & Texture
Module
Triaging
Module
User Interface
Module
VFX & Video
Platform
FreeBSD
Platform
Linux
Platform
macOS
Platform
Windows
Priority
High
Priority
Low
Priority
Normal
Priority
Unbreak Now!
Status
Archived
Status
Confirmed
Status
Duplicate
Status
Needs Info from Developers
Status
Needs Information from User
Status
Needs Triage
Status
Resolved
Type
Bug
Type
Design
Type
Known Issue
Type
Patch
Type
Report
Type
To Do
No Milestone
No project
No Assignees
4 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: blender/blender#112491
No description provided.