Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2020-09-08 00:52:55 +0300
committerClément Foucault <foucault.clem@gmail.com>2020-09-08 01:02:04 +0300
commit5c2ac8520e070db2085b7d95d9d232b567edb247 (patch)
treec91d89789e0e390937c84807dd73cf1637cada70
parentd4fd363d05943eaf021ef3bff8756cdf96241c0e (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.
-rw-r--r--source/blender/gpu/CMakeLists.txt6
-rw-r--r--source/blender/gpu/intern/gpu_backend.hh2
-rw-r--r--source/blender/gpu/intern/gpu_query.cc28
-rw-r--r--source/blender/gpu/intern/gpu_query.hh59
-rw-r--r--source/blender/gpu/intern/gpu_select_private.h8
-rw-r--r--source/blender/gpu/intern/gpu_select_sample_query.cc (renamed from source/blender/gpu/intern/gpu_select_sample_query.c)85
-rw-r--r--source/blender/gpu/opengl/gl_backend.hh6
-rw-r--r--source/blender/gpu/opengl/gl_context.hh16
-rw-r--r--source/blender/gpu/opengl/gl_query.cc78
-rw-r--r--source/blender/gpu/opengl/gl_query.hh69
10 files changed, 294 insertions, 63 deletions
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index 6fdd510ad28..0a372125391 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -74,9 +74,10 @@ set(SRC
intern/gpu_matrix.cc
intern/gpu_node_graph.c
intern/gpu_platform.cc
+ intern/gpu_query.cc
intern/gpu_select.c
intern/gpu_select_pick.c
- intern/gpu_select_sample_query.c
+ intern/gpu_select_sample_query.cc
intern/gpu_shader.cc
intern/gpu_shader_builtin.c
intern/gpu_shader_interface.cc
@@ -95,6 +96,7 @@ set(SRC
opengl/gl_framebuffer.cc
opengl/gl_immediate.cc
opengl/gl_index_buffer.cc
+ opengl/gl_query.cc
opengl/gl_shader.cc
opengl/gl_shader_interface.cc
opengl/gl_state.cc
@@ -146,6 +148,7 @@ set(SRC
intern/gpu_node_graph.h
intern/gpu_private.h
intern/gpu_platform_private.hh
+ intern/gpu_query.hh
intern/gpu_select_private.h
intern/gpu_shader_private.hh
intern/gpu_shader_interface.hh
@@ -164,6 +167,7 @@ set(SRC
opengl/gl_immediate.hh
opengl/gl_index_buffer.hh
opengl/gl_primitive.hh
+ opengl/gl_query.hh
opengl/gl_shader.hh
opengl/gl_shader_interface.hh
opengl/gl_state.hh
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);
diff --git a/source/blender/gpu/opengl/gl_backend.hh b/source/blender/gpu/opengl/gl_backend.hh
index 0c759d2cd62..94ac1692108 100644
--- a/source/blender/gpu/opengl/gl_backend.hh
+++ b/source/blender/gpu/opengl/gl_backend.hh
@@ -32,6 +32,7 @@
#include "gl_drawlist.hh"
#include "gl_framebuffer.hh"
#include "gl_index_buffer.hh"
+#include "gl_query.hh"
#include "gl_shader.hh"
#include "gl_texture.hh"
#include "gl_uniform_buffer.hh"
@@ -95,6 +96,11 @@ class GLBackend : public GPUBackend {
return new GLIndexBuf();
};
+ QueryPool *querypool_alloc(void) override
+ {
+ return new GLQueryPool();
+ };
+
Shader *shader_alloc(const char *name) override
{
return new GLShader(name);
diff --git a/source/blender/gpu/opengl/gl_context.hh b/source/blender/gpu/opengl/gl_context.hh
index f05029c7075..8bce0d2e345 100644
--- a/source/blender/gpu/opengl/gl_context.hh
+++ b/source/blender/gpu/opengl/gl_context.hh
@@ -68,13 +68,13 @@ class GLContext : public GPUContext {
static bool unused_fb_slot_workaround;
static float derivative_signs[2];
+ /** VBO for missing vertex attrib binding. Avoid undefined behavior on some implementation. */
+ GLuint default_attr_vbo_;
+
/** Used for debugging purpose. Bitflags of all bound slots. */
uint16_t bound_ubo_slots;
- /* TODO(fclem) these needs to become private. */
- public:
- /** VBO for missing vertex attrib binding. Avoid undefined behavior on some implementation. */
- GLuint default_attr_vbo_;
+ private:
/**
* GPUBatch & GPUFramebuffer have references to the context they are from, in the case the
* context is destroyed, we need to remove any reference to it.
@@ -112,12 +112,12 @@ class GLContext : public GPUContext {
static void buf_free(GLuint buf_id);
static void tex_free(GLuint tex_id);
- /* TODO(fclem) these needs to become private. */
- public:
- static void orphans_add(Vector<GLuint> &orphan_list, std::mutex &list_mutex, GLuint id);
- void orphans_clear(void);
void vao_cache_register(GLVaoCache *cache);
void vao_cache_unregister(GLVaoCache *cache);
+
+ private:
+ static void orphans_add(Vector<GLuint> &orphan_list, std::mutex &list_mutex, GLuint id);
+ void orphans_clear(void);
};
} // namespace gpu
diff --git a/source/blender/gpu/opengl/gl_query.cc b/source/blender/gpu/opengl/gl_query.cc
new file mode 100644
index 00000000000..6da5cacfcb2
--- /dev/null
+++ b/source/blender/gpu/opengl/gl_query.cc
@@ -0,0 +1,78 @@
+/*
+ * 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 "gl_query.hh"
+
+namespace blender::gpu {
+
+#define QUERY_CHUNCK_LEN 256
+
+GLQueryPool::~GLQueryPool()
+{
+ glDeleteQueries(query_ids_.size(), query_ids_.data());
+}
+
+void GLQueryPool::init(GPUQueryType type)
+{
+ BLI_assert(initialized_ == false);
+ initialized_ = true;
+ type_ = type;
+ gl_type_ = to_gl(type);
+ query_issued_ = 0;
+}
+
+#if 0 /* TODO to avoid realloc of permanent query pool. */
+void GLQueryPool::reset(GPUQueryType type)
+{
+ initialized_ = false;
+}
+#endif
+
+void GLQueryPool::begin_query(void)
+{
+ /* TODO add assert about expected usage. */
+ while (query_issued_ >= query_ids_.size()) {
+ int64_t prev_size = query_ids_.size();
+ query_ids_.resize(prev_size + QUERY_CHUNCK_LEN);
+ glGenQueries(QUERY_CHUNCK_LEN, &query_ids_[prev_size]);
+ }
+ glBeginQuery(gl_type_, query_ids_[query_issued_++]);
+}
+
+void GLQueryPool::end_query(void)
+{
+ /* TODO add assert about expected usage. */
+ glEndQuery(gl_type_);
+}
+
+void GLQueryPool::get_occlusion_result(MutableSpan<uint32_t> r_values)
+{
+ BLI_assert(r_values.size() == query_issued_);
+
+ for (int i = 0; i < query_issued_; i++) {
+ /* Note: This is a sync point. */
+ glGetQueryObjectuiv(query_ids_[i], GL_QUERY_RESULT, &r_values[i]);
+ }
+}
+
+} // namespace blender::gpu
diff --git a/source/blender/gpu/opengl/gl_query.hh b/source/blender/gpu/opengl/gl_query.hh
new file mode 100644
index 00000000000..fc54c0ee1dd
--- /dev/null
+++ b/source/blender/gpu/opengl/gl_query.hh
@@ -0,0 +1,69 @@
+/*
+ * 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_vector.hh"
+
+#include "gpu_query.hh"
+
+#include "glew-mx.h"
+
+namespace blender::gpu {
+
+class GLQueryPool : public QueryPool {
+ private:
+ /** Contains queries object handles. */
+ Vector<GLuint> query_ids_;
+ /** Type of this query pool. */
+ GPUQueryType type_;
+ /** Associated GL type. */
+ GLenum gl_type_;
+ /** Number of queries that have been issued since last initialization.
+ * Should be equal to query_ids_.size(). */
+ uint32_t query_issued_;
+ /** Can only be initialized once. */
+ bool initialized_ = false;
+
+ public:
+ ~GLQueryPool();
+
+ void init(GPUQueryType type) override;
+
+ void begin_query(void) override;
+ void end_query(void) override;
+
+ void get_occlusion_result(MutableSpan<uint32_t> r_values) override;
+};
+
+static inline GLenum to_gl(GPUQueryType type)
+{
+ if (type == GPU_QUERY_OCCLUSION) {
+ /* TODO(fclem) try with GL_ANY_SAMPLES_PASSED​. */
+ return GL_SAMPLES_PASSED;
+ }
+ BLI_assert(0);
+ return GL_SAMPLES_PASSED;
+}
+
+} // namespace blender::gpu \ No newline at end of file