Blender V5.0
gpu_select_sample_query.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2014 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
11
12#include <cstdlib>
13
14#include "GPU_debug.hh"
15#include "GPU_framebuffer.hh"
16#include "GPU_select.hh"
17#include "GPU_state.hh"
18
19#include "BLI_rect.h"
20
21#include "BLI_utildefines.h"
22#include "BLI_vector.hh"
23
24#include "gpu_backend.hh"
25#include "gpu_query.hh"
26
27#include "gpu_select_private.hh"
28
29using namespace blender;
30using namespace blender::gpu;
31
52
54
56 const rcti *input,
57 const GPUSelectMode mode,
58 int oldhits)
59{
60 GPU_debug_group_begin("Selection Queries");
61
62 g_query_state.query_issued = false;
63 g_query_state.buffer = buffer;
64 g_query_state.mode = mode;
65 g_query_state.index = 0;
66 g_query_state.oldhits = oldhits;
67
71
72 g_query_state.write_mask = GPU_write_mask_get();
73 g_query_state.depth_test = GPU_depth_test_get();
76
77 /* Write to color buffer. Seems to fix issues with selecting alpha blended geom (see #7997). */
78 GPU_color_mask(true, true, true, true);
79
80 /* In order to save some fill rate we minimize the viewport using rect.
81 * We need to get the region of the viewport so that our geometry doesn't
82 * get rejected before the depth test. Should probably cull rect against
83 * the viewport but this is a rare case I think */
84
85 const int viewport[4] = {
87
88 GPU_viewport(UNPACK4(viewport));
89 GPU_scissor(UNPACK4(viewport));
90 GPU_scissor_test(false);
91
92 /* occlusion queries operates on fragments that pass tests and since we are interested on all
93 * objects in the view frustum independently of their order, we need to disable the depth test */
94 if (mode == GPU_SELECT_ALL) {
95 /* #glQueries on Windows+Intel drivers only works with depth testing turned on.
96 * See #62947 for details */
98 GPU_depth_mask(true);
99 }
100 else if (mode == GPU_SELECT_NEAREST_FIRST_PASS) {
102 GPU_depth_mask(true);
103 GPU_clear_depth(1.0f);
104 }
105 else if (mode == GPU_SELECT_NEAREST_SECOND_PASS) {
107 GPU_depth_mask(false);
108 }
109}
110
112{
113 if (g_query_state.query_issued) {
114 g_query_state.queries->end_query();
115 }
116
117 g_query_state.queries->begin_query();
118 g_query_state.ids->append(id);
119 g_query_state.query_issued = true;
120
122 /* Second pass should never run if first pass fails,
123 * can read past `buffer_len` in this case. */
124 BLI_assert(g_query_state.oldhits != -1);
125 if (g_query_state.index < g_query_state.oldhits) {
126 if (g_query_state.buffer->storage[g_query_state.index].id == id) {
127 g_query_state.index++;
128 return true;
129 }
130 return false;
131 }
132 }
133 return true;
134}
135
137{
138 uint hits = 0;
139
140 if (g_query_state.query_issued) {
141 g_query_state.queries->end_query();
142 }
143
144 Span<uint> ids = *g_query_state.ids;
146 g_query_state.queries->get_occlusion_result(result);
147
148 for (int i = 0; i < result.size(); i++) {
149 if (result[i] != 0) {
151 GPUSelectResult hit_result{};
152 hit_result.id = ids[i];
153 hit_result.depth = 0xFFFF;
154 g_query_state.buffer->storage.append(hit_result);
155 hits++;
156 }
157 else {
158 int j;
159 /* search in buffer and make selected object first */
160 for (j = 0; j < g_query_state.oldhits; j++) {
161 if (g_query_state.buffer->storage[j].id == ids[i]) {
162 g_query_state.buffer->storage[j].depth = 0;
163 }
164 }
165 break;
166 }
167 }
168 }
169
170 delete g_query_state.queries;
171 delete g_query_state.ids;
172
173 GPU_write_mask(g_query_state.write_mask);
174 GPU_depth_test(g_query_state.depth_test);
176
178
179 return hits;
180}
#define BLI_assert(a)
Definition BLI_assert.h:46
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
Definition BLI_rect.h:198
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
Definition BLI_rect.h:194
unsigned int uint
#define UNPACK2(a)
#define UNPACK4(a)
void GPU_debug_group_end()
Definition gpu_debug.cc:33
void GPU_debug_group_begin(const char *name)
Definition gpu_debug.cc:22
void GPU_clear_depth(float depth)
GPUSelectMode
Definition GPU_select.hh:18
@ GPU_SELECT_NEAREST_SECOND_PASS
Definition GPU_select.hh:23
@ GPU_SELECT_NEAREST_FIRST_PASS
Definition GPU_select.hh:22
@ GPU_SELECT_ALL
Definition GPU_select.hh:20
void GPU_scissor_test(bool enable)
Definition gpu_state.cc:188
GPUDepthTest
Definition GPU_state.hh:110
@ GPU_DEPTH_EQUAL
Definition GPU_state.hh:115
@ GPU_DEPTH_ALWAYS
Definition GPU_state.hh:112
@ GPU_DEPTH_LESS_EQUAL
Definition GPU_state.hh:114
void GPU_depth_mask(bool depth)
Definition gpu_state.cc:110
void GPU_depth_test(GPUDepthTest test)
Definition gpu_state.cc:68
void GPU_color_mask(bool r, bool g, bool b, bool a)
Definition gpu_state.cc:98
void GPU_viewport_size_get_i(int coords[4])
Definition gpu_state.cc:282
void GPU_scissor(int x, int y, int width, int height)
Definition gpu_state.cc:193
GPUDepthTest GPU_depth_test_get()
Definition gpu_state.cc:244
GPUWriteMask
Definition GPU_state.hh:16
void GPU_viewport(int x, int y, int width, int height)
Definition gpu_state.cc:199
void GPU_write_mask(GPUWriteMask mask)
Definition gpu_state.cc:93
GPUWriteMask GPU_write_mask_get()
Definition gpu_state.cc:232
void GPU_scissor_get(int coords[4])
Definition gpu_state.cc:268
constexpr int64_t size() const
Definition BLI_span.hh:252
static GPUBackend * get()
virtual QueryPool * querypool_alloc()=0
bool gpu_select_query_load_id(uint id)
static GPUSelectQueryState g_query_state
uint gpu_select_query_end()
void gpu_select_query_begin(GPUSelectBuffer *buffer, const rcti *input, const GPUSelectMode mode, int oldhits)
#define input
@ GPU_QUERY_OCCLUSION
Definition gpu_query.hh:18
Vector< uint, QUERY_MIN_LEN > * ids
unsigned int id
Definition GPU_select.hh:34
unsigned int depth
Definition GPU_select.hh:42
i
Definition text_draw.cc:230