Blender  V2.93
gpu_select_sample_query.cc
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2014 Blender Foundation.
17  * All rights reserved.
18  */
19 
27 #include <cstdlib>
28 
29 #include "GPU_debug.h"
30 #include "GPU_framebuffer.h"
31 #include "GPU_select.h"
32 #include "GPU_state.h"
33 
34 #include "MEM_guardedalloc.h"
35 
36 #include "BLI_rect.h"
37 
38 #include "BLI_bitmap.h"
39 #include "BLI_utildefines.h"
40 #include "BLI_vector.hh"
41 
42 #include "gpu_backend.hh"
43 #include "gpu_query.hh"
44 
45 #include "gpu_select_private.h"
46 
47 using namespace blender;
48 using namespace blender::gpu;
49 
51  /* Tracks whether a query has been issued so that gpu_load_id can end the previous one */
53  /* GPU queries abstraction. Contains an array of queries. */
55  /* Array holding the id corresponding id to each query. */
57  /* cache on initialization */
58  uint (*buffer)[4];
59  /* buffer size (stores number of integers, for actual size multiply by sizeof integer)*/
61  /* mode of operation */
62  char mode;
64  int oldhits;
65 
66  /* Previous state to restore after drawing. */
67  int viewport[4];
68  int scissor[4];
71 };
72 
74 
76  uint (*buffer)[4], uint bufsize, const rcti *input, char mode, int oldhits)
77 {
78  GPU_debug_group_begin("Selection Queries");
79 
81  g_query_state.bufsize = bufsize;
83  g_query_state.mode = mode;
84  g_query_state.index = 0;
85  g_query_state.oldhits = oldhits;
86 
90 
95 
96  /* Write to color buffer. Seems to fix issues with selecting alpha blended geom (see T7997). */
97  GPU_color_mask(true, true, true, true);
98 
99  /* In order to save some fill rate we minimize the viewport using rect.
100  * We need to get the region of the viewport so that our geometry doesn't
101  * get rejected before the depth test. Should probably cull rect against
102  * the viewport but this is a rare case I think */
103 
104  int viewport[4] = {
106 
107  GPU_viewport(UNPACK4(viewport));
108  GPU_scissor(UNPACK4(viewport));
109  GPU_scissor_test(false);
110 
111  /* occlusion queries operates on fragments that pass tests and since we are interested on all
112  * objects in the view frustum independently of their order, we need to disable the depth test */
113  if (mode == GPU_SELECT_ALL) {
114  /* glQueries on Windows+Intel drivers only works with depth testing turned on.
115  * See T62947 for details */
117  GPU_depth_mask(true);
118  }
119  else if (mode == GPU_SELECT_NEAREST_FIRST_PASS) {
121  GPU_depth_mask(true);
122  GPU_clear_depth(1.0f);
123  }
124  else if (mode == GPU_SELECT_NEAREST_SECOND_PASS) {
126  GPU_depth_mask(false);
127  }
128 }
129 
131 {
134  }
135 
137  g_query_state.ids->append(id);
139 
141  /* Second pass should never run if first pass fails, can read past 'bufsize' in this case. */
144  if (g_query_state.buffer[g_query_state.index][3] == id) {
146  return true;
147  }
148  return false;
149  }
150  }
151  return true;
152 }
153 
155 {
156  uint hits = 0;
157  const uint maxhits = g_query_state.bufsize;
158 
161  }
162 
166 
167  for (int i = 0; i < result.size(); i++) {
168  if (result[i] != 0) {
170  if (hits < maxhits) {
171  g_query_state.buffer[hits][0] = 1;
172  g_query_state.buffer[hits][1] = 0xFFFF;
173  g_query_state.buffer[hits][2] = 0xFFFF;
174  g_query_state.buffer[hits][3] = ids[i];
175  hits++;
176  }
177  else {
178  hits = -1;
179  break;
180  }
181  }
182  else {
183  int j;
184  /* search in buffer and make selected object first */
185  for (j = 0; j < g_query_state.oldhits; j++) {
186  if (g_query_state.buffer[j][3] == ids[i]) {
187  g_query_state.buffer[j][1] = 0;
188  g_query_state.buffer[j][2] = 0;
189  }
190  }
191  break;
192  }
193  }
194  }
195 
196  delete g_query_state.queries;
197  delete g_query_state.ids;
198 
202 
204 
205  return hits;
206 }
#define BLI_assert(a)
Definition: BLI_assert.h:58
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
Definition: BLI_rect.h:157
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
Definition: BLI_rect.h:153
unsigned int uint
Definition: BLI_sys_types.h:83
#define UNPACK2(a)
#define UNPACK4(a)
void GPU_debug_group_end(void)
Definition: gpu_debug.cc:48
void GPU_debug_group_begin(const char *name)
Definition: gpu_debug.cc:37
@ GPU_SELECT_NEAREST_SECOND_PASS
Definition: GPU_select.h:39
@ GPU_SELECT_NEAREST_FIRST_PASS
Definition: GPU_select.h:38
@ GPU_SELECT_ALL
Definition: GPU_select.h:36
void GPU_write_mask(eGPUWriteMask mask)
Definition: gpu_state.cc:100
void GPU_scissor_test(bool enable)
Definition: gpu_state.cc:199
eGPUWriteMask
Definition: GPU_state.h:25
void GPU_depth_mask(bool depth)
Definition: gpu_state.cc:117
void GPU_color_mask(bool r, bool g, bool b, bool a)
Definition: gpu_state.cc:105
void GPU_viewport_size_get_i(int coords[4])
Definition: gpu_state.cc:288
void GPU_scissor(int x, int y, int width, int height)
Definition: gpu_state.cc:204
eGPUWriteMask GPU_write_mask_get(void)
Definition: gpu_state.cc:243
void GPU_viewport(int x, int y, int width, int height)
Definition: gpu_state.cc:210
eGPUDepthTest
Definition: GPU_state.h:77
@ GPU_DEPTH_EQUAL
Definition: GPU_state.h:82
@ GPU_DEPTH_ALWAYS
Definition: GPU_state.h:79
@ GPU_DEPTH_LESS_EQUAL
Definition: GPU_state.h:81
eGPUDepthTest GPU_depth_test_get(void)
Definition: gpu_state.cc:255
void GPU_depth_test(eGPUDepthTest test)
Definition: gpu_state.cc:75
void GPU_scissor_get(int coords[4])
Definition: gpu_state.cc:274
Read Guarded memory(de)allocation.
constexpr int64_t size() const
Definition: BLI_span.hh:254
void append(const T &value)
Definition: BLI_vector.hh:438
static GPUBackend * get(void)
Definition: gpu_context.cc:191
virtual QueryPool * querypool_alloc(void)=0
virtual void begin_query(void)=0
virtual void init(GPUQueryType type)=0
virtual void end_query(void)=0
virtual void get_occlusion_result(MutableSpan< uint32_t > r_values)=0
void GPU_clear_depth(float depth)
bool gpu_select_query_load_id(uint id)
void gpu_select_query_begin(uint(*buffer)[4], uint bufsize, const rcti *input, char mode, int oldhits)
static GPUSelectQueryState g_query_state
uint gpu_select_query_end(void)
__kernel void ccl_constant KernelData ccl_global void ccl_global char ccl_global int ccl_global char ccl_global unsigned int ccl_global float * buffer
@ GPU_QUERY_OCCLUSION
Definition: gpu_query.hh:31