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.cc15
-rw-r--r--source/blender/gpu/opengl/gl_context.hh2
-rw-r--r--source/blender/gpu/opengl/gl_debug.cc20
-rw-r--r--source/blender/gpu/opengl/gl_shader_interface.cc37
-rw-r--r--source/blender/gpu/opengl/gl_state.cc95
-rw-r--r--source/blender/gpu/opengl/gl_state.hh24
6 files changed, 182 insertions, 11 deletions
diff --git a/source/blender/gpu/opengl/gl_backend.cc b/source/blender/gpu/opengl/gl_backend.cc
index edaa84cdcf8..46e048d7f7c 100644
--- a/source/blender/gpu/opengl/gl_backend.cc
+++ b/source/blender/gpu/opengl/gl_backend.cc
@@ -210,6 +210,7 @@ static void detect_workarounds(void)
GLContext::debug_layer_workaround = true;
GLContext::unused_fb_slot_workaround = true;
/* Turn off extensions. */
+ GCaps.shader_image_load_store_support = false;
GLContext::base_instance_support = false;
GLContext::clear_texture_support = false;
GLContext::copy_image_support = false;
@@ -250,17 +251,20 @@ static void detect_workarounds(void)
(strstr(version, "4.5.13399") || strstr(version, "4.5.13417") ||
strstr(version, "4.5.13422"))) {
GLContext::unused_fb_slot_workaround = true;
+ GCaps.shader_image_load_store_support = false;
GCaps.broken_amd_driver = true;
}
/* We have issues with this specific renderer. (see T74024) */
if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_UNIX, GPU_DRIVER_OPENSOURCE) &&
strstr(renderer, "AMD VERDE")) {
GLContext::unused_fb_slot_workaround = true;
+ GCaps.shader_image_load_store_support = false;
GCaps.broken_amd_driver = true;
}
/* Fix slowdown on this particular driver. (see T77641) */
if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_UNIX, GPU_DRIVER_OPENSOURCE) &&
strstr(version, "Mesa 19.3.4")) {
+ GCaps.shader_image_load_store_support = false;
GCaps.broken_amd_driver = true;
}
/* There is an issue with the #glBlitFramebuffer on MacOS with radeon pro graphics.
@@ -349,10 +353,10 @@ static void detect_workarounds(void)
}
/** Internal capabilities. */
-GLint GLContext::max_texture_3d_size;
-GLint GLContext::max_cubemap_size;
-GLint GLContext::max_ubo_size;
-GLint GLContext::max_ubo_binds;
+GLint GLContext::max_cubemap_size = 0;
+GLint GLContext::max_texture_3d_size = 0;
+GLint GLContext::max_ubo_binds = 0;
+GLint GLContext::max_ubo_size = 0;
/** Extensions. */
bool GLContext::base_instance_support = false;
bool GLContext::clear_texture_support = false;
@@ -383,6 +387,7 @@ void GLBackend::capabilities_init(void)
glGetIntegerv(GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS, &GCaps.max_textures_geom);
glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &GCaps.max_textures);
GCaps.mem_stats_support = GLEW_NVX_gpu_memory_info || GLEW_ATI_meminfo;
+ GCaps.shader_image_load_store_support = GLEW_ARB_shader_image_load_store;
/* GL specific capabilities. */
glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &GLContext::max_texture_3d_size);
glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &GLContext::max_cubemap_size);
@@ -413,4 +418,4 @@ void GLBackend::capabilities_init(void)
/** \} */
-} // namespace blender::gpu \ No newline at end of file
+} // namespace blender::gpu
diff --git a/source/blender/gpu/opengl/gl_context.hh b/source/blender/gpu/opengl/gl_context.hh
index 9822c842ce7..4d9c2470db0 100644
--- a/source/blender/gpu/opengl/gl_context.hh
+++ b/source/blender/gpu/opengl/gl_context.hh
@@ -56,8 +56,8 @@ class GLSharedOrphanLists {
class GLContext : public Context {
public:
/** Capabilities. */
- static GLint max_texture_3d_size;
static GLint max_cubemap_size;
+ static GLint max_texture_3d_size;
static GLint max_ubo_size;
static GLint max_ubo_binds;
/** Extensions. */
diff --git a/source/blender/gpu/opengl/gl_debug.cc b/source/blender/gpu/opengl/gl_debug.cc
index db99e90d0ec..747d8ee2e3e 100644
--- a/source/blender/gpu/opengl/gl_debug.cc
+++ b/source/blender/gpu/opengl/gl_debug.cc
@@ -200,13 +200,16 @@ void check_gl_resources(const char *info)
* be big enough to feed the data range the shader awaits. */
uint16_t ubo_needed = interface->enabled_ubo_mask_;
ubo_needed &= ~ctx->bound_ubo_slots;
-
/* NOTE: This only check binding. To be valid, the bound texture needs to
* be the same format/target the shader expects. */
uint64_t tex_needed = interface->enabled_tex_mask_;
tex_needed &= ~GLContext::state_manager_active_get()->bound_texture_slots();
+ /* NOTE: This only check binding. To be valid, the bound image needs to
+ * be the same format/target the shader expects. */
+ uint8_t ima_needed = interface->enabled_ima_mask_;
+ ima_needed &= ~GLContext::state_manager_active_get()->bound_image_slots();
- if (ubo_needed == 0 && tex_needed == 0) {
+ if (ubo_needed == 0 && tex_needed == 0 && ima_needed == 0) {
return;
}
@@ -223,6 +226,7 @@ void check_gl_resources(const char *info)
for (int i = 0; tex_needed != 0; i++, tex_needed >>= 1) {
if ((tex_needed & 1) != 0) {
+ /* FIXME: texture_get might return an image input instead. */
const ShaderInput *tex_input = interface->texture_get(i);
const char *tex_name = interface->input_name_get(tex_input);
const char *sh_name = ctx->shader->name_get();
@@ -231,6 +235,18 @@ void check_gl_resources(const char *info)
debug_callback(0, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, 0, msg, NULL);
}
}
+
+ for (int i = 0; ima_needed != 0; i++, ima_needed >>= 1) {
+ if ((ima_needed & 1) != 0) {
+ /* FIXME: texture_get might return a texture input instead. */
+ const ShaderInput *tex_input = interface->texture_get(i);
+ const char *tex_name = interface->input_name_get(tex_input);
+ const char *sh_name = ctx->shader->name_get();
+ char msg[256];
+ SNPRINTF(msg, "Missing Image bind at slot %d : %s > %s : %s", i, sh_name, tex_name, info);
+ debug_callback(0, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, 0, msg, NULL);
+ }
+ }
}
void raise_gl_error(const char *info)
diff --git a/source/blender/gpu/opengl/gl_shader_interface.cc b/source/blender/gpu/opengl/gl_shader_interface.cc
index d611efcd975..2d55c222e9c 100644
--- a/source/blender/gpu/opengl/gl_shader_interface.cc
+++ b/source/blender/gpu/opengl/gl_shader_interface.cc
@@ -100,6 +100,31 @@ static inline int sampler_binding(int32_t program,
return -1;
}
}
+
+static inline int image_binding(int32_t program,
+ uint32_t uniform_index,
+ int32_t uniform_location,
+ int *image_len)
+{
+ /* Identify image uniforms and asign image units to them. */
+ GLint type;
+ glGetActiveUniformsiv(program, 1, &uniform_index, GL_UNIFORM_TYPE, &type);
+
+ switch (type) {
+ case GL_IMAGE_1D:
+ case GL_IMAGE_2D:
+ case GL_IMAGE_3D: {
+ /* 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 = *image_len;
+ glUniform1i(uniform_location, binding);
+ (*image_len)++;
+ return binding;
+ }
+ default:
+ return -1;
+ }
+}
/** \} */
/* -------------------------------------------------------------------- */
@@ -207,8 +232,8 @@ GLShaderInterface::GLShaderInterface(GLuint program)
enabled_ubo_mask_ |= (1 << input->binding);
}
- /* Uniforms */
- for (int i = 0, sampler = 0; i < active_uniform_len; i++) {
+ /* Uniforms & samplers & images */
+ for (int i = 0, sampler = 0, image = 0; i < active_uniform_len; i++) {
if (BLI_BITMAP_TEST(uniforms_from_blocks, i)) {
continue;
}
@@ -224,6 +249,12 @@ GLShaderInterface::GLShaderInterface(GLuint program)
name_buffer_offset += this->set_input_name(input, name, name_len);
enabled_tex_mask_ |= (input->binding != -1) ? (1lu << input->binding) : 0lu;
+
+ if (input->binding == -1) {
+ input->binding = image_binding(program, i, input->location, &image);
+
+ enabled_ima_mask_ |= (input->binding != -1) ? (1lu << input->binding) : 0lu;
+ }
}
/* Builtin Uniforms */
@@ -296,4 +327,4 @@ void GLShaderInterface::ref_remove(GLVaoCache *ref)
/** \} */
-} // namespace blender::gpu \ No newline at end of file
+} // namespace blender::gpu
diff --git a/source/blender/gpu/opengl/gl_state.cc b/source/blender/gpu/opengl/gl_state.cc
index 1678760e9cd..93753768928 100644
--- a/source/blender/gpu/opengl/gl_state.cc
+++ b/source/blender/gpu/opengl/gl_state.cc
@@ -76,6 +76,7 @@ void GLStateManager::apply_state(void)
this->set_state(this->state);
this->set_mutable_state(this->mutable_state);
this->texture_bind_apply();
+ this->image_bind_apply();
active_fb->apply_state();
};
@@ -538,4 +539,98 @@ uint64_t GLStateManager::bound_texture_slots(void)
/** \} */
+/* -------------------------------------------------------------------- */
+/** \name Image Binding (from image load store)
+ * \{ */
+
+void GLStateManager::image_bind(Texture *tex_, int unit)
+{
+ /* Minimum support is 8 image in the fragment shader. No image for other stages. */
+ BLI_assert(GPU_shader_image_load_store_support() && unit < 8);
+ GLTexture *tex = static_cast<GLTexture *>(tex_);
+ if (G.debug & G_DEBUG_GPU) {
+ tex->check_feedback_loop();
+ }
+ images_[unit] = tex->tex_id_;
+ formats_[unit] = to_gl_internal_format(tex->format_);
+ tex->is_bound_ = true;
+ dirty_image_binds_ |= 1ULL << unit;
+}
+
+void GLStateManager::image_unbind(Texture *tex_)
+{
+ GLTexture *tex = static_cast<GLTexture *>(tex_);
+ if (!tex->is_bound_) {
+ return;
+ }
+
+ GLuint tex_id = tex->tex_id_;
+ for (int i = 0; i < ARRAY_SIZE(images_); i++) {
+ if (images_[i] == tex_id) {
+ images_[i] = 0;
+ dirty_image_binds_ |= 1ULL << i;
+ }
+ }
+ tex->is_bound_ = false;
+}
+
+void GLStateManager::image_unbind_all(void)
+{
+ for (int i = 0; i < ARRAY_SIZE(images_); i++) {
+ if (images_[i] != 0) {
+ images_[i] = 0;
+ dirty_image_binds_ |= 1ULL << i;
+ }
+ }
+ this->image_bind_apply();
+}
+
+void GLStateManager::image_bind_apply(void)
+{
+ if (dirty_image_binds_ == 0) {
+ return;
+ }
+ uint32_t dirty_bind = dirty_image_binds_;
+ dirty_image_binds_ = 0;
+
+ int first = bitscan_forward_uint(dirty_bind);
+ int last = 32 - bitscan_reverse_uint(dirty_bind);
+ int count = last - first;
+
+ if (GLContext::multi_bind_support) {
+ glBindImageTextures(first, count, images_ + first);
+ }
+ else {
+ for (int unit = first; unit < last; unit++) {
+ if ((dirty_bind >> unit) & 1UL) {
+ glBindImageTexture(unit, images_[unit], 0, GL_TRUE, 0, GL_READ_WRITE, formats_[unit]);
+ }
+ }
+ }
+}
+
+uint8_t GLStateManager::bound_image_slots(void)
+{
+ uint8_t bound_slots = 0;
+ for (int i = 0; i < ARRAY_SIZE(images_); i++) {
+ if (images_[i] != 0) {
+ bound_slots |= 1ULL << i;
+ }
+ }
+ return bound_slots;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Memory barrier
+ * \{ */
+
+void GLStateManager::issue_barrier(eGPUBarrier barrier_bits)
+{
+ glMemoryBarrier(to_gl(barrier_bits));
+}
+
+/** \} */
+
} // namespace blender::gpu
diff --git a/source/blender/gpu/opengl/gl_state.hh b/source/blender/gpu/opengl/gl_state.hh
index fb2ed3403f7..b636c08ec0d 100644
--- a/source/blender/gpu/opengl/gl_state.hh
+++ b/source/blender/gpu/opengl/gl_state.hh
@@ -64,19 +64,30 @@ class GLStateManager : public GPUStateManager {
GLuint samplers_[64] = {0};
uint64_t dirty_texture_binds_ = 0;
+ GLuint images_[8] = {0};
+ GLenum formats_[8] = {0};
+ uint8_t dirty_image_binds_ = 0;
+
public:
GLStateManager();
void apply_state(void) override;
+ void issue_barrier(eGPUBarrier barrier_bits) override;
+
void texture_bind(Texture *tex, eGPUSamplerState sampler, int unit) override;
void texture_bind_temp(GLTexture *tex);
void texture_unbind(Texture *tex) override;
void texture_unbind_all(void) override;
+ void image_bind(Texture *tex, int unit) override;
+ void image_unbind(Texture *tex) override;
+ void image_unbind_all(void) override;
+
void texture_unpack_row_length_set(uint len) override;
uint64_t bound_texture_slots(void);
+ uint8_t bound_image_slots(void);
private:
static void set_write_mask(const eGPUWriteMask value);
@@ -95,9 +106,22 @@ class GLStateManager : public GPUStateManager {
void set_mutable_state(const GPUStateMutable &state);
void texture_bind_apply(void);
+ void image_bind_apply(void);
MEM_CXX_CLASS_ALLOC_FUNCS("GLStateManager")
};
+static inline GLbitfield to_gl(eGPUBarrier barrier_bits)
+{
+ GLbitfield barrier = 0;
+ if (barrier_bits & GPU_BARRIER_SHADER_IMAGE_ACCESS) {
+ barrier |= GL_SHADER_IMAGE_ACCESS_BARRIER_BIT;
+ }
+ if (barrier_bits & GPU_BARRIER_TEXTURE_FETCH) {
+ barrier |= GL_TEXTURE_FETCH_BARRIER_BIT;
+ }
+ return barrier;
+}
+
} // namespace gpu
} // namespace blender