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:
Diffstat (limited to 'source/blender/gpu/opengl')
-rw-r--r--source/blender/gpu/opengl/gl_backend.hh11
-rw-r--r--source/blender/gpu/opengl/gl_batch.cc57
-rw-r--r--source/blender/gpu/opengl/gl_batch.hh19
-rw-r--r--source/blender/gpu/opengl/gl_context.cc35
-rw-r--r--source/blender/gpu/opengl/gl_context.hh15
-rw-r--r--source/blender/gpu/opengl/gl_drawlist.hh6
-rw-r--r--source/blender/gpu/opengl/gl_shader.cc13
-rw-r--r--source/blender/gpu/opengl/gl_shader.hh10
-rw-r--r--source/blender/gpu/opengl/gl_shader_interface.cc297
-rw-r--r--source/blender/gpu/opengl/gl_shader_interface.hh63
-rw-r--r--source/blender/gpu/opengl/gl_state.cc22
-rw-r--r--source/blender/gpu/opengl/gl_state.hh6
-rw-r--r--source/blender/gpu/opengl/gl_uniform_buffer.cc126
-rw-r--r--source/blender/gpu/opengl/gl_uniform_buffer.hh58
-rw-r--r--source/blender/gpu/opengl/gl_vertex_array.cc14
-rw-r--r--source/blender/gpu/opengl/gl_vertex_array.hh4
16 files changed, 694 insertions, 62 deletions
diff --git a/source/blender/gpu/opengl/gl_backend.hh b/source/blender/gpu/opengl/gl_backend.hh
index 63a14af6612..0234c1a3f63 100644
--- a/source/blender/gpu/opengl/gl_backend.hh
+++ b/source/blender/gpu/opengl/gl_backend.hh
@@ -31,6 +31,7 @@
#include "gl_context.hh"
#include "gl_drawlist.hh"
#include "gl_shader.hh"
+#include "gl_uniform_buffer.hh"
namespace blender {
namespace gpu {
@@ -40,6 +41,11 @@ class GLBackend : public GPUBackend {
GLSharedOrphanLists shared_orphan_list_;
public:
+ static GLBackend *get(void)
+ {
+ return static_cast<GLBackend *>(GPUBackend::get());
+ }
+
GPUContext *context_alloc(void *ghost_window)
{
return new GLContext(ghost_window, shared_orphan_list_);
@@ -60,6 +66,11 @@ class GLBackend : public GPUBackend {
return new GLShader(name);
};
+ UniformBuf *uniformbuf_alloc(int size, const char *name)
+ {
+ return new GLUniformBuf(size, name);
+ };
+
/* TODO remove */
void buf_free(GLuint buf_id);
void tex_free(GLuint tex_id);
diff --git a/source/blender/gpu/opengl/gl_batch.cc b/source/blender/gpu/opengl/gl_batch.cc
index fade8763065..7d6270bca93 100644
--- a/source/blender/gpu/opengl/gl_batch.cc
+++ b/source/blender/gpu/opengl/gl_batch.cc
@@ -33,6 +33,7 @@
#include "gpu_batch_private.hh"
#include "gpu_primitive_private.h"
+#include "gpu_shader_private.hh"
#include "gl_batch.hh"
#include "gl_context.hh"
@@ -68,10 +69,11 @@ void GLVaoCache::init(void)
}
vao_base_instance_ = 0;
base_instance_ = 0;
+ vao_id_ = 0;
}
/* Create a new VAO object and store it in the cache. */
-void GLVaoCache::insert(const GPUShaderInterface *interface, GLuint vao)
+void GLVaoCache::insert(const GLShaderInterface *interface, GLuint vao)
{
/* Now insert the cache. */
if (!is_dynamic_vao_count) {
@@ -90,8 +92,7 @@ void GLVaoCache::insert(const GPUShaderInterface *interface, GLuint vao)
/* Erase previous entries, they will be added back if drawn again. */
for (int i = 0; i < GPU_VAO_STATIC_LEN; i++) {
if (static_vaos.interfaces[i] != NULL) {
- GPU_shaderinterface_remove_batch_ref(
- const_cast<GPUShaderInterface *>(static_vaos.interfaces[i]), this);
+ const_cast<GLShaderInterface *>(static_vaos.interfaces[i])->ref_remove(this);
context_->vao_free(static_vaos.vao_ids[i]);
}
}
@@ -99,8 +100,8 @@ void GLVaoCache::insert(const GPUShaderInterface *interface, GLuint vao)
is_dynamic_vao_count = true;
/* Init dynamic arrays and let the branch below set the values. */
dynamic_vaos.count = GPU_BATCH_VAO_DYN_ALLOC_COUNT;
- dynamic_vaos.interfaces = (const GPUShaderInterface **)MEM_callocN(
- dynamic_vaos.count * sizeof(GPUShaderInterface *), "dyn vaos interfaces");
+ dynamic_vaos.interfaces = (const GLShaderInterface **)MEM_callocN(
+ dynamic_vaos.count * sizeof(GLShaderInterface *), "dyn vaos interfaces");
dynamic_vaos.vao_ids = (GLuint *)MEM_callocN(dynamic_vaos.count * sizeof(GLuint),
"dyn vaos ids");
}
@@ -118,8 +119,8 @@ void GLVaoCache::insert(const GPUShaderInterface *interface, GLuint vao)
/* Not enough place, realloc the array. */
i = dynamic_vaos.count;
dynamic_vaos.count += GPU_BATCH_VAO_DYN_ALLOC_COUNT;
- dynamic_vaos.interfaces = (const GPUShaderInterface **)MEM_recallocN(
- (void *)dynamic_vaos.interfaces, sizeof(GPUShaderInterface *) * dynamic_vaos.count);
+ dynamic_vaos.interfaces = (const GLShaderInterface **)MEM_recallocN(
+ (void *)dynamic_vaos.interfaces, sizeof(GLShaderInterface *) * dynamic_vaos.count);
dynamic_vaos.vao_ids = (GLuint *)MEM_recallocN(dynamic_vaos.vao_ids,
sizeof(GLuint) * dynamic_vaos.count);
}
@@ -127,15 +128,15 @@ void GLVaoCache::insert(const GPUShaderInterface *interface, GLuint vao)
dynamic_vaos.vao_ids[i] = vao;
}
- GPU_shaderinterface_add_batch_ref(const_cast<GPUShaderInterface *>(interface), this);
+ const_cast<GLShaderInterface *>(interface)->ref_add(this);
}
-void GLVaoCache::remove(const GPUShaderInterface *interface)
+void GLVaoCache::remove(const GLShaderInterface *interface)
{
const int count = (is_dynamic_vao_count) ? dynamic_vaos.count : GPU_VAO_STATIC_LEN;
GLuint *vaos = (is_dynamic_vao_count) ? dynamic_vaos.vao_ids : static_vaos.vao_ids;
- const GPUShaderInterface **interfaces = (is_dynamic_vao_count) ? dynamic_vaos.interfaces :
- static_vaos.interfaces;
+ const GLShaderInterface **interfaces = (is_dynamic_vao_count) ? dynamic_vaos.interfaces :
+ static_vaos.interfaces;
for (int i = 0; i < count; i++) {
if (interfaces[i] == interface) {
context_->vao_free(vaos[i]);
@@ -151,8 +152,8 @@ void GLVaoCache::clear(void)
GLContext *ctx = static_cast<GLContext *>(GPU_context_active_get());
const int count = (is_dynamic_vao_count) ? dynamic_vaos.count : GPU_VAO_STATIC_LEN;
GLuint *vaos = (is_dynamic_vao_count) ? dynamic_vaos.vao_ids : static_vaos.vao_ids;
- const GPUShaderInterface **interfaces = (is_dynamic_vao_count) ? dynamic_vaos.interfaces :
- static_vaos.interfaces;
+ const GLShaderInterface **interfaces = (is_dynamic_vao_count) ? dynamic_vaos.interfaces :
+ static_vaos.interfaces;
/* Early out, nothing to free. */
if (context_ == NULL) {
return;
@@ -171,10 +172,9 @@ void GLVaoCache::clear(void)
}
for (int i = 0; i < count; i++) {
- if (interfaces[i] == NULL) {
- continue;
+ if (interfaces[i] != NULL) {
+ const_cast<GLShaderInterface *>(interfaces[i])->ref_remove(this);
}
- GPU_shaderinterface_remove_batch_ref(const_cast<GPUShaderInterface *>(interfaces[i]), this);
}
if (is_dynamic_vao_count) {
@@ -190,11 +190,11 @@ void GLVaoCache::clear(void)
}
/* Return 0 on cache miss (invalid VAO) */
-GLuint GLVaoCache::lookup(const GPUShaderInterface *interface)
+GLuint GLVaoCache::lookup(const GLShaderInterface *interface)
{
const int count = (is_dynamic_vao_count) ? dynamic_vaos.count : GPU_VAO_STATIC_LEN;
- const GPUShaderInterface **interfaces = (is_dynamic_vao_count) ? dynamic_vaos.interfaces :
- static_vaos.interfaces;
+ const GLShaderInterface **interfaces = (is_dynamic_vao_count) ? dynamic_vaos.interfaces :
+ static_vaos.interfaces;
for (int i = 0; i < count; i++) {
if (interfaces[i] == interface) {
return (is_dynamic_vao_count) ? dynamic_vaos.vao_ids[i] : static_vaos.vao_ids[i];
@@ -226,7 +226,9 @@ GLuint GLVaoCache::base_instance_vao_get(GPUBatch *batch, int i_first)
{
this->context_check();
/* Make sure the interface is up to date. */
- if (interface_ != GPU_context_active_get()->shader->interface) {
+ Shader *shader = GPU_context_active_get()->shader;
+ GLShaderInterface *interface = static_cast<GLShaderInterface *>(shader->interface);
+ if (interface_ != interface) {
vao_get(batch);
/* Trigger update. */
base_instance_ = 0;
@@ -238,6 +240,7 @@ GLuint GLVaoCache::base_instance_vao_get(GPUBatch *batch, int i_first)
#ifdef __APPLE__
glDeleteVertexArrays(1, &vao_base_instance_);
vao_base_instance_ = 0;
+ base_instance_ = 0;
#endif
if (vao_base_instance_ == 0) {
@@ -248,16 +251,17 @@ GLuint GLVaoCache::base_instance_vao_get(GPUBatch *batch, int i_first)
base_instance_ = i_first;
GLVertArray::update_bindings(vao_base_instance_, batch, interface_, i_first);
}
- return base_instance_;
+ return vao_base_instance_;
}
GLuint GLVaoCache::vao_get(GPUBatch *batch)
{
this->context_check();
- GPUContext *ctx = GPU_context_active_get();
- if (interface_ != ctx->shader->interface) {
- interface_ = ctx->shader->interface;
+ Shader *shader = GPU_context_active_get()->shader;
+ GLShaderInterface *interface = static_cast<GLShaderInterface *>(shader->interface);
+ if (interface_ != interface) {
+ interface_ = interface;
vao_id_ = this->lookup(interface_);
if (vao_id_ == 0) {
@@ -303,6 +307,7 @@ void GLBatch::bind(int i_first)
GPU_context_active_get()->state_manager->apply_state();
if (flag & GPU_BATCH_DIRTY) {
+ flag &= ~GPU_BATCH_DIRTY;
vao_cache_.clear();
}
@@ -324,6 +329,8 @@ void GLBatch::bind(int i_first)
void GLBatch::draw(int v_first, int v_count, int i_first, int i_count)
{
+ GL_CHECK_ERROR("Batch Pre drawing");
+
this->bind(i_first);
BLI_assert(v_count > 0 && i_count > 0);
@@ -350,6 +357,7 @@ void GLBatch::draw(int v_first, int v_count, int i_first, int i_count)
glDrawElementsInstancedBaseVertex(
gl_type, v_count, index_type, v_first_ofs, i_count, base_index);
}
+ GL_CHECK_ERROR("Batch Post-drawing Indexed");
}
else {
#ifdef __APPLE__
@@ -364,6 +372,7 @@ void GLBatch::draw(int v_first, int v_count, int i_first, int i_count)
#ifdef __APPLE__
glEnable(GL_PRIMITIVE_RESTART);
#endif
+ GL_CHECK_ERROR("Batch Post-drawing Non-indexed");
}
}
diff --git a/source/blender/gpu/opengl/gl_batch.hh b/source/blender/gpu/opengl/gl_batch.hh
index d70f43aed2a..9399148c68d 100644
--- a/source/blender/gpu/opengl/gl_batch.hh
+++ b/source/blender/gpu/opengl/gl_batch.hh
@@ -32,11 +32,12 @@
#include "glew-mx.h"
-#include "GPU_shader_interface.h"
-
namespace blender {
namespace gpu {
+class GLContext;
+class GLShaderInterface;
+
#define GPU_VAO_STATIC_LEN 3
/* Vao management: remembers all geometry state (vertex attribute bindings & element buffer)
@@ -45,9 +46,9 @@ namespace gpu {
class GLVaoCache {
private:
/** Context for which the vao_cache_ was generated. */
- struct GLContext *context_ = NULL;
+ GLContext *context_ = NULL;
/** Last interface this batch was drawn with. */
- GPUShaderInterface *interface_ = NULL;
+ GLShaderInterface *interface_ = NULL;
/** Cached vao for the last interface. */
GLuint vao_id_ = 0;
/** Used whend arb_base_instance is not supported. */
@@ -58,13 +59,13 @@ class GLVaoCache {
union {
/** Static handle count */
struct {
- const GPUShaderInterface *interfaces[GPU_VAO_STATIC_LEN];
+ const GLShaderInterface *interfaces[GPU_VAO_STATIC_LEN];
GLuint vao_ids[GPU_VAO_STATIC_LEN];
} static_vaos;
/** Dynamic handle count */
struct {
uint count;
- const GPUShaderInterface **interfaces;
+ const GLShaderInterface **interfaces;
GLuint *vao_ids;
} dynamic_vaos;
};
@@ -76,9 +77,9 @@ class GLVaoCache {
GLuint vao_get(GPUBatch *batch);
GLuint base_instance_vao_get(GPUBatch *batch, int i_first);
- GLuint lookup(const GPUShaderInterface *interface);
- void insert(const GPUShaderInterface *interface, GLuint vao_id);
- void remove(const GPUShaderInterface *interface);
+ GLuint lookup(const GLShaderInterface *interface);
+ void insert(const GLShaderInterface *interface, GLuint vao_id);
+ void remove(const GLShaderInterface *interface);
void clear(void);
private:
diff --git a/source/blender/gpu/opengl/gl_context.cc b/source/blender/gpu/opengl/gl_context.cc
index 11f313f639b..2ac361d28e1 100644
--- a/source/blender/gpu/opengl/gl_context.cc
+++ b/source/blender/gpu/opengl/gl_context.cc
@@ -22,6 +22,7 @@
*/
#include "BLI_assert.h"
+#include "BLI_system.h"
#include "BLI_utildefines.h"
#include "GPU_framebuffer.h"
@@ -238,3 +239,37 @@ void GLContext::framebuffer_unregister(struct GPUFrameBuffer *fb)
}
/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Error Checking
+ *
+ * This is only useful for implementation that does not support the KHR_debug extension.
+ * \{ */
+
+void GLContext::check_error(const char *info)
+{
+ GLenum error = glGetError();
+
+#define ERROR_CASE(err) \
+ case err: \
+ fprintf(stderr, "GL error: %s : %s\n", #err, info); \
+ BLI_system_backtrace(stderr); \
+ break;
+
+ switch (error) {
+ ERROR_CASE(GL_INVALID_ENUM)
+ ERROR_CASE(GL_INVALID_VALUE)
+ ERROR_CASE(GL_INVALID_OPERATION)
+ ERROR_CASE(GL_INVALID_FRAMEBUFFER_OPERATION)
+ ERROR_CASE(GL_OUT_OF_MEMORY)
+ ERROR_CASE(GL_STACK_UNDERFLOW)
+ ERROR_CASE(GL_STACK_OVERFLOW)
+ case GL_NO_ERROR:
+ break;
+ default:
+ fprintf(stderr, "Unknown GL error: %x : %s", error, info);
+ break;
+ }
+}
+
+/** \} */
diff --git a/source/blender/gpu/opengl/gl_context.hh b/source/blender/gpu/opengl/gl_context.hh
index 0b762c939f1..35121a960ba 100644
--- a/source/blender/gpu/opengl/gl_context.hh
+++ b/source/blender/gpu/opengl/gl_context.hh
@@ -32,13 +32,20 @@
#include "glew-mx.h"
-#include "gl_batch.hh"
-
#include <mutex>
+/* Enabled on MacOS by default since there is no support for debug callbacks. */
+#if defined(DEBUG) && defined(__APPLE__)
+# define GL_CHECK_ERROR(info) GLContext::check_error(info)
+#else
+# define GL_CHECK_ERROR(info)
+#endif
+
namespace blender {
namespace gpu {
+class GLVaoCache;
+
class GLSharedOrphanLists {
public:
/** Mutex for the bellow structures. */
@@ -51,7 +58,7 @@ class GLSharedOrphanLists {
void orphans_clear(void);
};
-struct GLContext : public GPUContext {
+class GLContext : public GPUContext {
/* TODO(fclem) these needs to become private. */
public:
/** Default VAO for procedural draw calls. */
@@ -78,6 +85,8 @@ struct GLContext : public GPUContext {
GLContext(void *ghost_window, GLSharedOrphanLists &shared_orphan_list);
~GLContext();
+ static void check_error(const char *info);
+
void activate(void) override;
void deactivate(void) override;
diff --git a/source/blender/gpu/opengl/gl_drawlist.hh b/source/blender/gpu/opengl/gl_drawlist.hh
index 4f085149388..b690b8f8a98 100644
--- a/source/blender/gpu/opengl/gl_drawlist.hh
+++ b/source/blender/gpu/opengl/gl_drawlist.hh
@@ -19,6 +19,9 @@
/** \file
* \ingroup gpu
+ *
+ * Implementation of Multi Draw Indirect using OpenGL.
+ * Fallback if the needed extensions are not supported.
*/
#pragma once
@@ -37,6 +40,9 @@
namespace blender {
namespace gpu {
+/**
+ * Implementation of Multi Draw Indirect using OpenGL.
+ **/
class GLDrawList : public DrawList {
public:
GLDrawList(int length);
diff --git a/source/blender/gpu/opengl/gl_shader.cc b/source/blender/gpu/opengl/gl_shader.cc
index ea33ff00d69..3ec818b53a6 100644
--- a/source/blender/gpu/opengl/gl_shader.cc
+++ b/source/blender/gpu/opengl/gl_shader.cc
@@ -29,6 +29,7 @@
#include "GPU_platform.h"
#include "gl_shader.hh"
+#include "gl_shader_interface.hh"
using namespace blender;
using namespace blender::gpu;
@@ -48,7 +49,7 @@ GLShader::GLShader(const char *name) : Shader(name)
#ifndef __APPLE__
if ((G.debug & G_DEBUG_GPU) && (GLEW_VERSION_4_3 || GLEW_KHR_debug)) {
char sh_name[64];
- BLI_snprintf(sh_name, sizeof(sh_name), "ShaderProgram-%s", name);
+ SNPRINTF(sh_name, "ShaderProgram-%s", name);
glObjectLabel(GL_PROGRAM, shader_program_, -1, sh_name);
}
#endif
@@ -150,6 +151,7 @@ GLuint GLShader::create_shader_stage(GLenum gl_stage, MutableSpan<const char *>
}
if (!status) {
glDeleteShader(shader);
+ compilation_failed_ = true;
return 0;
}
@@ -192,6 +194,10 @@ void GLShader::fragment_shader_from_glsl(MutableSpan<const char *> sources)
bool GLShader::finalize(void)
{
+ if (compilation_failed_) {
+ return false;
+ }
+
glLinkProgram(shader_program_);
GLint status;
@@ -203,10 +209,7 @@ bool GLShader::finalize(void)
return false;
}
- /* TODO(fclem) We need this to modify the image binding points using glUniform.
- * This could be avoided using glProgramUniform in GL 4.1. */
- glUseProgram(shader_program_);
- interface = GPU_shaderinterface_create(shader_program_);
+ interface = new GLShaderInterface(shader_program_);
return true;
}
diff --git a/source/blender/gpu/opengl/gl_shader.hh b/source/blender/gpu/opengl/gl_shader.hh
index b432a04abaa..a686014f4c5 100644
--- a/source/blender/gpu/opengl/gl_shader.hh
+++ b/source/blender/gpu/opengl/gl_shader.hh
@@ -19,9 +19,6 @@
/** \file
* \ingroup gpu
- *
- * GPUDrawList is an API to do lots of similar draw-calls very fast using
- * multi-draw-indirect. There is a fallback if the feature is not supported.
*/
#pragma once
@@ -35,14 +32,19 @@
namespace blender {
namespace gpu {
+/**
+ * Implementation of shader compilation and uniforms handling using OpenGL.
+ **/
class GLShader : public Shader {
private:
/** Handle for full program (links shader stages below). */
GLuint shader_program_ = 0;
-
+ /** Individual shader stages. */
GLuint vert_shader_ = 0;
GLuint geom_shader_ = 0;
GLuint frag_shader_ = 0;
+ /** True if any shader failed to compile. */
+ bool compilation_failed_ = false;
eGPUShaderTFBType transform_feedback_type_ = GPU_SHADER_TFB_NONE;
diff --git a/source/blender/gpu/opengl/gl_shader_interface.cc b/source/blender/gpu/opengl/gl_shader_interface.cc
new file mode 100644
index 00000000000..423db5c8c97
--- /dev/null
+++ b/source/blender/gpu/opengl/gl_shader_interface.cc
@@ -0,0 +1,297 @@
+/*
+ * 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.
+ *
+ * The Original Code is Copyright (C) 2016 by Mike Erwin.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup gpu
+ *
+ * GPU shader interface (C --> GLSL)
+ */
+
+#include "BLI_bitmap.h"
+
+#include "gl_batch.hh"
+
+#include "gl_shader_interface.hh"
+
+namespace blender::gpu {
+
+/* -------------------------------------------------------------------- */
+/** \name Binding assignment
+ *
+ * To mimic vulkan, we assign binding at shader creation to avoid shader recompilation.
+ * In the future, we should set it in the shader using layout(binding = i) and query its value.
+ * \{ */
+
+static inline int block_binding(int32_t program, uint32_t block_index)
+{
+ /* For now just assign a consecutive index. In the future, we should set it in
+ * the shader using layout(binding = i) and query its value. */
+ glUniformBlockBinding(program, block_index, block_index);
+ return block_index;
+}
+
+static inline int sampler_binding(int32_t program,
+ uint32_t uniform_index,
+ int32_t uniform_location,
+ int *sampler_len)
+{
+ /* Identify sampler uniforms and asign sampler units to them. */
+ GLint type;
+ glGetActiveUniformsiv(program, 1, &uniform_index, GL_UNIFORM_TYPE, &type);
+
+ switch (type) {
+ case GL_SAMPLER_1D:
+ case GL_SAMPLER_2D:
+ case GL_SAMPLER_3D:
+ case GL_SAMPLER_CUBE:
+ case GL_SAMPLER_CUBE_MAP_ARRAY_ARB: /* OpenGL 4.0 */
+ case GL_SAMPLER_1D_SHADOW:
+ case GL_SAMPLER_2D_SHADOW:
+ case GL_SAMPLER_1D_ARRAY:
+ case GL_SAMPLER_2D_ARRAY:
+ case GL_SAMPLER_1D_ARRAY_SHADOW:
+ case GL_SAMPLER_2D_ARRAY_SHADOW:
+ case GL_SAMPLER_2D_MULTISAMPLE:
+ case GL_SAMPLER_2D_MULTISAMPLE_ARRAY:
+ case GL_SAMPLER_CUBE_SHADOW:
+ case GL_SAMPLER_BUFFER:
+ case GL_INT_SAMPLER_1D:
+ case GL_INT_SAMPLER_2D:
+ case GL_INT_SAMPLER_3D:
+ case GL_INT_SAMPLER_CUBE:
+ case GL_INT_SAMPLER_1D_ARRAY:
+ case GL_INT_SAMPLER_2D_ARRAY:
+ case GL_INT_SAMPLER_2D_MULTISAMPLE:
+ case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
+ case GL_INT_SAMPLER_BUFFER:
+ case GL_UNSIGNED_INT_SAMPLER_1D:
+ case GL_UNSIGNED_INT_SAMPLER_2D:
+ case GL_UNSIGNED_INT_SAMPLER_3D:
+ case GL_UNSIGNED_INT_SAMPLER_CUBE:
+ case GL_UNSIGNED_INT_SAMPLER_1D_ARRAY:
+ case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
+ case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
+ case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
+ case GL_UNSIGNED_INT_SAMPLER_BUFFER: {
+ /* For now just assign a consecutive index. In the future, we should set it in
+ * the shader using layout(binding = i) and query its value. */
+ int binding = *sampler_len;
+ glUniform1i(uniform_location, binding);
+ (*sampler_len)++;
+ return binding;
+ }
+ default:
+ return -1;
+ }
+}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Creation / Destruction
+ * \{ */
+
+GLShaderInterface::GLShaderInterface(GLuint program)
+{
+ /* Necessary to make glUniform works. */
+ glUseProgram(program);
+
+ GLint max_attr_name_len = 0, attr_len = 0;
+ glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_attr_name_len);
+ glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &attr_len);
+
+ GLint max_ubo_name_len = 0, ubo_len = 0;
+ glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &max_ubo_name_len);
+ glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCKS, &ubo_len);
+
+ GLint max_uniform_name_len = 0, active_uniform_len = 0, uniform_len = 0;
+ glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_uniform_name_len);
+ glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &active_uniform_len);
+ uniform_len = active_uniform_len;
+
+ /* Work around driver bug with Intel HD 4600 on Windows 7/8, where
+ * GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH does not work. */
+ if (attr_len > 0 && max_attr_name_len == 0) {
+ max_attr_name_len = 256;
+ }
+ if (ubo_len > 0 && max_ubo_name_len == 0) {
+ max_ubo_name_len = 256;
+ }
+ if (uniform_len > 0 && max_uniform_name_len == 0) {
+ max_uniform_name_len = 256;
+ }
+
+ /* GL_ACTIVE_UNIFORMS lied to us! Remove the UBO uniforms from the total before
+ * allocating the uniform array. */
+ GLint max_ubo_uni_len = 0;
+ for (int i = 0; i < ubo_len; i++) {
+ GLint ubo_uni_len;
+ glGetActiveUniformBlockiv(program, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &ubo_uni_len);
+ max_ubo_uni_len = max_ii(max_ubo_uni_len, ubo_uni_len);
+ uniform_len -= ubo_uni_len;
+ }
+ /* Bit set to true if uniform comes from a uniform block. */
+ BLI_bitmap *uniforms_from_blocks = BLI_BITMAP_NEW(active_uniform_len, __func__);
+ /* Set uniforms from block for exclusion. */
+ GLint *ubo_uni_ids = (GLint *)MEM_mallocN(sizeof(GLint) * max_ubo_uni_len, __func__);
+ for (int i = 0; i < ubo_len; i++) {
+ GLint ubo_uni_len;
+ glGetActiveUniformBlockiv(program, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &ubo_uni_len);
+ glGetActiveUniformBlockiv(program, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, ubo_uni_ids);
+ for (int u = 0; u < ubo_uni_len; u++) {
+ BLI_BITMAP_ENABLE(uniforms_from_blocks, ubo_uni_ids[u]);
+ }
+ }
+ MEM_freeN(ubo_uni_ids);
+
+ int input_tot_len = attr_len + ubo_len + uniform_len;
+ inputs_ = (ShaderInput *)MEM_callocN(sizeof(ShaderInput) * input_tot_len, __func__);
+
+ const uint32_t name_buffer_len = attr_len * max_attr_name_len + ubo_len * max_ubo_name_len +
+ uniform_len * max_uniform_name_len;
+ name_buffer_ = (char *)MEM_mallocN(name_buffer_len, "name_buffer");
+ uint32_t name_buffer_offset = 0;
+
+ /* Attributes */
+ enabled_attr_mask_ = 0;
+ for (int i = 0; i < attr_len; i++) {
+ char *name = name_buffer_ + name_buffer_offset;
+ GLsizei remaining_buffer = name_buffer_len - name_buffer_offset;
+ GLsizei name_len = 0;
+ GLenum type;
+ GLint size;
+
+ glGetActiveAttrib(program, i, remaining_buffer, &name_len, &size, &type, name);
+ GLint location = glGetAttribLocation(program, name);
+ /* Ignore OpenGL names like `gl_BaseInstanceARB`, `gl_InstanceID` and `gl_VertexID`. */
+ if (location == -1) {
+ continue;
+ }
+
+ ShaderInput *input = &inputs_[attr_len_++];
+ input->location = input->binding = location;
+
+ name_buffer_offset += set_input_name(input, name, name_len);
+ enabled_attr_mask_ |= (1 << input->location);
+ }
+
+ /* Uniform Blocks */
+ for (int i = 0; i < ubo_len; i++) {
+ char *name = name_buffer_ + name_buffer_offset;
+ GLsizei remaining_buffer = name_buffer_len - name_buffer_offset;
+ GLsizei name_len = 0;
+
+ glGetActiveUniformBlockName(program, i, remaining_buffer, &name_len, name);
+
+ ShaderInput *input = &inputs_[attr_len_ + ubo_len_++];
+ input->binding = input->location = block_binding(program, i);
+
+ name_buffer_offset += this->set_input_name(input, name, name_len);
+ enabled_ubo_mask_ |= (1 << input->binding);
+ }
+
+ /* Uniforms */
+ for (int i = 0, sampler = 0; i < active_uniform_len; i++) {
+ if (BLI_BITMAP_TEST(uniforms_from_blocks, i)) {
+ continue;
+ }
+ char *name = name_buffer_ + name_buffer_offset;
+ GLsizei remaining_buffer = name_buffer_len - name_buffer_offset;
+ GLsizei name_len = 0;
+
+ glGetActiveUniformName(program, i, remaining_buffer, &name_len, name);
+
+ ShaderInput *input = &inputs_[attr_len_ + ubo_len_ + uniform_len_++];
+ input->location = glGetUniformLocation(program, name);
+ input->binding = sampler_binding(program, i, input->location, &sampler);
+
+ name_buffer_offset += this->set_input_name(input, name, name_len);
+ enabled_tex_mask_ |= (input->binding != -1) ? (1lu << input->binding) : 0lu;
+ }
+
+ /* Builtin Uniforms */
+ for (int32_t u_int = 0; u_int < GPU_NUM_UNIFORMS; u_int++) {
+ GPUUniformBuiltin u = static_cast<GPUUniformBuiltin>(u_int);
+ builtins_[u] = glGetUniformLocation(program, builtin_uniform_name(u));
+ }
+
+ /* Builtin Uniforms Blocks */
+ for (int32_t u_int = 0; u_int < GPU_NUM_UNIFORM_BLOCKS; u_int++) {
+ GPUUniformBlockBuiltin u = static_cast<GPUUniformBlockBuiltin>(u_int);
+ const ShaderInput *block = this->ubo_get(builtin_uniform_block_name(u));
+ builtin_blocks_[u] = (block != NULL) ? block->binding : -1;
+ }
+
+ MEM_freeN(uniforms_from_blocks);
+
+ /* Resize name buffer to save some memory. */
+ if (name_buffer_offset < name_buffer_len) {
+ name_buffer_ = (char *)MEM_reallocN(name_buffer_, name_buffer_offset);
+ }
+
+ // this->debug_print();
+
+ this->sort_inputs();
+}
+
+GLShaderInterface::~GLShaderInterface()
+{
+ for (auto *ref : refs_) {
+ if (ref != NULL) {
+ ref->remove(this);
+ }
+ }
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Batch Reference
+ * \{ */
+
+void GLShaderInterface::ref_add(GLVaoCache *ref)
+{
+ for (int i = 0; i < refs_.size(); i++) {
+ if (refs_[i] == NULL) {
+ refs_[i] = ref;
+ return;
+ }
+ }
+ refs_.append(ref);
+}
+
+void GLShaderInterface::ref_remove(GLVaoCache *ref)
+{
+ for (int i = 0; i < refs_.size(); i++) {
+ if (refs_[i] == ref) {
+ refs_[i] = NULL;
+ break; /* cannot have duplicates */
+ }
+ }
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Validation
+ * TODO
+ * \{ */
+
+/** \} */
+
+} // namespace blender::gpu \ No newline at end of file
diff --git a/source/blender/gpu/opengl/gl_shader_interface.hh b/source/blender/gpu/opengl/gl_shader_interface.hh
new file mode 100644
index 00000000000..0b9585aa389
--- /dev/null
+++ b/source/blender/gpu/opengl/gl_shader_interface.hh
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ *
+ * The Original Code is Copyright (C) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup gpu
+ *
+ * GPU shader interface (C --> GLSL)
+ *
+ * Structure detailing needed vertex inputs and resources for a specific shader.
+ * A shader interface can be shared between two similar shaders.
+ */
+
+#pragma once
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_vector.hh"
+
+#include "glew-mx.h"
+
+#include "gpu_shader_interface.hh"
+
+namespace blender::gpu {
+
+class GLVaoCache;
+
+/**
+ * Implementation of Shader interface using OpenGL.
+ **/
+class GLShaderInterface : public ShaderInterface {
+ private:
+ /** Reference to VaoCaches using this interface */
+ Vector<GLVaoCache *> refs_;
+
+ public:
+ GLShaderInterface(GLuint program);
+ ~GLShaderInterface();
+
+ void ref_add(GLVaoCache *ref);
+ void ref_remove(GLVaoCache *ref);
+
+ // bool resource_binding_validate();
+
+ MEM_CXX_CLASS_ALLOC_FUNCS("GLShaderInterface");
+};
+
+} // namespace blender::gpu
diff --git a/source/blender/gpu/opengl/gl_state.cc b/source/blender/gpu/opengl/gl_state.cc
index 3e3695e0b48..7dc3e44c516 100644
--- a/source/blender/gpu/opengl/gl_state.cc
+++ b/source/blender/gpu/opengl/gl_state.cc
@@ -26,6 +26,7 @@
#include "glew-mx.h"
+#include "gl_context.hh"
#include "gl_state.hh"
using namespace blender::gpu;
@@ -53,6 +54,9 @@ GLStateManager::GLStateManager(void) : GPUStateManager()
glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
}
+ /* Limits. */
+ glGetFloatv(GL_ALIASED_LINE_WIDTH_RANGE, line_width_range_);
+
/* Force update using default state. */
current_ = ~state;
current_mutable_ = ~mutable_state;
@@ -65,23 +69,23 @@ void GLStateManager::set_state(const GPUState &state)
GPUState changed = state ^ current_;
if (changed.blend != 0) {
- set_blend(state.blend);
+ set_blend((eGPUBlend)state.blend);
}
if (changed.write_mask != 0) {
- set_write_mask(state.write_mask);
+ set_write_mask((eGPUWriteMask)state.write_mask);
}
if (changed.depth_test != 0) {
- set_depth_test(state.depth_test);
+ set_depth_test((eGPUDepthTest)state.depth_test);
}
if (changed.stencil_test != 0 || changed.stencil_op != 0) {
- set_stencil_test(state.stencil_test, state.stencil_op);
- set_stencil_mask(state.stencil_test, mutable_state);
+ set_stencil_test((eGPUStencilTest)state.stencil_test, (eGPUStencilOp)state.stencil_op);
+ set_stencil_mask((eGPUStencilTest)state.stencil_test, mutable_state);
}
if (changed.clip_distances != 0) {
set_clip_distances(state.clip_distances, current_.clip_distances);
}
if (changed.culling_test != 0) {
- set_backface_culling(state.culling_test);
+ set_backface_culling((eGPUFaceCullTest)state.culling_test);
}
if (changed.logic_op_xor != 0) {
set_logic_op(state.logic_op_xor);
@@ -90,7 +94,7 @@ void GLStateManager::set_state(const GPUState &state)
set_facing(state.invert_facing);
}
if (changed.provoking_vert != 0) {
- set_provoking_vert(state.provoking_vert);
+ set_provoking_vert((eGPUProvokingVertex)state.provoking_vert);
}
if (changed.shadow_bias != 0) {
set_shadow_bias(state.shadow_bias);
@@ -150,7 +154,7 @@ void GLStateManager::set_mutable_state(const GPUStateMutable &state)
if (changed.line_width != 0) {
/* TODO remove, should use wide line shader. */
- glLineWidth(clamp_f(state.line_width, 1.0f, GPU_max_line_width()));
+ glLineWidth(clamp_f(state.line_width, line_width_range_[0], line_width_range_[1]));
}
if (changed.depth_range[0] != 0 || changed.depth_range[1] != 0) {
@@ -160,7 +164,7 @@ void GLStateManager::set_mutable_state(const GPUStateMutable &state)
if (changed.stencil_compare_mask != 0 || changed.stencil_reference != 0 ||
changed.stencil_write_mask != 0) {
- set_stencil_mask(current_.stencil_test, state);
+ set_stencil_mask((eGPUStencilTest)current_.stencil_test, state);
}
current_mutable_ = state;
diff --git a/source/blender/gpu/opengl/gl_state.hh b/source/blender/gpu/opengl/gl_state.hh
index b05fcc5d044..8e806cb3e7a 100644
--- a/source/blender/gpu/opengl/gl_state.hh
+++ b/source/blender/gpu/opengl/gl_state.hh
@@ -31,11 +31,17 @@
namespace blender {
namespace gpu {
+/**
+ * State manager keeping track of the draw state and applying it before drawing.
+ * Opengl Implementation.
+ **/
class GLStateManager : public GPUStateManager {
private:
/** Current state of the GL implementation. Avoids resetting the whole state for every change. */
GPUState current_;
GPUStateMutable current_mutable_;
+ /** Limits. */
+ float line_width_range_[2];
public:
GLStateManager();
diff --git a/source/blender/gpu/opengl/gl_uniform_buffer.cc b/source/blender/gpu/opengl/gl_uniform_buffer.cc
new file mode 100644
index 00000000000..5115034639c
--- /dev/null
+++ b/source/blender/gpu/opengl/gl_uniform_buffer.cc
@@ -0,0 +1,126 @@
+/*
+ * 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.
+ *
+ * The Original Code is Copyright (C) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup gpu
+ */
+
+#include "BKE_global.h"
+
+#include "BLI_string.h"
+
+#include "GPU_extensions.h"
+
+#include "gpu_backend.hh"
+#include "gpu_context_private.hh"
+
+#include "gl_backend.hh"
+#include "gl_uniform_buffer.hh"
+
+namespace blender::gpu {
+
+/* -------------------------------------------------------------------- */
+/** \name Creation & Deletion
+ * \{ */
+
+GLUniformBuf::GLUniformBuf(size_t size, const char *name) : UniformBuf(size, name)
+{
+ /* Do not create ubo GL buffer here to allow allocation from any thread. */
+}
+
+GLUniformBuf::~GLUniformBuf()
+{
+ GLBackend::get()->buf_free(ubo_id_);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Data upload / update
+ * \{ */
+
+void GLUniformBuf::init(void)
+{
+ BLI_assert(GPU_context_active_get());
+
+ glGenBuffers(1, &ubo_id_);
+ glBindBuffer(GL_UNIFORM_BUFFER, ubo_id_);
+ glBufferData(GL_UNIFORM_BUFFER, size_in_bytes_, NULL, GL_DYNAMIC_DRAW);
+
+#ifndef __APPLE__
+ if ((G.debug & G_DEBUG_GPU) && (GLEW_VERSION_4_3 || GLEW_KHR_debug)) {
+ char sh_name[64];
+ SNPRINTF(sh_name, "UBO-%s", name_);
+ glObjectLabel(GL_BUFFER, ubo_id_, -1, sh_name);
+ }
+#endif
+}
+
+void GLUniformBuf::update(const void *data)
+{
+ if (ubo_id_ == 0) {
+ this->init();
+ }
+ glBindBuffer(GL_UNIFORM_BUFFER, ubo_id_);
+ glBufferSubData(GL_UNIFORM_BUFFER, 0, size_in_bytes_, data);
+ glBindBuffer(GL_UNIFORM_BUFFER, 0);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Usage
+ * \{ */
+
+void GLUniformBuf::bind(int slot)
+{
+ if (slot >= GPU_max_ubo_binds()) {
+ fprintf(stderr,
+ "Error: Trying to bind \"%s\" ubo to slot %d which is above the reported limit of %d.",
+ name_,
+ slot,
+ GPU_max_ubo_binds());
+ return;
+ }
+
+ if (ubo_id_ == 0) {
+ this->init();
+ }
+
+ if (data_ != NULL) {
+ this->update(data_);
+ MEM_SAFE_FREE(data_);
+ }
+
+ slot_ = slot;
+ glBindBufferBase(GL_UNIFORM_BUFFER, slot_, ubo_id_);
+}
+
+void GLUniformBuf::unbind(void)
+{
+#ifdef DEBUG
+ /* NOTE: This only unbinds the last bound slot. */
+ glBindBufferBase(GL_UNIFORM_BUFFER, slot_, 0);
+#endif
+ slot_ = 0;
+}
+
+/** \} */
+
+} // namespace blender::gpu \ No newline at end of file
diff --git a/source/blender/gpu/opengl/gl_uniform_buffer.hh b/source/blender/gpu/opengl/gl_uniform_buffer.hh
new file mode 100644
index 00000000000..b71356c4121
--- /dev/null
+++ b/source/blender/gpu/opengl/gl_uniform_buffer.hh
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ *
+ * The Original Code is Copyright (C) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup gpu
+ */
+
+#pragma once
+
+#include "MEM_guardedalloc.h"
+
+#include "gpu_uniform_buffer_private.hh"
+
+#include "glew-mx.h"
+
+namespace blender {
+namespace gpu {
+
+/**
+ * Implementation of Uniform Buffers using OpenGL.
+ **/
+class GLUniformBuf : public UniformBuf {
+ private:
+ int slot_ = -1;
+ GLuint ubo_id_ = 0;
+
+ public:
+ GLUniformBuf(size_t size, const char *name);
+ ~GLUniformBuf();
+
+ void update(const void *data) override;
+ void bind(int slot) override;
+ void unbind(void) override;
+
+ private:
+ void init(void);
+
+ MEM_CXX_CLASS_ALLOC_FUNCS("GLUniformBuf");
+};
+
+} // namespace gpu
+} // namespace blender
diff --git a/source/blender/gpu/opengl/gl_vertex_array.cc b/source/blender/gpu/opengl/gl_vertex_array.cc
index 907dc37e46f..b2d2445f113 100644
--- a/source/blender/gpu/opengl/gl_vertex_array.cc
+++ b/source/blender/gpu/opengl/gl_vertex_array.cc
@@ -23,9 +23,9 @@
#include "GPU_glew.h"
-#include "GPU_shader_interface.h"
#include "GPU_vertex_buffer.h"
+#include "gpu_shader_interface.hh"
#include "gpu_vertex_format_private.h"
#include "gl_batch.hh"
@@ -33,14 +33,14 @@
#include "gl_vertex_array.hh"
-using namespace blender::gpu;
+namespace blender::gpu {
/* -------------------------------------------------------------------- */
/** \name Vertex Array Bindings
* \{ */
/* Returns enabled vertex pointers as a bitflag (one bit per attrib). */
-static uint16_t vbo_bind(const GPUShaderInterface *interface,
+static uint16_t vbo_bind(const ShaderInterface *interface,
const GPUVertFormat *format,
uint v_first,
uint v_len,
@@ -68,7 +68,7 @@ static uint16_t vbo_bind(const GPUShaderInterface *interface,
for (uint n_idx = 0; n_idx < a->name_len; n_idx++) {
const char *name = GPU_vertformat_attr_name_get(format, a, n_idx);
- const GPUShaderInput *input = GPU_shaderinterface_attr(interface, name);
+ const ShaderInput *input = interface->attr_get(name);
if (input == NULL) {
continue;
@@ -111,10 +111,10 @@ static uint16_t vbo_bind(const GPUShaderInterface *interface,
/* Update the Attrib Binding of the currently bound VAO. */
void GLVertArray::update_bindings(const GLuint vao,
const GPUBatch *batch,
- const GPUShaderInterface *interface,
+ const ShaderInterface *interface,
const int base_instance)
{
- uint16_t attr_mask = interface->enabled_attr_mask;
+ uint16_t attr_mask = interface->enabled_attr_mask_;
glBindVertexArray(vao);
@@ -156,3 +156,5 @@ void GLVertArray::update_bindings(const GLuint vao,
}
/** \} */
+
+} // namespace blender::gpu \ No newline at end of file
diff --git a/source/blender/gpu/opengl/gl_vertex_array.hh b/source/blender/gpu/opengl/gl_vertex_array.hh
index 6da414d7e62..59cd50ad7b8 100644
--- a/source/blender/gpu/opengl/gl_vertex_array.hh
+++ b/source/blender/gpu/opengl/gl_vertex_array.hh
@@ -26,7 +26,7 @@
#include "glew-mx.h"
#include "GPU_batch.h"
-#include "GPU_shader_interface.h"
+#include "gl_shader_interface.hh"
namespace blender {
namespace gpu {
@@ -35,7 +35,7 @@ namespace GLVertArray {
void update_bindings(const GLuint vao,
const GPUBatch *batch,
- const GPUShaderInterface *interface,
+ const ShaderInterface *interface,
const int base_instance);
} // namespace GLVertArray