Blender  V3.3
gpu_select.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2014 Blender Foundation. All rights reserved. */
3 
10 #include <stdlib.h>
11 #include <string.h>
12 
13 #include "GPU_select.h"
14 
15 #include "BLI_rect.h"
16 
17 #include "BLI_utildefines.h"
18 
19 #include "gpu_select_private.h"
20 
21 /* -------------------------------------------------------------------- */
25 /* Internal algorithm used */
26 typedef enum eGPUSelectAlgo {
34 
35 typedef struct GPUSelectState {
36  /* To ignore selection id calls when not initialized */
38  /* mode of operation */
40  /* internal algorithm for selection */
42  /* allow GPU_select_begin/end without drawing */
43  bool use_cache;
54 
56 
59 /* -------------------------------------------------------------------- */
64  const uint buffer_len,
65  const rcti *input,
66  eGPUSelectMode mode,
67  int oldhits)
68 {
69  if (mode == GPU_SELECT_NEAREST_SECOND_PASS) {
70  /* In the case hits was '-1',
71  * don't start the second pass since it's not going to give useful results.
72  * As well as buffer overflow in 'gpu_select_query_load_id'. */
73  BLI_assert(oldhits != -1);
74  }
75 
77  g_select_state.mode = mode;
78 
81  }
82  else {
84  }
85 
86  /* This function is called when cache has already been initialized,
87  * so only manipulate cache values when cache is pending. */
90 
91  switch (g_select_state.algorithm) {
92  case ALGO_GL_QUERY: {
93  g_select_state.use_cache = false;
94  break;
95  }
96  default: {
99  break;
100  }
101  }
102  }
103 
104  switch (g_select_state.algorithm) {
105  case ALGO_GL_QUERY: {
106  gpu_select_query_begin(buffer, buffer_len, input, mode, oldhits);
107  break;
108  }
109  default: /* ALGO_GL_PICK */
110  {
111  gpu_select_pick_begin(buffer, buffer_len, input, mode);
112  break;
113  }
114  }
115 }
116 
118 {
119  /* if no selection mode active, ignore */
121  return true;
122  }
123 
124  switch (g_select_state.algorithm) {
125  case ALGO_GL_QUERY: {
126  return gpu_select_query_load_id(id);
127  }
128  default: /* ALGO_GL_PICK */
129  {
130  return gpu_select_pick_load_id(id, false);
131  }
132  }
133 }
134 
136 {
137  uint hits = 0;
138 
139  switch (g_select_state.algorithm) {
140  case ALGO_GL_QUERY: {
141  hits = gpu_select_query_end();
142  break;
143  }
144  default: /* ALGO_GL_PICK */
145  {
146  hits = gpu_select_pick_end();
147  break;
148  }
149  }
150 
152 
153  return hits;
154 }
155 
158 /* -------------------------------------------------------------------- */
166 {
168  /* Ensure #GPU_select_cache_end is always called. */
170 
171  /* Signal that cache should be used, instead of calling the algorithms cache-begin function.
172  * This is more convenient as the exact method of selection may not be known by the caller. */
174 }
175 
177 {
181  }
182 }
183 
185 {
189  }
190  g_select_state.use_cache = false;
191  /* Paranoid assignment, should already be false. */
193 }
194 
196 {
198 }
199 
202 /* -------------------------------------------------------------------- */
207 {
208  const GPUSelectResult *buffer_near = NULL;
209  uint depth_min = (uint)-1;
210  for (int i = 0; i < hits; i++) {
211  if (buffer->depth < depth_min) {
212  BLI_assert(buffer->id != -1);
213  depth_min = buffer->depth;
214  buffer_near = buffer;
215  }
216  buffer++;
217  }
218  return buffer_near;
219 }
220 
222 {
223  GPUSelectResult *buffer_src = buffer;
224  GPUSelectResult *buffer_dst = buffer;
225  int hits_final = 0;
226  for (int i = 0; i < hits; i++) {
227  if (buffer_src->id != select_id) {
228  if (buffer_dst != buffer_src) {
229  memcpy(buffer_dst, buffer_src, sizeof(GPUSelectResult));
230  }
231  buffer_dst++;
232  hits_final += 1;
233  }
234  buffer_src++;
235  }
236  return hits_final;
237 }
238 
239 void GPU_select_buffer_stride_realign(const rcti *src, const rcti *dst, uint *r_buf)
240 {
241  const int x = dst->xmin - src->xmin;
242  const int y = dst->ymin - src->ymin;
243 
244  BLI_assert(src->xmin <= dst->xmin && src->ymin <= dst->ymin && src->xmax >= dst->xmax &&
245  src->ymax >= dst->ymax);
246  BLI_assert(x >= 0 && y >= 0);
247 
248  const int src_x = BLI_rcti_size_x(src);
249  const int src_y = BLI_rcti_size_y(src);
250  const int dst_x = BLI_rcti_size_x(dst);
251  const int dst_y = BLI_rcti_size_y(dst);
252 
253  int last_px_id = src_x * (y + dst_y - 1) + (x + dst_x - 1);
254  memset(&r_buf[last_px_id + 1], 0, (src_x * src_y - (last_px_id + 1)) * sizeof(*r_buf));
255 
256  if (last_px_id < 0) {
257  /* Nothing to write. */
258  BLI_assert(last_px_id == -1);
259  return;
260  }
261 
262  int last_px_written = dst_x * dst_y - 1;
263  const int skip = src_x - dst_x;
264 
265  while (true) {
266  for (int i = dst_x; i--;) {
267  r_buf[last_px_id--] = r_buf[last_px_written--];
268  }
269  if (last_px_written < 0) {
270  break;
271  }
272  last_px_id -= skip;
273  memset(&r_buf[last_px_id + 1], 0, skip * sizeof(*r_buf));
274  }
275  memset(r_buf, 0, (last_px_id + 1) * sizeof(*r_buf));
276 }
277 
#define BLI_assert(a)
Definition: BLI_assert.h:46
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
Definition: BLI_rect.h:190
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
Definition: BLI_rect.h:186
unsigned int uint
Definition: BLI_sys_types.h:67
#define ELEM(...)
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
eGPUSelectMode
Definition: GPU_select.h:19
@ GPU_SELECT_NEAREST_SECOND_PASS
Definition: GPU_select.h:23
@ GPU_SELECT_PICK_ALL
Definition: GPU_select.h:25
@ GPU_SELECT_PICK_NEAREST
Definition: GPU_select.h:26
SyclQueue void void * src
eGPUSelectAlgo
Definition: gpu_select.c:26
@ ALGO_GL_QUERY
Definition: gpu_select.c:29
@ ALGO_GL_PICK
Definition: gpu_select.c:32
static GPUSelectState g_select_state
Definition: gpu_select.c:55
uint GPU_select_buffer_remove_by_id(GPUSelectResult *buffer, int hits, uint select_id)
Definition: gpu_select.c:221
uint GPU_select_end(void)
Definition: gpu_select.c:135
const GPUSelectResult * GPU_select_buffer_near(const GPUSelectResult *buffer, int hits)
Definition: gpu_select.c:206
void GPU_select_cache_begin(void)
Definition: gpu_select.c:165
bool GPU_select_is_cached(void)
Definition: gpu_select.c:195
bool GPU_select_load_id(uint id)
Definition: gpu_select.c:117
void GPU_select_cache_load_id(void)
Definition: gpu_select.c:176
void GPU_select_cache_end(void)
Definition: gpu_select.c:184
struct GPUSelectState GPUSelectState
void GPU_select_begin(GPUSelectResult *buffer, const uint buffer_len, const rcti *input, eGPUSelectMode mode, int oldhits)
Definition: gpu_select.c:63
void GPU_select_buffer_stride_realign(const rcti *src, const rcti *dst, uint *r_buf)
Definition: gpu_select.c:239
bool gpu_select_pick_load_id(uint id, bool end)
void gpu_select_pick_begin(GPUSelectResult *buffer, const uint buffer_len, const rcti *input, eGPUSelectMode mode)
bool gpu_select_pick_is_cached(void)
void gpu_select_pick_cache_end(void)
uint gpu_select_pick_end(void)
void gpu_select_pick_cache_begin(void)
void gpu_select_pick_cache_load_id(void)
bool gpu_select_query_load_id(uint id)
void gpu_select_query_begin(GPUSelectResult *buffer, uint buffer_len, const rcti *input, eGPUSelectMode mode, int oldhits)
uint gpu_select_query_end(void)
ccl_global float * buffer
ccl_global KernelShaderEvalInput * input
unsigned int id
Definition: GPU_select.h:34
eGPUSelectAlgo algorithm
Definition: gpu_select.c:41
eGPUSelectMode mode
Definition: gpu_select.c:39
bool select_is_active
Definition: gpu_select.c:37
bool use_cache_needs_init
Definition: gpu_select.c:52
int ymin
Definition: DNA_vec_types.h:64
int ymax
Definition: DNA_vec_types.h:64
int xmin
Definition: DNA_vec_types.h:63
int xmax
Definition: DNA_vec_types.h:63