Blender  V3.3
gl_storage_buffer.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2022 Blender Foundation. All rights reserved. */
3 
8 #include "BLI_string.h"
9 
10 #include "gpu_backend.hh"
11 #include "gpu_context_private.hh"
12 
13 #include "gl_backend.hh"
14 #include "gl_debug.hh"
15 #include "gl_storage_buffer.hh"
16 #include "gl_vertex_buffer.hh"
17 
18 namespace blender::gpu {
19 
20 /* -------------------------------------------------------------------- */
24 GLStorageBuf::GLStorageBuf(size_t size, GPUUsageType usage, const char *name)
25  : StorageBuf(size, name)
26 {
27  usage_ = usage;
28  /* Do not create UBO GL buffer here to allow allocation from any thread. */
30 }
31 
33 {
34  GLContext::buf_free(ssbo_id_);
35 }
36 
39 /* -------------------------------------------------------------------- */
43 void GLStorageBuf::init()
44 {
46 
47  glGenBuffers(1, &ssbo_id_);
48  glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo_id_);
49  glBufferData(GL_SHADER_STORAGE_BUFFER, size_in_bytes_, nullptr, to_gl(this->usage_));
50 
51  debug::object_label(GL_SHADER_STORAGE_BUFFER, ssbo_id_, name_);
52 }
53 
54 void GLStorageBuf::update(const void *data)
55 {
56  if (ssbo_id_ == 0) {
57  this->init();
58  }
59  glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo_id_);
60  glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, size_in_bytes_, data);
61  glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
62 }
63 
66 /* -------------------------------------------------------------------- */
70 void GLStorageBuf::bind(int slot)
71 {
72  if (slot >= GLContext::max_ssbo_binds) {
73  fprintf(
74  stderr,
75  "Error: Trying to bind \"%s\" ssbo to slot %d which is above the reported limit of %d.",
76  name_,
77  slot,
79  return;
80  }
81 
82  if (ssbo_id_ == 0) {
83  this->init();
84  }
85 
86  if (data_ != nullptr) {
87  this->update(data_);
89  }
90 
91  slot_ = slot;
92  glBindBufferBase(GL_SHADER_STORAGE_BUFFER, slot_, ssbo_id_);
93 
94 #ifdef DEBUG
95  BLI_assert(slot < 16);
96  /* TODO */
97  // GLContext::get()->bound_ssbo_slots |= 1 << slot;
98 #endif
99 }
100 
101 void GLStorageBuf::bind_as(GLenum target)
102 {
103  BLI_assert_msg(ssbo_id_ != 0,
104  "Trying to use storage buf as indirect buffer but buffer was never filled.");
105  glBindBuffer(target, ssbo_id_);
106 }
107 
109 {
110 #ifdef DEBUG
111  /* NOTE: This only unbinds the last bound slot. */
112  glBindBufferBase(GL_SHADER_STORAGE_BUFFER, slot_, 0);
113  /* Hope that the context did not change. */
114  /* TODO */
115  // GLContext::get()->bound_ssbo_slots &= ~(1 << slot_);
116 #endif
117  slot_ = 0;
118 }
119 
120 void GLStorageBuf::clear(eGPUTextureFormat internal_format, eGPUDataFormat data_format, void *data)
121 {
122  if (ssbo_id_ == 0) {
123  this->init();
124  }
125 
127  glClearNamedBufferData(ssbo_id_,
128  to_gl_internal_format(internal_format),
129  to_gl_data_format(internal_format),
130  to_gl(data_format),
131  data);
132  }
133  else {
134  /* WATCH(@fclem): This should be ok since we only use clear outside of drawing functions. */
135  glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo_id_);
136  glClearBufferData(GL_SHADER_STORAGE_BUFFER,
137  to_gl_internal_format(internal_format),
138  to_gl_data_format(internal_format),
139  to_gl(data_format),
140  data);
141  glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
142  }
143 }
144 
145 void GLStorageBuf::copy_sub(VertBuf *src_, uint dst_offset, uint src_offset, uint copy_size)
146 {
147  GLVertBuf *src = static_cast<GLVertBuf *>(src_);
148  GLStorageBuf *dst = this;
149 
150  if (dst->ssbo_id_ == 0) {
151  dst->init();
152  }
153  if (src->vbo_id_ == 0) {
154  src->bind();
155  }
156 
158  glCopyNamedBufferSubData(src->vbo_id_, dst->ssbo_id_, src_offset, dst_offset, copy_size);
159  }
160  else {
161  /* This binds the buffer to GL_ARRAY_BUFFER and upload the data if any. */
162  src->bind();
163  glBindBuffer(GL_COPY_WRITE_BUFFER, dst->ssbo_id_);
164  glCopyBufferSubData(GL_ARRAY_BUFFER, GL_COPY_WRITE_BUFFER, src_offset, dst_offset, copy_size);
165  glBindBuffer(GL_COPY_WRITE_BUFFER, 0);
166  }
167 }
168 
171 } // namespace blender::gpu
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition: BLI_assert.h:53
unsigned int uint
Definition: BLI_sys_types.h:67
eGPUDataFormat
Definition: GPU_texture.h:170
eGPUTextureFormat
Definition: GPU_texture.h:83
GPUUsageType
#define MEM_SAFE_FREE(v)
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
static void buf_free(GLuint buf_id)
Definition: gl_context.cc:250
static GLint max_ssbo_binds
Definition: gl_context.hh:49
static GLint max_ssbo_size
Definition: gl_context.hh:48
static bool direct_state_access_support
Definition: gl_context.hh:57
static GLContext * get()
Definition: gl_context.hh:117
void clear(eGPUTextureFormat internal_format, eGPUDataFormat data_format, void *data) override
void bind(int slot) override
void update(const void *data) override
GLStorageBuf(size_t size, GPUUsageType usage, const char *name)
void copy_sub(VertBuf *src, uint dst_offset, uint src_offset, uint copy_size) override
SyclQueue void void * src
void object_label(GLenum type, GLuint object, const char *name)
Definition: gl_debug.cc:328
GLenum to_gl_internal_format(eGPUTextureFormat format)
Definition: gl_texture.hh:90
GLenum to_gl_data_format(eGPUTextureFormat format)
Definition: gl_texture.hh:294
static GLenum to_gl(const GPUAttachmentType type)