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.
This commit is contained in:
parent
d4fd363d05
commit
5c2ac8520e
Notes:
blender-bot
2023-02-14 08:21:44 +01:00
Referenced by issue #47030, BMesh booleans (track todo's)
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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. */
|
|
@ -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
|
|
@ -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
|
|
@ -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);
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
Loading…
Reference in New Issue