From 8815f2f11632ea84d706bacd18e60639cb13d6eb Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 31 Jan 2022 13:01:29 +1100 Subject: 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). --- source/blender/gpu/GPU_select.h | 24 +++++++++++--- source/blender/gpu/intern/gpu_select.c | 37 ++++++++++++---------- source/blender/gpu/intern/gpu_select_pick.c | 22 ++++++------- source/blender/gpu/intern/gpu_select_private.h | 6 ++-- .../blender/gpu/intern/gpu_select_sample_query.cc | 33 +++++++++---------- 5 files changed, 70 insertions(+), 52 deletions(-) (limited to 'source/blender/gpu') diff --git a/source/blender/gpu/GPU_select.h b/source/blender/gpu/GPU_select.h index e5dda23b98d..90bbde4976c 100644 --- a/source/blender/gpu/GPU_select.h +++ b/source/blender/gpu/GPU_select.h @@ -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`. */ diff --git a/source/blender/gpu/intern/gpu_select.c b/source/blender/gpu/intern/gpu_select.c index 741df05799f..afef0e70ccc 100644 --- a/source/blender/gpu/intern/gpu_select.c +++ b/source/blender/gpu/intern/gpu_select.c @@ -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; } diff --git a/source/blender/gpu/intern/gpu_select_pick.c b/source/blender/gpu/intern/gpu_select_pick.c index ee509a076c9..680d1e8d6f5 100644 --- a/source/blender/gpu/intern/gpu_select_pick.c +++ b/source/blender/gpu/intern/gpu_select_pick.c @@ -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); diff --git a/source/blender/gpu/intern/gpu_select_private.h b/source/blender/gpu/intern/gpu_select_private.h index 940cb0bb9e2..0ec9f083c07 100644 --- a/source/blender/gpu/intern/gpu_select_private.h +++ b/source/blender/gpu/intern/gpu_select_private.h @@ -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); diff --git a/source/blender/gpu/intern/gpu_select_sample_query.cc b/source/blender/gpu/intern/gpu_select_sample_query.cc index 3d0b8518f98..195c22c5acd 100644 --- a/source/blender/gpu/intern/gpu_select_sample_query.cc +++ b/source/blender/gpu/intern/gpu_select_sample_query.cc @@ -55,9 +55,9 @@ struct GPUSelectQueryState { /* Array holding the id corresponding id to each query. */ Vector *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; -- cgit v1.2.3