diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2020-09-08 00:52:55 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2020-09-08 01:02:04 +0300 |
commit | 5c2ac8520e070db2085b7d95d9d232b567edb247 (patch) | |
tree | c91d89789e0e390937c84807dd73cf1637cada70 /source/blender/gpu/intern | |
parent | d4fd363d05943eaf021ef3bff8756cdf96241c0e (diff) |
GPUQuery: GL Backend isolation
This is part of the Vulkan task T68990.
This introduce a new GLQueryPool for managing queries in an
implementation agnostic manner.
This modify the GPU selection query to use this new object.
This also make use of blender::Vector for better code quality.
No real functionnal change.
Diffstat (limited to 'source/blender/gpu/intern')
-rw-r--r-- | source/blender/gpu/intern/gpu_backend.hh | 2 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_query.cc | 28 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_query.hh | 59 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_select_private.h | 8 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_select_sample_query.cc (renamed from source/blender/gpu/intern/gpu_select_sample_query.c) | 85 |
5 files changed, 128 insertions, 54 deletions
diff --git a/source/blender/gpu/intern/gpu_backend.hh b/source/blender/gpu/intern/gpu_backend.hh index d074350e8d0..1a6a6668b42 100644 --- a/source/blender/gpu/intern/gpu_backend.hh +++ b/source/blender/gpu/intern/gpu_backend.hh @@ -34,6 +34,7 @@ class Batch; class DrawList; class FrameBuffer; class IndexBuf; +class QueryPool; class Shader; class Texture; class UniformBuf; @@ -53,6 +54,7 @@ class GPUBackend { virtual DrawList *drawlist_alloc(int list_length) = 0; virtual FrameBuffer *framebuffer_alloc(const char *name) = 0; virtual IndexBuf *indexbuf_alloc(void) = 0; + virtual QueryPool *querypool_alloc(void) = 0; virtual Shader *shader_alloc(const char *name) = 0; virtual Texture *texture_alloc(const char *name) = 0; virtual UniformBuf *uniformbuf_alloc(int size, const char *name) = 0; diff --git a/source/blender/gpu/intern/gpu_query.cc b/source/blender/gpu/intern/gpu_query.cc new file mode 100644 index 00000000000..ad9b6d21420 --- /dev/null +++ b/source/blender/gpu/intern/gpu_query.cc @@ -0,0 +1,28 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright 2020, Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup gpu + */ + +#include "gpu_query.hh" + +using namespace blender::gpu; + +/* TODO(fclem) Make the associated C-API to use inside DRW profiler. */ diff --git a/source/blender/gpu/intern/gpu_query.hh b/source/blender/gpu/intern/gpu_query.hh new file mode 100644 index 00000000000..5e3159a94f7 --- /dev/null +++ b/source/blender/gpu/intern/gpu_query.hh @@ -0,0 +1,59 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright 2020, Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup gpu + */ + +#pragma once + +#include "BLI_span.hh" + +namespace blender::gpu { + +typedef enum GPUQueryType { + GPU_QUERY_OCCLUSION = 0, +} GPUQueryType; + +class QueryPool { + public: + virtual ~QueryPool(){}; + + /** + * Will start and end the query at this index inside the pool. The pool will resize + * automatically but does not support sparse allocation. So prefer using consecutive indices. + */ + virtual void init(GPUQueryType type) = 0; + + /** + * Will start and end the query at this index inside the pool. + * The pool will resize automatically. + */ + virtual void begin_query(void) = 0; + virtual void end_query(void) = 0; + + /** + * Must be fed with a buffer large enough to contain all the queries issued. + * IMPORTANT: Result for each query can be either binary or represent the number of samples + * drawn. + */ + virtual void get_occlusion_result(MutableSpan<uint32_t> r_values) = 0; +}; + +} // namespace blender::gpu
\ No newline at end of file diff --git a/source/blender/gpu/intern/gpu_select_private.h b/source/blender/gpu/intern/gpu_select_private.h index e364b78bff2..f9a1aea8338 100644 --- a/source/blender/gpu/intern/gpu_select_private.h +++ b/source/blender/gpu/intern/gpu_select_private.h @@ -25,6 +25,10 @@ #pragma once +#ifdef __cplusplus +extern "C" { +#endif + /* gpu_select_pick */ void gpu_select_pick_begin(uint (*buffer)[4], uint bufsize, const rcti *input, char mode); bool gpu_select_pick_load_id(uint id, bool end); @@ -42,3 +46,7 @@ bool gpu_select_query_load_id(uint id); uint gpu_select_query_end(void); #define SELECT_ID_NONE ((uint)0xffffffff) + +#ifdef __cplusplus +} +#endif
\ No newline at end of file diff --git a/source/blender/gpu/intern/gpu_select_sample_query.c b/source/blender/gpu/intern/gpu_select_sample_query.cc index 45d52b22664..1b54cbff5dd 100644 --- a/source/blender/gpu/intern/gpu_select_sample_query.c +++ b/source/blender/gpu/intern/gpu_select_sample_query.cc @@ -27,7 +27,6 @@ #include <stdlib.h> #include "GPU_framebuffer.h" -#include "GPU_glew.h" #include "GPU_select.h" #include "GPU_state.h" @@ -35,24 +34,25 @@ #include "BLI_rect.h" +#include "BLI_bitmap.h" #include "BLI_utildefines.h" +#include "BLI_vector.hh" + +#include "gpu_backend.hh" +#include "gpu_query.hh" #include "gpu_select_private.h" -/* Ad hoc number of queries to allocate to skip doing many glGenQueries */ -#define ALLOC_QUERIES 200 +using namespace blender; +using namespace blender::gpu; -typedef struct GPUQueryState { +typedef struct GPUSelectQueryState { /* Tracks whether a query has been issued so that gpu_load_id can end the previous one */ bool query_issued; - /* array holding the OpenGL query identifiers */ - uint *queries; - /* array holding the id corresponding to each query */ - uint *id; - /* number of queries in *queries and *id */ - uint num_of_queries; - /* index to the next query to start */ - uint active_query; + /* GPU queries abstraction. Contains an array of queries. */ + QueryPool *queries; + /* 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 integer)*/ @@ -67,29 +67,23 @@ typedef struct GPUQueryState { int scissor[4]; eGPUWriteMask write_mask; eGPUDepthTest depth_test; -} GPUQueryState; +} GPUSelectQueryState; -static GPUQueryState g_query_state = {0}; +static GPUSelectQueryState g_query_state = {0}; void gpu_select_query_begin( uint (*buffer)[4], uint bufsize, const rcti *input, char mode, int oldhits) { g_query_state.query_issued = false; - g_query_state.active_query = 0; - g_query_state.num_of_queries = 0; g_query_state.bufsize = bufsize; g_query_state.buffer = buffer; g_query_state.mode = mode; g_query_state.index = 0; g_query_state.oldhits = oldhits; - g_query_state.num_of_queries = ALLOC_QUERIES; - - g_query_state.queries = MEM_mallocN( - g_query_state.num_of_queries * sizeof(*g_query_state.queries), "gpu selection queries"); - g_query_state.id = MEM_mallocN(g_query_state.num_of_queries * sizeof(*g_query_state.id), - "gpu selection ids"); - glGenQueries(g_query_state.num_of_queries, g_query_state.queries); + g_query_state.ids = new Vector<uint>(); + g_query_state.queries = GPUBackend::get()->querypool_alloc(); + g_query_state.queries->init(GPU_QUERY_OCCLUSION); g_query_state.write_mask = GPU_write_mask_get(); g_query_state.depth_test = GPU_depth_test_get(); @@ -133,21 +127,11 @@ void gpu_select_query_begin( bool gpu_select_query_load_id(uint id) { if (g_query_state.query_issued) { - glEndQuery(GL_SAMPLES_PASSED); - } - /* if required, allocate extra queries */ - if (g_query_state.active_query == g_query_state.num_of_queries) { - g_query_state.num_of_queries += ALLOC_QUERIES; - g_query_state.queries = MEM_reallocN( - g_query_state.queries, g_query_state.num_of_queries * sizeof(*g_query_state.queries)); - g_query_state.id = MEM_reallocN(g_query_state.id, - g_query_state.num_of_queries * sizeof(*g_query_state.id)); - glGenQueries(ALLOC_QUERIES, &g_query_state.queries[g_query_state.active_query]); + g_query_state.queries->end_query(); } - glBeginQuery(GL_SAMPLES_PASSED, g_query_state.queries[g_query_state.active_query]); - g_query_state.id[g_query_state.active_query] = id; - g_query_state.active_query++; + g_query_state.queries->begin_query(); + g_query_state.ids->append(id); g_query_state.query_issued = true; if (g_query_state.mode == GPU_SELECT_NEAREST_SECOND_PASS) { @@ -158,39 +142,33 @@ bool gpu_select_query_load_id(uint id) g_query_state.index++; return true; } - return false; } } - return true; } uint gpu_select_query_end(void) { - int i; - uint hits = 0; const uint maxhits = g_query_state.bufsize; if (g_query_state.query_issued) { - glEndQuery(GL_SAMPLES_PASSED); + g_query_state.queries->end_query(); } - for (i = 0; i < g_query_state.active_query; i++) { - uint result = 0; - /* We are not using GL_QUERY_RESULT_AVAILABLE and sleep to wait for results, - * because it causes lagging on Windows/NVIDIA, see T61474. */ - glGetQueryObjectuiv(g_query_state.queries[i], GL_QUERY_RESULT, &result); - if (result > 0) { - if (g_query_state.mode != GPU_SELECT_NEAREST_SECOND_PASS) { + Span<uint> ids = *g_query_state.ids; + Vector<uint32_t> result(ids.size()); + g_query_state.queries->get_occlusion_result(result); + for (int i = 0; i < result.size(); i++) { + 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] = g_query_state.id[i]; - + g_query_state.buffer[hits][3] = ids[i]; hits++; } else { @@ -202,7 +180,7 @@ uint gpu_select_query_end(void) 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] == g_query_state.id[i]) { + if (g_query_state.buffer[j][3] == ids[i]) { g_query_state.buffer[j][1] = 0; g_query_state.buffer[j][2] = 0; } @@ -212,9 +190,8 @@ uint gpu_select_query_end(void) } } - glDeleteQueries(g_query_state.num_of_queries, g_query_state.queries); - MEM_freeN(g_query_state.queries); - MEM_freeN(g_query_state.id); + delete g_query_state.queries; + delete g_query_state.ids; GPU_write_mask(g_query_state.write_mask); GPU_depth_test(g_query_state.depth_test); |