Cleanup: use struct for GPU the select buffer

GPU_select originally used GL_SELECT which defined the format for
storing the selection result.

Now this is no longer the case, define our own struct - making the code
easier to follow:

- Avoid having to deal with arrays in both `uint*` and `uint(*)[4]`
  multiplying offsets by 4 in some cases & not others.

- No magic numbers for the offsets of depth & selection-ID.

- No need to allocate unused members to match GL_SELECT
  (halving the buffer size).
This commit is contained in:
Campbell Barton 2022-01-31 13:01:29 +11:00
parent 9ccdad8a21
commit 8815f2f116
15 changed files with 259 additions and 205 deletions

View File

@ -27,6 +27,7 @@
struct wmOperatorType;
struct Base;
struct GPUSelectResult;
struct Object;
struct Scene;
struct bContext;
@ -323,21 +324,21 @@ struct Bone *ED_armature_pick_bone(struct bContext *C,
struct EditBone *ED_armature_pick_ebone_from_selectbuffer(struct Base **bases,
uint bases_len,
const uint *buffer,
const struct GPUSelectResult *buffer,
short hits,
bool findunsel,
bool do_nearest,
struct Base **r_base);
struct bPoseChannel *ED_armature_pick_pchan_from_selectbuffer(struct Base **bases,
uint bases_len,
const uint *buffer,
const struct GPUSelectResult *buffer,
short hits,
bool findunsel,
bool do_nearest,
struct Base **r_base);
struct Bone *ED_armature_pick_bone_from_selectbuffer(struct Base **bases,
uint bases_len,
const uint *buffer,
const struct GPUSelectResult *buffer,
short hits,
bool findunsel,
bool do_nearest,

View File

@ -55,6 +55,8 @@
#include "DEG_depsgraph.h"
#include "GPU_select.h"
#include "armature_intern.h"
/* utility macros for storing a temp int in the bone (selection flag) */
@ -67,10 +69,10 @@
Base *ED_armature_base_and_ebone_from_select_buffer(Base **bases,
uint bases_len,
int hit,
const uint select_id,
EditBone **r_ebone)
{
const uint hit_object = hit & 0xFFFF;
const uint hit_object = select_id & 0xFFFF;
Base *base = NULL;
EditBone *ebone = NULL;
/* TODO(campbell): optimize, eg: sort & binary search. */
@ -81,7 +83,7 @@ Base *ED_armature_base_and_ebone_from_select_buffer(Base **bases,
}
}
if (base != NULL) {
const uint hit_bone = (hit & ~BONESEL_ANY) >> 16;
const uint hit_bone = (select_id & ~BONESEL_ANY) >> 16;
bArmature *arm = base->object->data;
ebone = BLI_findlink(arm->edbo, hit_bone);
}
@ -91,10 +93,10 @@ Base *ED_armature_base_and_ebone_from_select_buffer(Base **bases,
Object *ED_armature_object_and_ebone_from_select_buffer(Object **objects,
uint objects_len,
int hit,
const uint select_id,
EditBone **r_ebone)
{
const uint hit_object = hit & 0xFFFF;
const uint hit_object = select_id & 0xFFFF;
Object *ob = NULL;
EditBone *ebone = NULL;
/* TODO(campbell): optimize, eg: sort & binary search. */
@ -105,7 +107,7 @@ Object *ED_armature_object_and_ebone_from_select_buffer(Object **objects,
}
}
if (ob != NULL) {
const uint hit_bone = (hit & ~BONESEL_ANY) >> 16;
const uint hit_bone = (select_id & ~BONESEL_ANY) >> 16;
bArmature *arm = ob->data;
ebone = BLI_findlink(arm->edbo, hit_bone);
}
@ -115,10 +117,10 @@ Object *ED_armature_object_and_ebone_from_select_buffer(Object **objects,
Base *ED_armature_base_and_pchan_from_select_buffer(Base **bases,
uint bases_len,
int hit,
const uint select_id,
bPoseChannel **r_pchan)
{
const uint hit_object = hit & 0xFFFF;
const uint hit_object = select_id & 0xFFFF;
Base *base = NULL;
bPoseChannel *pchan = NULL;
/* TODO(campbell): optimize, eg: sort & binary search. */
@ -130,7 +132,7 @@ Base *ED_armature_base_and_pchan_from_select_buffer(Base **bases,
}
if (base != NULL) {
if (base->object->pose != NULL) {
const uint hit_bone = (hit & ~BONESEL_ANY) >> 16;
const uint hit_bone = (select_id & ~BONESEL_ANY) >> 16;
/* pchan may be NULL. */
pchan = BLI_findlink(&base->object->pose->chanbase, hit_bone);
}
@ -141,11 +143,11 @@ Base *ED_armature_base_and_pchan_from_select_buffer(Base **bases,
Base *ED_armature_base_and_bone_from_select_buffer(Base **bases,
uint bases_len,
int hit,
const uint select_id,
Bone **r_bone)
{
bPoseChannel *pchan = NULL;
Base *base = ED_armature_base_and_pchan_from_select_buffer(bases, bases_len, hit, &pchan);
Base *base = ED_armature_base_and_pchan_from_select_buffer(bases, bases_len, select_id, &pchan);
*r_bone = pchan ? pchan->bone : NULL;
return base;
}
@ -166,8 +168,8 @@ Base *ED_armature_base_and_bone_from_select_buffer(Base **bases,
static void *ed_armature_pick_bone_from_selectbuffer_impl(const bool is_editmode,
Base **bases,
uint bases_len,
const uint *buffer,
short hits,
const GPUSelectResult *buffer,
const short hits,
bool findunsel,
bool do_nearest,
Base **r_base)
@ -181,7 +183,7 @@ static void *ed_armature_pick_bone_from_selectbuffer_impl(const bool is_editmode
int minsel = 0xffffffff, minunsel = 0xffffffff;
for (short i = 0; i < hits; i++) {
hitresult = buffer[3 + (i * 4)];
hitresult = buffer[i].id;
if (hitresult & BONESEL_ANY) { /* to avoid including objects in selection */
Base *base = NULL;
@ -221,10 +223,10 @@ static void *ed_armature_pick_bone_from_selectbuffer_impl(const bool is_editmode
if (data) {
if (sel) {
if (do_nearest) {
if (minsel > buffer[4 * i + 1]) {
if (minsel > buffer[i].depth) {
firstSel = data;
firstSel_base = base;
minsel = buffer[4 * i + 1];
minsel = buffer[i].depth;
}
}
else {
@ -237,10 +239,10 @@ static void *ed_armature_pick_bone_from_selectbuffer_impl(const bool is_editmode
}
else {
if (do_nearest) {
if (minunsel > buffer[4 * i + 1]) {
if (minunsel > buffer[i].depth) {
firstunSel = data;
firstunSel_base = base;
minunsel = buffer[4 * i + 1];
minunsel = buffer[i].depth;
}
}
else {
@ -268,8 +270,8 @@ static void *ed_armature_pick_bone_from_selectbuffer_impl(const bool is_editmode
EditBone *ED_armature_pick_ebone_from_selectbuffer(Base **bases,
uint bases_len,
const uint *buffer,
short hits,
const GPUSelectResult *buffer,
const short hits,
bool findunsel,
bool do_nearest,
Base **r_base)
@ -281,8 +283,8 @@ EditBone *ED_armature_pick_ebone_from_selectbuffer(Base **bases,
bPoseChannel *ED_armature_pick_pchan_from_selectbuffer(Base **bases,
uint bases_len,
const uint *buffer,
short hits,
const GPUSelectResult *buffer,
const short hits,
bool findunsel,
bool do_nearest,
Base **r_base)
@ -294,8 +296,8 @@ bPoseChannel *ED_armature_pick_pchan_from_selectbuffer(Base **bases,
Bone *ED_armature_pick_bone_from_selectbuffer(Base **bases,
uint bases_len,
const uint *buffer,
short hits,
const GPUSelectResult *buffer,
const short hits,
bool findunsel,
bool do_nearest,
Base **r_base)
@ -327,7 +329,7 @@ static void *ed_armature_pick_bone_impl(
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
ViewContext vc;
rcti rect;
uint buffer[MAXPICKBUF];
GPUSelectResult buffer[MAXPICKELEMS];
short hits;
ED_view3d_viewcontext_init(C, &vc, depsgraph);
@ -340,7 +342,7 @@ static void *ed_armature_pick_bone_impl(
hits = view3d_opengl_select_with_id_filter(&vc,
buffer,
MAXPICKBUF,
ARRAY_SIZE(buffer),
&rect,
VIEW3D_SELECT_PICK_NEAREST,
VIEW3D_SELECT_FILTER_NOP,
@ -636,15 +638,15 @@ void ARMATURE_OT_select_linked_pick(wmOperatorType *ot)
* \{ */
/* utility function for get_nearest_editbonepoint */
static int selectbuffer_ret_hits_12(uint *UNUSED(buffer), const int hits12)
static int selectbuffer_ret_hits_12(GPUSelectResult *UNUSED(buffer), const int hits12)
{
return hits12;
}
static int selectbuffer_ret_hits_5(uint *buffer, const int hits12, const int hits5)
static int selectbuffer_ret_hits_5(GPUSelectResult *buffer, const int hits12, const int hits5)
{
const int ofs = 4 * hits12;
memcpy(buffer, buffer + ofs, 4 * hits5 * sizeof(uint));
const int ofs = hits12;
memcpy(buffer, buffer + ofs, hits5 * sizeof(*buffer));
return hits5;
}
@ -653,7 +655,7 @@ static int selectbuffer_ret_hits_5(uint *buffer, const int hits12, const int hit
static EditBone *get_nearest_editbonepoint(
ViewContext *vc, bool findunsel, bool use_cycle, Base **r_base, int *r_selmask)
{
uint buffer[MAXPICKBUF];
GPUSelectResult buffer[MAXPICKELEMS];
struct {
uint hitresult;
Base *base;
@ -692,7 +694,7 @@ static EditBone *get_nearest_editbonepoint(
rcti rect;
BLI_rcti_init_pt_radius(&rect, vc->mval, 12);
const int hits12 = view3d_opengl_select_with_id_filter(
vc, buffer, MAXPICKBUF, &rect, select_mode, select_filter, select_id_ignore);
vc, buffer, ARRAY_SIZE(buffer), &rect, select_mode, select_filter, select_id_ignore);
if (hits12 == 1) {
hits = selectbuffer_ret_hits_12(buffer, hits12);
@ -701,10 +703,15 @@ static EditBone *get_nearest_editbonepoint(
else if (hits12 > 0) {
int ofs;
ofs = 4 * hits12;
ofs = hits12;
BLI_rcti_init_pt_radius(&rect, vc->mval, 5);
const int hits5 = view3d_opengl_select_with_id_filter(
vc, buffer + ofs, MAXPICKBUF - ofs, &rect, select_mode, select_filter, select_id_ignore);
const int hits5 = view3d_opengl_select_with_id_filter(vc,
buffer + ofs,
ARRAY_SIZE(buffer) - ofs,
&rect,
select_mode,
select_filter,
select_id_ignore);
if (hits5 == 1) {
hits = selectbuffer_ret_hits_5(buffer, hits12, hits5);
@ -732,7 +739,7 @@ cache_end:
/* See if there are any selected bones in this group */
if (hits > 0) {
if (hits == 1) {
result_bias.hitresult = buffer[3];
result_bias.hitresult = buffer->id;
result_bias.base = ED_armature_base_and_ebone_from_select_buffer(
bases, bases_len, result_bias.hitresult, &result_bias.ebone);
}
@ -771,7 +778,7 @@ cache_end:
}
for (int i = 0; i < hits; i++) {
const uint hitresult = buffer[3 + (i * 4)];
const uint hitresult = buffer[i].id;
Base *base = NULL;
EditBone *ebone;

View File

@ -240,8 +240,8 @@ void ED_armature_pose_select_pick_bone(ViewLayer *view_layer,
bool ED_armature_pose_select_pick_with_buffer(ViewLayer *view_layer,
View3D *v3d,
Base *base,
const uint *buffer,
short hits,
const struct GPUSelectResult *buffer,
const short hits,
bool extend,
bool deselect,
bool toggle,

View File

@ -35,6 +35,7 @@ struct Base;
struct Bone;
struct Depsgraph;
struct EditBone;
struct GPUSelectResult;
struct ListBase;
struct Main;
struct Mesh;
@ -157,22 +158,22 @@ int ED_armature_join_objects_exec(struct bContext *C, struct wmOperator *op);
struct Base *ED_armature_base_and_ebone_from_select_buffer(struct Base **bases,
uint bases_len,
int hit,
unsigned int select_id,
struct EditBone **r_ebone);
struct Object *ED_armature_object_and_ebone_from_select_buffer(struct Object **objects,
uint objects_len,
int hit,
unsigned int select_id,
struct EditBone **r_ebone);
struct Base *ED_armature_base_and_pchan_from_select_buffer(struct Base **bases,
uint bases_len,
int hit,
unsigned int select_id,
struct bPoseChannel **r_pchan);
/**
* For callers that don't need the pose channel.
*/
struct Base *ED_armature_base_and_bone_from_select_buffer(struct Base **bases,
uint bases_len,
int hit,
unsigned int select_id,
struct Bone **r_bone);
bool ED_armature_edit_deselect_all(struct Object *obedit);
bool ED_armature_edit_deselect_all_visible(struct Object *obedit);
@ -334,7 +335,7 @@ void ED_armature_pose_select_pick_bone(struct ViewLayer *view_layer,
bool ED_armature_pose_select_pick_with_buffer(struct ViewLayer *view_layer,
struct View3D *v3d,
struct Base *base,
const unsigned int *buffer,
const struct GPUSelectResult *buffer,
short hits,
bool extend,
bool deselect,

View File

@ -41,6 +41,7 @@ struct Camera;
struct CustomData_MeshMasks;
struct Depsgraph;
struct EditBone;
struct GPUSelectResult;
struct ID;
struct MVert;
struct Main;
@ -873,7 +874,6 @@ bool ED_view3d_depth_read_cached_seg(
/* select */
#define MAXPICKELEMS 2500
#define MAXPICKBUF (4 * MAXPICKELEMS)
typedef enum {
/* all elements in the region, ignore depth */
@ -912,21 +912,21 @@ void view3d_opengl_select_cache_end(void);
* \note (vc->obedit == NULL) can be set to explicitly skip edit-object selection.
*/
int view3d_opengl_select_ex(struct ViewContext *vc,
unsigned int *buffer,
unsigned int bufsize,
struct GPUSelectResult *buffer,
unsigned int buffer_len,
const struct rcti *input,
eV3DSelectMode select_mode,
eV3DSelectObjectFilter select_filter,
bool do_material_slot_selection);
int view3d_opengl_select(struct ViewContext *vc,
unsigned int *buffer,
unsigned int bufsize,
struct GPUSelectResult *buffer,
unsigned int buffer_len,
const struct rcti *input,
eV3DSelectMode select_mode,
eV3DSelectObjectFilter select_filter);
int view3d_opengl_select_with_id_filter(struct ViewContext *vc,
unsigned int *buffer,
unsigned int bufsize,
struct GPUSelectResult *buffer,
unsigned int buffer_len,
const struct rcti *input,
eV3DSelectMode select_mode,
eV3DSelectObjectFilter select_filter,

View File

@ -20,6 +20,7 @@ set(INC
../../blenkernel
../../blenlib
../../depsgraph
../../gpu
../../makesdna
../../makesrna
../../render

View File

@ -47,6 +47,8 @@
#include "DEG_depsgraph.h"
#include "GPU_select.h"
#include "ED_mball.h"
#include "ED_object.h"
#include "ED_screen.h"
@ -756,15 +758,19 @@ bool ED_mball_select_pick(bContext *C, const int mval[2], bool extend, bool dese
static MetaElem *startelem = NULL;
ViewContext vc;
int a, hits;
uint buffer[MAXPICKBUF];
GPUSelectResult buffer[MAXPICKELEMS];
rcti rect;
ED_view3d_viewcontext_init(C, &vc, depsgraph);
BLI_rcti_init_pt_radius(&rect, mval, 12);
hits = view3d_opengl_select(
&vc, buffer, MAXPICKBUF, &rect, VIEW3D_SELECT_PICK_NEAREST, VIEW3D_SELECT_FILTER_NOP);
hits = view3d_opengl_select(&vc,
buffer,
ARRAY_SIZE(buffer),
&rect,
VIEW3D_SELECT_PICK_NEAREST,
VIEW3D_SELECT_FILTER_NOP);
FOREACH_BASE_IN_EDIT_MODE_BEGIN (vc.view_layer, vc.v3d, base) {
ED_view3d_viewcontext_init_object(&vc, base->object);
@ -789,7 +795,7 @@ bool ED_mball_select_pick(bContext *C, const int mval[2], bool extend, bool dese
ml = startelem;
while (ml) {
for (a = 0; a < hits; a++) {
int hitresult = buffer[(4 * a) + 3];
const int hitresult = buffer[a].id;
if (hitresult == -1) {
continue;
}

View File

@ -99,6 +99,7 @@
#include "UI_resources.h"
#include "GPU_matrix.h"
#include "GPU_select.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
@ -1566,8 +1567,8 @@ void VIEW3D_OT_select_menu(wmOperatorType *ot)
static Base *object_mouse_select_menu(bContext *C,
ViewContext *vc,
const uint *buffer,
int hits,
const GPUSelectResult *buffer,
const int hits,
const int mval[2],
bool extend,
bool deselect,
@ -1585,7 +1586,7 @@ static Base *object_mouse_select_menu(bContext *C,
if (buffer) {
for (int a = 0; a < hits; a++) {
/* index was converted */
if (base->object->runtime.select_id == (buffer[(4 * a) + 3] & ~0xFFFF0000)) {
if (base->object->runtime.select_id == (buffer[a].id & ~0xFFFF0000)) {
ok = true;
break;
}
@ -1742,7 +1743,7 @@ void VIEW3D_OT_bone_select_menu(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
static bool bone_mouse_select_menu(bContext *C,
const uint *buffer,
const GPUSelectResult *buffer,
const int hits,
const bool is_editmode,
const bool extend,
@ -1760,7 +1761,7 @@ static bool bone_mouse_select_menu(bContext *C,
for (int a = 0; a < hits; a++) {
void *bone_ptr = NULL;
Base *bone_base = NULL;
uint hitresult = buffer[3 + (a * 4)];
uint hitresult = buffer[a].id;
if (!(hitresult & BONESEL_ANY)) {
/* To avoid including objects in selection. */
@ -1874,10 +1875,10 @@ static bool bone_mouse_select_menu(bContext *C,
return true;
}
static bool selectbuffer_has_bones(const uint *buffer, const uint hits)
static bool selectbuffer_has_bones(const GPUSelectResult *buffer, const uint hits)
{
for (uint i = 0; i < hits; i++) {
if (buffer[(4 * i) + 3] & 0xFFFF0000) {
if (buffer[i].id & 0xFFFF0000) {
return true;
}
}
@ -1885,25 +1886,25 @@ static bool selectbuffer_has_bones(const uint *buffer, const uint hits)
}
/* utility function for mixed_bones_object_selectbuffer */
static int selectbuffer_ret_hits_15(uint *UNUSED(buffer), const int hits15)
static int selectbuffer_ret_hits_15(GPUSelectResult *UNUSED(buffer), const int hits15)
{
return hits15;
}
static int selectbuffer_ret_hits_9(uint *buffer, const int hits15, const int hits9)
static int selectbuffer_ret_hits_9(GPUSelectResult *buffer, const int hits15, const int hits9)
{
const int ofs = 4 * hits15;
memcpy(buffer, buffer + ofs, 4 * hits9 * sizeof(uint));
const int ofs = hits15;
memcpy(buffer, buffer + ofs, hits9 * sizeof(GPUSelectResult));
return hits9;
}
static int selectbuffer_ret_hits_5(uint *buffer,
static int selectbuffer_ret_hits_5(GPUSelectResult *buffer,
const int hits15,
const int hits9,
const int hits5)
{
const int ofs = 4 * hits15 + 4 * hits9;
memcpy(buffer, buffer + ofs, 4 * hits5 * sizeof(uint));
const int ofs = hits15 + hits9;
memcpy(buffer, buffer + ofs, hits5 * sizeof(GPUSelectResult));
return hits5;
}
@ -1916,7 +1917,8 @@ static int selectbuffer_ret_hits_5(uint *buffer,
* Needed so we can step to the next, non-active object when it's already selected, see: T76445.
*/
static int mixed_bones_object_selectbuffer(ViewContext *vc,
uint *buffer,
GPUSelectResult *buffer,
const int buffer_len,
const int mval[2],
eV3DSelectObjectFilter select_filter,
bool do_nearest,
@ -1941,7 +1943,7 @@ static int mixed_bones_object_selectbuffer(ViewContext *vc,
BLI_rcti_init_pt_radius(&rect, mval, 14);
hits15 = view3d_opengl_select_ex(
vc, buffer, MAXPICKBUF, &rect, select_mode, select_filter, do_material_slot_selection);
vc, buffer, buffer_len, &rect, select_mode, select_filter, do_material_slot_selection);
if (hits15 == 1) {
hits = selectbuffer_ret_hits_15(buffer, hits15);
goto finally;
@ -1950,10 +1952,10 @@ static int mixed_bones_object_selectbuffer(ViewContext *vc,
int ofs;
has_bones15 = selectbuffer_has_bones(buffer, hits15);
ofs = 4 * hits15;
ofs = hits15;
BLI_rcti_init_pt_radius(&rect, mval, 9);
hits9 = view3d_opengl_select(
vc, buffer + ofs, MAXPICKBUF - ofs, &rect, select_mode, select_filter);
vc, buffer + ofs, buffer_len - ofs, &rect, select_mode, select_filter);
if (hits9 == 1) {
hits = selectbuffer_ret_hits_9(buffer, hits15, hits9);
goto finally;
@ -1961,10 +1963,10 @@ static int mixed_bones_object_selectbuffer(ViewContext *vc,
else if (hits9 > 0) {
has_bones9 = selectbuffer_has_bones(buffer + ofs, hits9);
ofs += 4 * hits9;
ofs += hits9;
BLI_rcti_init_pt_radius(&rect, mval, 5);
hits5 = view3d_opengl_select(
vc, buffer + ofs, MAXPICKBUF - ofs, &rect, select_mode, select_filter);
vc, buffer + ofs, buffer_len - ofs, &rect, select_mode, select_filter);
if (hits5 == 1) {
hits = selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5);
goto finally;
@ -2007,7 +2009,8 @@ finally:
}
static int mixed_bones_object_selectbuffer_extended(ViewContext *vc,
uint *buffer,
GPUSelectResult *buffer,
const int buffer_len,
const int mval[2],
eV3DSelectObjectFilter select_filter,
bool use_cycle,
@ -2038,7 +2041,7 @@ static int mixed_bones_object_selectbuffer_extended(ViewContext *vc,
do_nearest = do_nearest && !enumerate;
int hits = mixed_bones_object_selectbuffer(
vc, buffer, mval, select_filter, do_nearest, true, false);
vc, buffer, buffer_len, mval, select_filter, do_nearest, true, false);
return hits;
}
@ -2051,7 +2054,7 @@ static int mixed_bones_object_selectbuffer_extended(ViewContext *vc,
* \return the active base or NULL.
*/
static Base *mouse_select_eval_buffer(ViewContext *vc,
const uint *buffer,
const GPUSelectResult *buffer,
int hits,
Base *startbase,
bool has_bones,
@ -2071,10 +2074,10 @@ static Base *mouse_select_eval_buffer(ViewContext *vc,
if (has_bones) {
/* we skip non-bone hits */
for (a = 0; a < hits; a++) {
if (min > buffer[4 * a + 1] && (buffer[4 * a + 3] & 0xFFFF0000)) {
min = buffer[4 * a + 1];
selcol = buffer[4 * a + 3] & 0xFFFF;
sub_selection_id = (buffer[4 * a + 3] & 0xFFFF0000) >> 16;
if (min > buffer[a].depth && (buffer[a].id & 0xFFFF0000)) {
min = buffer[a].depth;
selcol = buffer[a].id & 0xFFFF;
sub_selection_id = (buffer[a].id & 0xFFFF0000) >> 16;
}
}
}
@ -2085,10 +2088,10 @@ static Base *mouse_select_eval_buffer(ViewContext *vc,
}
for (a = 0; a < hits; a++) {
if (min > buffer[4 * a + 1] && notcol != (buffer[4 * a + 3] & 0xFFFF)) {
min = buffer[4 * a + 1];
selcol = buffer[4 * a + 3] & 0xFFFF;
sub_selection_id = (buffer[4 * a + 3] & 0xFFFF0000) >> 16;
if (min > buffer[a].depth && notcol != (buffer[a].id & 0xFFFF)) {
min = buffer[a].depth;
selcol = buffer[a].id & 0xFFFF;
sub_selection_id = (buffer[a].id & 0xFFFF0000) >> 16;
}
}
}
@ -2127,14 +2130,14 @@ static Base *mouse_select_eval_buffer(ViewContext *vc,
for (a = 0; a < hits; a++) {
if (has_bones) {
/* skip non-bone objects */
if (buffer[4 * a + 3] & 0xFFFF0000) {
if (base->object->runtime.select_id == (buffer[(4 * a) + 3] & 0xFFFF)) {
if (buffer[a].id & 0xFFFF0000) {
if (base->object->runtime.select_id == (buffer[a].id & 0xFFFF)) {
basact = base;
}
}
}
else {
if (base->object->runtime.select_id == (buffer[(4 * a) + 3] & 0xFFFF)) {
if (base->object->runtime.select_id == (buffer[a].id & 0xFFFF)) {
basact = base;
}
}
@ -2169,7 +2172,7 @@ static Base *ed_view3d_give_base_under_cursor_ex(bContext *C,
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
ViewContext vc;
Base *basact = NULL;
uint buffer[MAXPICKBUF];
GPUSelectResult buffer[MAXPICKELEMS];
/* setup view context for argument to callbacks */
view3d_operator_needs_opengl(C);
@ -2179,8 +2182,14 @@ static Base *ed_view3d_give_base_under_cursor_ex(bContext *C,
const bool do_nearest = !XRAY_ACTIVE(vc.v3d);
const bool do_material_slot_selection = r_material_slot != NULL;
const int hits = mixed_bones_object_selectbuffer(
&vc, buffer, mval, VIEW3D_SELECT_FILTER_NOP, do_nearest, false, do_material_slot_selection);
const int hits = mixed_bones_object_selectbuffer(&vc,
buffer,
ARRAY_SIZE(buffer),
mval,
VIEW3D_SELECT_FILTER_NOP,
do_nearest,
false,
do_material_slot_selection);
if (hits > 0) {
const bool has_bones = (r_material_slot == NULL) && selectbuffer_has_bones(buffer, hits);
@ -2342,7 +2351,7 @@ static bool ed_object_select_pick(bContext *C,
}
}
else {
uint buffer[MAXPICKBUF];
GPUSelectResult buffer[MAXPICKELEMS];
bool do_nearest;
// TIMEIT_START(select_time);
@ -2353,7 +2362,7 @@ static bool ed_object_select_pick(bContext *C,
vc.obact) :
VIEW3D_SELECT_FILTER_NOP);
hits = mixed_bones_object_selectbuffer_extended(
&vc, buffer, mval, select_filter, true, enumerate, &do_nearest);
&vc, buffer, ARRAY_SIZE(buffer), mval, select_filter, true, enumerate, &do_nearest);
// TIMEIT_END(select_time);
@ -2383,7 +2392,7 @@ static bool ed_object_select_pick(bContext *C,
bool changed = false;
for (int i = 0; i < hits; i++) {
int hitresult = buffer[3 + (i * 4)];
const int hitresult = buffer[i].id;
/* if there's bundles in buffer select bundles first,
* so non-camera elements should be ignored in buffer */
@ -2394,7 +2403,7 @@ static bool ed_object_select_pick(bContext *C,
/* index of bundle is 1<<16-based. if there's no "bone" index
* in height word, this buffer value belongs to camera. not to bundle
*/
if (buffer[4 * i + 3] & 0xFFFF0000) {
if (hitresult & 0xFFFF0000) {
MovieTracking *tracking = &clip->tracking;
ListBase *tracksbase;
MovieTrackingTrack *track;
@ -2674,9 +2683,15 @@ static int view3d_select_exec(bContext *C, wmOperator *op)
ViewContext vc;
ED_view3d_viewcontext_init(C, &vc, depsgraph);
uint buffer[MAXPICKBUF];
const int hits = mixed_bones_object_selectbuffer(
&vc, buffer, location, VIEW3D_SELECT_FILTER_NOP, false, true, false);
GPUSelectResult buffer[MAXPICKELEMS];
const int hits = mixed_bones_object_selectbuffer(&vc,
buffer,
ARRAY_SIZE(buffer),
location,
VIEW3D_SELECT_FILTER_NOP,
false,
true,
false);
retval = bone_mouse_select_menu(C, buffer, hits, true, extend, deselect, toggle);
}
if (!retval) {
@ -3256,11 +3271,11 @@ static bool do_meta_box_select(ViewContext *vc, const rcti *rect, const eSelectO
int a;
bool changed = false;
uint buffer[MAXPICKBUF];
GPUSelectResult buffer[MAXPICKELEMS];
int hits;
hits = view3d_opengl_select(
vc, buffer, MAXPICKBUF, rect, VIEW3D_SELECT_ALL, VIEW3D_SELECT_FILTER_NOP);
vc, buffer, MAXPICKELEMS, rect, VIEW3D_SELECT_ALL, VIEW3D_SELECT_FILTER_NOP);
if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
changed |= BKE_mball_deselect_all(mb);
@ -3272,7 +3287,7 @@ static bool do_meta_box_select(ViewContext *vc, const rcti *rect, const eSelectO
bool is_inside_stiff = false;
for (a = 0; a < hits; a++) {
int hitresult = buffer[(4 * a) + 3];
const int hitresult = buffer[a].id;
if (hitresult == -1) {
continue;
@ -3323,11 +3338,11 @@ static bool do_armature_box_select(ViewContext *vc, const rcti *rect, const eSel
bool changed = false;
int a;
uint buffer[MAXPICKBUF];
GPUSelectResult buffer[MAXPICKELEMS];
int hits;
hits = view3d_opengl_select(
vc, buffer, MAXPICKBUF, rect, VIEW3D_SELECT_ALL, VIEW3D_SELECT_FILTER_NOP);
vc, buffer, MAXPICKELEMS, rect, VIEW3D_SELECT_ALL, VIEW3D_SELECT_FILTER_NOP);
uint bases_len = 0;
Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(
@ -3347,7 +3362,7 @@ static bool do_armature_box_select(ViewContext *vc, const rcti *rect, const eSel
/* first we only check points inside the border */
for (a = 0; a < hits; a++) {
int select_id = buffer[(4 * a) + 3];
const int select_id = buffer[a].id;
if (select_id != -1) {
if ((select_id & 0xFFFF0000) == 0) {
continue;
@ -3375,14 +3390,13 @@ static bool do_armature_box_select(ViewContext *vc, const rcti *rect, const eSel
}
/**
* Compare result of 'GPU_select': 'uint[4]',
* Compare result of 'GPU_select': 'GPUSelectResult',
* needed for when we need to align with object draw-order.
*/
static int opengl_bone_select_buffer_cmp(const void *sel_a_p, const void *sel_b_p)
{
/* 4th element is select id */
uint sel_a = ((uint *)sel_a_p)[3];
uint sel_b = ((uint *)sel_b_p)[3];
uint sel_a = ((GPUSelectResult *)sel_a_p)->id;
uint sel_b = ((GPUSelectResult *)sel_b_p)->id;
#ifdef __BIG_ENDIAN__
BLI_endian_switch_uint32(&sel_a);
@ -3401,14 +3415,15 @@ static int opengl_bone_select_buffer_cmp(const void *sel_a_p, const void *sel_b_
static bool do_object_box_select(bContext *C, ViewContext *vc, rcti *rect, const eSelectOp sel_op)
{
View3D *v3d = vc->v3d;
int totobj = MAXPICKBUF; /* XXX solve later */
int totobj = MAXPICKELEMS; /* XXX solve later */
/* selection buffer now has bones potentially too, so we add MAXPICKBUF */
uint *vbuffer = MEM_mallocN(4 * (totobj + MAXPICKELEMS) * sizeof(uint[4]), "selection buffer");
/* Selection buffer has bones potentially too, so we add #MAXPICKELEMS. */
GPUSelectResult *buffer = MEM_mallocN((totobj + MAXPICKELEMS) * sizeof(GPUSelectResult),
"selection buffer");
const eV3DSelectObjectFilter select_filter = ED_view3d_select_filter_from_mode(vc->scene,
vc->obact);
const int hits = view3d_opengl_select(
vc, vbuffer, 4 * (totobj + MAXPICKELEMS), rect, VIEW3D_SELECT_ALL, select_filter);
vc, buffer, (totobj + MAXPICKELEMS), rect, VIEW3D_SELECT_ALL, select_filter);
LISTBASE_FOREACH (Base *, base, &vc->view_layer->object_bases) {
base->object->id.tag &= ~LIB_TAG_DOIT;
@ -3435,12 +3450,13 @@ static bool do_object_box_select(bContext *C, ViewContext *vc, rcti *rect, const
}
/* The draw order doesn't always match the order we populate the engine, see: T51695. */
qsort(vbuffer, hits, sizeof(uint[4]), opengl_bone_select_buffer_cmp);
qsort(buffer, hits, sizeof(GPUSelectResult), opengl_bone_select_buffer_cmp);
for (const uint *col = vbuffer + 3, *col_end = col + (hits * 4); col < col_end; col += 4) {
for (const GPUSelectResult *buf_iter = buffer, *buf_end = buf_iter + hits; buf_iter < buf_end;
buf_iter++) {
bPoseChannel *pchan_dummy;
Base *base = ED_armature_base_and_pchan_from_select_buffer(
bases, BLI_array_len(bases), *col, &pchan_dummy);
bases, BLI_array_len(bases), buf_iter->id, &pchan_dummy);
if (base != NULL) {
base->object->id.tag |= LIB_TAG_DOIT;
}
@ -3463,7 +3479,7 @@ finally:
MEM_freeN(bases);
}
MEM_freeN(vbuffer);
MEM_freeN(buffer);
if (changed) {
DEG_id_tag_update(&vc->scene->id, ID_RECALC_SELECT);
@ -3477,14 +3493,15 @@ static bool do_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, const e
uint bases_len;
Base **bases = do_pose_tag_select_op_prepare(vc, &bases_len);
int totobj = MAXPICKBUF; /* XXX solve later */
int totobj = MAXPICKELEMS; /* XXX solve later */
/* selection buffer now has bones potentially too, so we add MAXPICKBUF */
uint *vbuffer = MEM_mallocN((totobj + MAXPICKELEMS) * sizeof(uint[4]), "selection buffer");
/* Selection buffer has bones potentially too, so add #MAXPICKELEMS. */
GPUSelectResult *buffer = MEM_mallocN((totobj + MAXPICKELEMS) * sizeof(GPUSelectResult),
"selection buffer");
const eV3DSelectObjectFilter select_filter = ED_view3d_select_filter_from_mode(vc->scene,
vc->obact);
const int hits = view3d_opengl_select(
vc, vbuffer, 4 * (totobj + MAXPICKELEMS), rect, VIEW3D_SELECT_ALL, select_filter);
vc, buffer, (totobj + MAXPICKELEMS), rect, VIEW3D_SELECT_ALL, select_filter);
/*
* LOGIC NOTES (theeth):
* The buffer and ListBase have the same relative order, which makes the selection
@ -3498,18 +3515,20 @@ static bool do_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, const e
/* no need to loop if there's no hit */
/* The draw order doesn't always match the order we populate the engine, see: T51695. */
qsort(vbuffer, hits, sizeof(uint[4]), opengl_bone_select_buffer_cmp);
qsort(buffer, hits, sizeof(GPUSelectResult), opengl_bone_select_buffer_cmp);
for (const uint *col = vbuffer + 3, *col_end = col + (hits * 4); col < col_end; col += 4) {
for (const GPUSelectResult *buf_iter = buffer, *buf_end = buf_iter + hits; buf_iter < buf_end;
buf_iter++) {
Bone *bone;
Base *base = ED_armature_base_and_bone_from_select_buffer(bases, bases_len, *col, &bone);
Base *base = ED_armature_base_and_bone_from_select_buffer(
bases, bases_len, buf_iter->id, &bone);
if (base == NULL) {
continue;
}
/* Loop over contiguous bone hits for 'base'. */
for (; col != col_end; col += 4) {
for (; buf_iter != buf_end; buf_iter++) {
/* should never fail */
if (bone != NULL) {
base->object->id.tag |= LIB_TAG_DOIT;
@ -3517,12 +3536,13 @@ static bool do_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, const e
}
/* Select the next bone if we're not switching bases. */
if (col + 4 != col_end) {
if ((base->object->runtime.select_id & 0x0000FFFF) != (col[4] & 0x0000FFFF)) {
if (buf_iter + 1 != buf_end) {
const GPUSelectResult *col_next = buf_iter + 1;
if ((base->object->runtime.select_id & 0x0000FFFF) != (col_next->id & 0x0000FFFF)) {
break;
}
if (base->object->pose != NULL) {
const uint hit_bone = (col[4] & ~BONESEL_ANY) >> 16;
const uint hit_bone = (col_next->id & ~BONESEL_ANY) >> 16;
bPoseChannel *pchan = BLI_findlink(&base->object->pose->chanbase, hit_bone);
bone = pchan ? pchan->bone : NULL;
}
@ -3543,7 +3563,7 @@ static bool do_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, const e
if (bases != NULL) {
MEM_freeN(bases);
}
MEM_freeN(vbuffer);
MEM_freeN(buffer);
return changed_multi;
}

View File

@ -863,7 +863,7 @@ void view3d_opengl_select_cache_end(void)
struct DrawSelectLoopUserData {
uint pass;
uint hits;
uint *buffer;
GPUSelectResult *buffer;
uint buffer_len;
const rcti *rect;
eGPUSelectMode gpu_select_mode;
@ -927,8 +927,8 @@ static bool drw_select_filter_object_mode_lock_for_weight_paint(Object *ob, void
}
int view3d_opengl_select_ex(ViewContext *vc,
uint *buffer,
uint bufsize,
GPUSelectResult *buffer,
uint buffer_len,
const rcti *input,
eV3DSelectMode select_mode,
eV3DSelectObjectFilter select_filter,
@ -1043,7 +1043,7 @@ int view3d_opengl_select_ex(ViewContext *vc,
/* Re-use cache (rect must be smaller than the cached)
* other context is assumed to be unchanged */
if (GPU_select_is_cached()) {
GPU_select_begin(buffer, bufsize, &rect, gpu_select_mode, 0);
GPU_select_begin(buffer, buffer_len, &rect, gpu_select_mode, 0);
GPU_select_cache_load_id();
hits = GPU_select_end();
goto finally;
@ -1071,7 +1071,7 @@ int view3d_opengl_select_ex(ViewContext *vc,
.pass = 0,
.hits = 0,
.buffer = buffer,
.buffer_len = bufsize,
.buffer_len = buffer_len,
.rect = &rect,
.gpu_select_mode = gpu_select_mode,
};
@ -1101,7 +1101,7 @@ int view3d_opengl_select_ex(ViewContext *vc,
.pass = 0,
.hits = 0,
.buffer = buffer,
.buffer_len = bufsize,
.buffer_len = buffer_len,
.rect = &rect,
.gpu_select_mode = gpu_select_mode,
};
@ -1144,24 +1144,24 @@ finally:
}
int view3d_opengl_select(ViewContext *vc,
uint *buffer,
uint bufsize,
GPUSelectResult *buffer,
uint buffer_len,
const rcti *input,
eV3DSelectMode select_mode,
eV3DSelectObjectFilter select_filter)
{
return view3d_opengl_select_ex(vc, buffer, bufsize, input, select_mode, select_filter, false);
return view3d_opengl_select_ex(vc, buffer, buffer_len, input, select_mode, select_filter, false);
}
int view3d_opengl_select_with_id_filter(ViewContext *vc,
uint *buffer,
uint bufsize,
GPUSelectResult *buffer,
const uint buffer_len,
const rcti *input,
eV3DSelectMode select_mode,
eV3DSelectObjectFilter select_filter,
uint select_id)
{
int hits = view3d_opengl_select(vc, buffer, bufsize, input, select_mode, select_filter);
int hits = view3d_opengl_select(vc, buffer, buffer_len, input, select_mode, select_filter);
/* Selection sometimes uses -1 for an invalid selection ID, remove these as they
* interfere with detection of actual number of hits in the selection. */

View File

@ -42,11 +42,27 @@ typedef enum eGPUSelectMode {
GPU_SELECT_PICK_NEAREST = 5,
} eGPUSelectMode;
/**
* The result of calling #GPU_select_begin & #GPU_select_end.
*/
typedef struct GPUSelectResult {
/** The selection identifier matching the value passed in by #GPU_select_load_id. */
unsigned int id;
/**
* The nearest depth.
* - Only supported by picking modes (#GPU_SELECT_PICK_ALL and #GPU_SELECT_PICK_NEAREST)
* since occlusion quiries don't provide a convenient way of accessing the depth-buffer.
* - OpenGL's `GL_SELECT` supported both near and far depths,
* this has not been included as Blender doesn't need this however support could be added.
*/
unsigned int depth;
} GPUSelectResult;
/**
* Initialize and provide buffer for results.
*/
void GPU_select_begin(unsigned int *buffer,
unsigned int bufsize,
void GPU_select_begin(GPUSelectResult *buffer,
unsigned int buffer_len,
const struct rcti *input,
eGPUSelectMode mode,
int oldhits);
@ -82,8 +98,8 @@ void GPU_select_cache_end(void);
*
* Note that comparing depth as uint is fine.
*/
const uint *GPU_select_buffer_near(const uint *buffer, int hits);
uint GPU_select_buffer_remove_by_id(uint *buffer, int hits, uint select_id);
const GPUSelectResult *GPU_select_buffer_near(const GPUSelectResult *buffer, int hits);
uint GPU_select_buffer_remove_by_id(GPUSelectResult *buffer, int hits, uint select_id);
/**
* Part of the solution copied from `rect_subregion_stride_calc`.
*/

View File

@ -80,8 +80,11 @@ static GPUSelectState g_select_state = {0};
/** \name Public API
* \{ */
void GPU_select_begin(
uint *buffer, uint bufsize, const rcti *input, eGPUSelectMode mode, int oldhits)
void GPU_select_begin(GPUSelectResult *buffer,
const uint buffer_len,
const rcti *input,
eGPUSelectMode mode,
int oldhits)
{
if (mode == GPU_SELECT_NEAREST_SECOND_PASS) {
/* In the case hits was '-1',
@ -120,12 +123,12 @@ void GPU_select_begin(
switch (g_select_state.algorithm) {
case ALGO_GL_QUERY: {
gpu_select_query_begin((uint(*)[4])buffer, bufsize / 4, input, mode, oldhits);
gpu_select_query_begin(buffer, buffer_len, input, mode, oldhits);
break;
}
default: /* ALGO_GL_PICK */
{
gpu_select_pick_begin((uint(*)[4])buffer, bufsize / 4, input, mode);
gpu_select_pick_begin(buffer, buffer_len, input, mode);
break;
}
}
@ -220,35 +223,35 @@ bool GPU_select_is_cached(void)
/** \name Utilities
* \{ */
const uint *GPU_select_buffer_near(const uint *buffer, int hits)
const GPUSelectResult *GPU_select_buffer_near(const GPUSelectResult *buffer, int hits)
{
const uint *buffer_near = NULL;
const GPUSelectResult *buffer_near = NULL;
uint depth_min = (uint)-1;
for (int i = 0; i < hits; i++) {
if (buffer[1] < depth_min) {
BLI_assert(buffer[3] != -1);
depth_min = buffer[1];
if (buffer->depth < depth_min) {
BLI_assert(buffer->id != -1);
depth_min = buffer->depth;
buffer_near = buffer;
}
buffer += 4;
buffer++;
}
return buffer_near;
}
uint GPU_select_buffer_remove_by_id(uint *buffer, int hits, uint select_id)
uint GPU_select_buffer_remove_by_id(GPUSelectResult *buffer, int hits, uint select_id)
{
uint *buffer_src = buffer;
uint *buffer_dst = buffer;
GPUSelectResult *buffer_src = buffer;
GPUSelectResult *buffer_dst = buffer;
int hits_final = 0;
for (int i = 0; i < hits; i++) {
if (buffer_src[3] != select_id) {
if (buffer_src->id != select_id) {
if (buffer_dst != buffer_src) {
memcpy(buffer_dst, buffer_src, sizeof(int[4]));
memcpy(buffer_dst, buffer_src, sizeof(GPUSelectResult));
}
buffer_dst += 4;
buffer_dst++;
hits_final += 1;
}
buffer_src += 4;
buffer_src++;
}
return hits_final;
}

View File

@ -238,10 +238,8 @@ static int depth_cmp(const void *v1, const void *v2)
/* depth sorting */
typedef struct GPUPickState {
/* cache on initialization */
uint (*buffer)[4];
/* Buffer size (stores number of integers, for actual size multiply by sizeof integer). */
uint bufsize;
GPUSelectResult *buffer;
uint buffer_len;
/* mode of operation */
eGPUSelectMode mode;
@ -303,7 +301,10 @@ typedef struct GPUPickState {
static GPUPickState g_pick_state = {0};
void gpu_select_pick_begin(uint (*buffer)[4], uint bufsize, const rcti *input, eGPUSelectMode mode)
void gpu_select_pick_begin(GPUSelectResult *buffer,
const uint buffer_len,
const rcti *input,
eGPUSelectMode mode)
{
GPUPickState *ps = &g_pick_state;
@ -317,8 +318,8 @@ void gpu_select_pick_begin(uint (*buffer)[4], uint bufsize, const rcti *input, e
GPU_debug_group_begin("Selection Pick");
ps->bufsize = bufsize;
ps->buffer = buffer;
ps->buffer_len = buffer_len;
ps->mode = mode;
const uint rect_len = (uint)(BLI_rcti_size_x(input) * BLI_rcti_size_y(input));
@ -580,7 +581,7 @@ uint gpu_select_pick_end(void)
rect_depth_final = ps->gl.rect_depth;
}
uint maxhits = g_pick_state.bufsize;
uint maxhits = g_pick_state.buffer_len;
DepthID *depth_data;
uint depth_data_len = 0;
@ -675,11 +676,8 @@ uint gpu_select_pick_end(void)
#ifdef DEBUG_PRINT
printf(" hit: %u: depth %u\n", depth_data[i].id, depth_data[i].depth);
#endif
/* first 3 are dummy values */
g_pick_state.buffer[hits][0] = 1;
g_pick_state.buffer[hits][1] = depth_data[i].depth;
g_pick_state.buffer[hits][2] = 0x0; /* z-far is currently never used. */
g_pick_state.buffer[hits][3] = depth_data[i].id;
g_pick_state.buffer[hits].depth = depth_data[i].depth;
g_pick_state.buffer[hits].id = depth_data[i].id;
hits++;
}
BLI_assert(hits < maxhits);

View File

@ -31,8 +31,8 @@ extern "C" {
/* gpu_select_pick */
void gpu_select_pick_begin(uint (*buffer)[4],
uint bufsize,
void gpu_select_pick_begin(GPUSelectResult *buffer,
uint buffer_len,
const rcti *input,
eGPUSelectMode mode);
bool gpu_select_pick_load_id(uint id, bool end);
@ -49,7 +49,7 @@ void gpu_select_pick_cache_load_id(void);
/* gpu_select_sample_query */
void gpu_select_query_begin(
uint (*buffer)[4], uint bufsize, const rcti *input, eGPUSelectMode mode, int oldhits);
GPUSelectResult *buffer, uint buffer_len, const rcti *input, eGPUSelectMode mode, int oldhits);
bool gpu_select_query_load_id(uint id);
uint gpu_select_query_end(void);

View File

@ -55,9 +55,9 @@ struct GPUSelectQueryState {
/* Array holding the id corresponding id to each query. */
Vector<uint> *ids;
/* Cache on initialization. */
uint (*buffer)[4];
/* Buffer size (stores number of integers, for actual size multiply by `sizeof(int)`). */
uint bufsize;
GPUSelectResult *buffer;
/* The capacity of the `buffer` array. */
uint buffer_len;
/* Mode of operation. */
eGPUSelectMode mode;
uint index;
@ -72,14 +72,17 @@ struct GPUSelectQueryState {
static GPUSelectQueryState g_query_state = {false};
void gpu_select_query_begin(
uint (*buffer)[4], uint bufsize, const rcti *input, const eGPUSelectMode mode, int oldhits)
void gpu_select_query_begin(GPUSelectResult *buffer,
uint buffer_len,
const rcti *input,
const eGPUSelectMode mode,
int oldhits)
{
GPU_debug_group_begin("Selection Queries");
g_query_state.query_issued = false;
g_query_state.bufsize = bufsize;
g_query_state.buffer = buffer;
g_query_state.buffer_len = buffer_len;
g_query_state.mode = mode;
g_query_state.index = 0;
g_query_state.oldhits = oldhits;
@ -138,10 +141,11 @@ bool gpu_select_query_load_id(uint id)
g_query_state.query_issued = true;
if (g_query_state.mode == GPU_SELECT_NEAREST_SECOND_PASS) {
/* Second pass should never run if first pass fails, can read past 'bufsize' in this case. */
/* Second pass should never run if first pass fails,
* can read past `buffer_len` in this case. */
BLI_assert(g_query_state.oldhits != -1);
if (g_query_state.index < g_query_state.oldhits) {
if (g_query_state.buffer[g_query_state.index][3] == id) {
if (g_query_state.buffer[g_query_state.index].id == id) {
g_query_state.index++;
return true;
}
@ -154,7 +158,7 @@ bool gpu_select_query_load_id(uint id)
uint gpu_select_query_end()
{
uint hits = 0;
const uint maxhits = g_query_state.bufsize;
const uint maxhits = g_query_state.buffer_len;
if (g_query_state.query_issued) {
g_query_state.queries->end_query();
@ -168,10 +172,8 @@ uint gpu_select_query_end()
if (result[i] != 0) {
if (g_query_state.mode != GPU_SELECT_NEAREST_SECOND_PASS) {
if (hits < maxhits) {
g_query_state.buffer[hits][0] = 1;
g_query_state.buffer[hits][1] = 0xFFFF;
g_query_state.buffer[hits][2] = 0xFFFF;
g_query_state.buffer[hits][3] = ids[i];
g_query_state.buffer[hits].depth = 0xFFFF;
g_query_state.buffer[hits].id = ids[i];
hits++;
}
else {
@ -183,9 +185,8 @@ uint gpu_select_query_end()
int j;
/* search in buffer and make selected object first */
for (j = 0; j < g_query_state.oldhits; j++) {
if (g_query_state.buffer[j][3] == ids[i]) {
g_query_state.buffer[j][1] = 0;
g_query_state.buffer[j][2] = 0;
if (g_query_state.buffer[j].id == ids[i]) {
g_query_state.buffer[j].depth = 0;
}
}
break;

View File

@ -572,7 +572,7 @@ static int gizmo_find_intersected_3d_intern(wmGizmo **visible_gizmos,
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
rcti rect;
/* Almost certainly overkill, but allow for many custom gizmos. */
uint buffer[MAXPICKBUF];
GPUSelectResult buffer[MAXPICKELEMS];
short hits;
BLI_rcti_init_pt_radius(&rect, co, hotspot);
@ -650,14 +650,14 @@ static int gizmo_find_intersected_3d_intern(wmGizmo **visible_gizmos,
GPU_matrix_unproject_3fv(co_screen, rv3d->viewinv, rv3d->winmat, viewport, co_3d_origin);
uint *buf_iter = buffer;
GPUSelectResult *buf_iter = buffer;
float dot_best = FLT_MAX;
for (int i = 0; i < hits; i++, buf_iter += 4) {
BLI_assert(buf_iter[3] != -1);
wmGizmo *gz = visible_gizmos[buf_iter[3] >> 8];
for (int i = 0; i < hits; i++, buf_iter++) {
BLI_assert(buf_iter->id != -1);
wmGizmo *gz = visible_gizmos[buf_iter->id >> 8];
float co_3d[3];
co_screen[2] = int_as_float(buf_iter[1]);
co_screen[2] = int_as_float(buf_iter->depth);
GPU_matrix_unproject_3fv(co_screen, rv3d->viewinv, rv3d->winmat, viewport, co_3d);
float select_bias = gz->select_bias;
if ((gz->flag & WM_GIZMO_DRAW_NO_SCALE) == 0) {
@ -667,14 +667,14 @@ static int gizmo_find_intersected_3d_intern(wmGizmo **visible_gizmos,
const float dot_test = dot_v3v3(co_3d, co_direction) - select_bias;
if (dot_best > dot_test) {
dot_best = dot_test;
hit_found = buf_iter[3];
hit_found = buf_iter->id;
}
}
}
else {
const uint *hit_near = GPU_select_buffer_near(buffer, hits);
const GPUSelectResult *hit_near = GPU_select_buffer_near(buffer, hits);
if (hit_near) {
hit_found = hit_near[3];
hit_found = hit_near->id;
}
}