diff options
Diffstat (limited to 'source/blender/gpu/opengl')
-rw-r--r-- | source/blender/gpu/opengl/gl_backend.cc | 6 | ||||
-rw-r--r-- | source/blender/gpu/opengl/gl_context.hh | 2 | ||||
-rw-r--r-- | source/blender/gpu/opengl/gl_framebuffer.hh | 2 | ||||
-rw-r--r-- | source/blender/gpu/opengl/gl_shader.cc | 250 | ||||
-rw-r--r-- | source/blender/gpu/opengl/gl_shader.hh | 8 | ||||
-rw-r--r-- | source/blender/gpu/opengl/gl_shader_interface.cc | 30 | ||||
-rw-r--r-- | source/blender/gpu/opengl/gl_shader_log.cc | 9 | ||||
-rw-r--r-- | source/blender/gpu/opengl/gl_state.hh | 13 |
8 files changed, 303 insertions, 17 deletions
diff --git a/source/blender/gpu/opengl/gl_backend.cc b/source/blender/gpu/opengl/gl_backend.cc index 92d180f1140..2ee7c0503f4 100644 --- a/source/blender/gpu/opengl/gl_backend.cc +++ b/source/blender/gpu/opengl/gl_backend.cc @@ -248,6 +248,8 @@ static void detect_workarounds() GLContext::direct_state_access_support = false; GLContext::fixed_restart_index_support = false; GLContext::geometry_shader_invocations = false; + GLContext::layered_rendering_support = false; + GLContext::native_barycentric_support = false; GLContext::multi_bind_support = false; GLContext::multi_draw_indirect_support = false; GLContext::shader_draw_parameters_support = false; @@ -445,6 +447,8 @@ bool GLContext::direct_state_access_support = false; bool GLContext::explicit_location_support = false; bool GLContext::geometry_shader_invocations = false; bool GLContext::fixed_restart_index_support = false; +bool GLContext::layered_rendering_support = false; +bool GLContext::native_barycentric_support = false; bool GLContext::multi_bind_support = false; bool GLContext::multi_draw_indirect_support = false; bool GLContext::shader_draw_parameters_support = false; @@ -505,6 +509,8 @@ void GLBackend::capabilities_init() GLContext::explicit_location_support = GLEW_VERSION_4_3; GLContext::geometry_shader_invocations = GLEW_ARB_gpu_shader5; GLContext::fixed_restart_index_support = GLEW_ARB_ES3_compatibility; + GLContext::layered_rendering_support = GLEW_AMD_vertex_shader_layer; + GLContext::native_barycentric_support = GLEW_AMD_shader_explicit_vertex_parameter; GLContext::multi_bind_support = GLEW_ARB_multi_bind; GLContext::multi_draw_indirect_support = GLEW_ARB_multi_draw_indirect; GLContext::shader_draw_parameters_support = GLEW_ARB_shader_draw_parameters; diff --git a/source/blender/gpu/opengl/gl_context.hh b/source/blender/gpu/opengl/gl_context.hh index dd22418972b..b7a74863ac4 100644 --- a/source/blender/gpu/opengl/gl_context.hh +++ b/source/blender/gpu/opengl/gl_context.hh @@ -72,6 +72,8 @@ class GLContext : public Context { static bool explicit_location_support; static bool geometry_shader_invocations; static bool fixed_restart_index_support; + static bool layered_rendering_support; + static bool native_barycentric_support; static bool multi_bind_support; static bool multi_draw_indirect_support; static bool shader_draw_parameters_support; diff --git a/source/blender/gpu/opengl/gl_framebuffer.hh b/source/blender/gpu/opengl/gl_framebuffer.hh index 9ebe549efe7..00a7676dd3f 100644 --- a/source/blender/gpu/opengl/gl_framebuffer.hh +++ b/source/blender/gpu/opengl/gl_framebuffer.hh @@ -141,6 +141,8 @@ static inline GLenum to_gl(const GPUAttachmentType type) ATTACHMENT(COLOR_ATTACHMENT3); ATTACHMENT(COLOR_ATTACHMENT4); ATTACHMENT(COLOR_ATTACHMENT5); + ATTACHMENT(COLOR_ATTACHMENT6); + ATTACHMENT(COLOR_ATTACHMENT7); default: BLI_assert(0); return GL_COLOR_ATTACHMENT0; diff --git a/source/blender/gpu/opengl/gl_shader.cc b/source/blender/gpu/opengl/gl_shader.cc index f0a4b5b7f58..275f2c96bbd 100644 --- a/source/blender/gpu/opengl/gl_shader.cc +++ b/source/blender/gpu/opengl/gl_shader.cc @@ -127,6 +127,74 @@ static const char *to_string(const Type &type) } } +static const char *to_string(const eGPUTextureFormat &type) +{ + switch (type) { + case GPU_RGBA8UI: + return "rgba8ui"; + case GPU_RGBA8I: + return "rgba8i"; + case GPU_RGBA8: + return "rgba8"; + case GPU_RGBA32UI: + return "rgba32ui"; + case GPU_RGBA32I: + return "rgba32i"; + case GPU_RGBA32F: + return "rgba32f"; + case GPU_RGBA16UI: + return "rgba16ui"; + case GPU_RGBA16I: + return "rgba16i"; + case GPU_RGBA16F: + return "rgba16f"; + case GPU_RGBA16: + return "rgba16"; + case GPU_RG8UI: + return "rg8ui"; + case GPU_RG8I: + return "rg8i"; + case GPU_RG8: + return "rg8"; + case GPU_RG32UI: + return "rg32ui"; + case GPU_RG32I: + return "rg32i"; + case GPU_RG32F: + return "rg32f"; + case GPU_RG16UI: + return "rg16ui"; + case GPU_RG16I: + return "rg16i"; + case GPU_RG16F: + return "rg16f"; + case GPU_RG16: + return "rg16"; + case GPU_R8UI: + return "r8ui"; + case GPU_R8I: + return "r8i"; + case GPU_R8: + return "r8"; + case GPU_R32UI: + return "r32ui"; + case GPU_R32I: + return "r32i"; + case GPU_R32F: + return "r32f"; + case GPU_R16UI: + return "r16ui"; + case GPU_R16I: + return "r16i"; + case GPU_R16F: + return "r16f"; + case GPU_R16: + return "r16"; + default: + return "unkown"; + } +} + static const char *to_string(const PrimitiveIn &layout) { switch (layout) { @@ -277,15 +345,15 @@ static void print_image_type(std::ostream &os, static std::ostream &print_qualifier(std::ostream &os, const Qualifier &qualifiers) { - if ((qualifiers & Qualifier::RESTRICT) == Qualifier::RESTRICT) { + if (bool(qualifiers & Qualifier::NO_RESTRICT) == false) { os << "restrict "; } - if ((qualifiers & Qualifier::READ_ONLY) == Qualifier::READ_ONLY) { - os << "readonly "; - } - if ((qualifiers & Qualifier::WRITE_ONLY) == Qualifier::WRITE_ONLY) { + if (bool(qualifiers & Qualifier::READ) == false) { os << "writeonly "; } + if (bool(qualifiers & Qualifier::WRITE) == false) { + os << "readonly "; + } return os; } @@ -294,7 +362,7 @@ static void print_resource(std::ostream &os, const ShaderCreateInfo::Resource &r if (GLContext::explicit_location_support) { os << "layout(binding = " << res.slot; if (res.bind_type == ShaderCreateInfo::Resource::BindType::IMAGE) { - os << ", " << res.image.format; + os << ", " << to_string(res.image.format); } else if (res.bind_type == ShaderCreateInfo::Resource::BindType::UNIFORM_BUFFER) { os << ", std140"; @@ -370,7 +438,7 @@ static void print_interface(std::ostream &os, const StageInterfaceInfo &iface, const StringRefNull &suffix = "") { - /* TODO(fclem) Move that to interface check. */ + /* TODO(@fclem): Move that to interface check. */ // if (iface.instance_name.is_empty()) { // BLI_assert_msg(0, "Interfaces require an instance name for geometry shader."); // std::cout << iface.name << ": Interfaces require an instance name for geometry shader.\n"; @@ -426,9 +494,28 @@ std::string GLShader::resources_declare(const ShaderCreateInfo &info) const return ss.str(); } +static std::string main_function_wrapper(std::string &pre_main, std::string &post_main) +{ + std::stringstream ss; + /* Prototype for the original main. */ + ss << "\n"; + ss << "void main_function_();\n"; + /* Wrapper to the main function in order to inject code processing on globals. */ + ss << "void main() {\n"; + ss << pre_main; + ss << " main_function_();\n"; + ss << post_main; + ss << "}\n"; + /* Rename the original main. */ + ss << "#define main main_function_\n"; + ss << "\n"; + return ss.str(); +} + std::string GLShader::vertex_interface_declare(const ShaderCreateInfo &info) const { std::stringstream ss; + std::string post_main = ""; ss << "\n/* Inputs. */\n"; for (const ShaderCreateInfo::VertIn &attr : info.vertex_inputs_) { @@ -443,13 +530,35 @@ std::string GLShader::vertex_interface_declare(const ShaderCreateInfo &info) con for (const StageInterfaceInfo *iface : info.vertex_out_interfaces_) { print_interface(ss, "out", *iface); } + if (!GLContext::layered_rendering_support && bool(info.builtins_ & BuiltinBits::LAYER)) { + ss << "out int gpu_Layer;\n"; + } + if (bool(info.builtins_ & BuiltinBits::BARYCENTRIC_COORD)) { + if (!GLContext::native_barycentric_support) { + /* Disabled or unsupported. */ + } + else if (GLEW_AMD_shader_explicit_vertex_parameter) { + /* Need this for stable barycentric. */ + ss << "flat out vec4 gpu_pos_flat;\n"; + ss << "out vec4 gpu_pos;\n"; + + post_main += " gpu_pos = gpu_pos_flat = gl_Position;\n"; + } + } ss << "\n"; + + if (post_main.empty() == false) { + std::string pre_main = ""; + ss << main_function_wrapper(pre_main, post_main); + } return ss.str(); } std::string GLShader::fragment_interface_declare(const ShaderCreateInfo &info) const { std::stringstream ss; + std::string pre_main = ""; + ss << "\n/* Interfaces. */\n"; const Vector<StageInterfaceInfo *> &in_interfaces = (info.geometry_source_.is_empty()) ? info.vertex_out_interfaces_ : @@ -457,6 +566,32 @@ std::string GLShader::fragment_interface_declare(const ShaderCreateInfo &info) c for (const StageInterfaceInfo *iface : in_interfaces) { print_interface(ss, "in", *iface); } + if (bool(info.builtins_ & BuiltinBits::BARYCENTRIC_COORD)) { + if (!GLContext::native_barycentric_support) { + ss << "smooth in vec3 gpu_BaryCoord;\n"; + ss << "noperspective in vec3 gpu_BaryCoordNoPersp;\n"; + } + else if (GLEW_AMD_shader_explicit_vertex_parameter) { + /* NOTE(fclem): This won't work with geometry shader. Hopefully, we don't need geometry + * shader workaround if this extension/feature is detected. */ + ss << "\n/* Stable Barycentric Coordinates. */\n"; + ss << "flat in vec4 gpu_pos_flat;\n"; + ss << "__explicitInterpAMD in vec4 gpu_pos;\n"; + /* Globals. */ + ss << "vec3 gpu_BaryCoord;\n"; + ss << "vec3 gpu_BaryCoordNoPersp;\n"; + ss << "\n"; + ss << "vec2 stable_bary_(vec2 in_bary) {\n"; + ss << " vec3 bary = vec3(in_bary, 1.0 - in_bary.x - in_bary.y);\n"; + ss << " if (interpolateAtVertexAMD(gpu_pos, 0) == gpu_pos_flat) { return bary.zxy; }\n"; + ss << " if (interpolateAtVertexAMD(gpu_pos, 2) == gpu_pos_flat) { return bary.yzx; }\n"; + ss << " return bary.xyz;\n"; + ss << "}\n"; + + pre_main += " gpu_BaryCoord = stable_bary_(gl_BaryCoordSmoothAMD);\n"; + pre_main += " gpu_BaryCoordNoPersp = stable_bary_(gl_BaryCoordNoPerspAMD);\n"; + } + } ss << "\n/* Outputs. */\n"; for (const ShaderCreateInfo::FragOut &output : info.fragment_outputs_) { ss << "layout(location = " << output.index; @@ -474,6 +609,11 @@ std::string GLShader::fragment_interface_declare(const ShaderCreateInfo &info) c ss << "out " << to_string(output.type) << " " << output.name << ";\n"; } ss << "\n"; + + if (pre_main.empty() == false) { + std::string post_main = ""; + ss << main_function_wrapper(pre_main, post_main); + } return ss.str(); } @@ -505,7 +645,7 @@ static StageInterfaceInfo *find_interface_by_name(const Vector<StageInterfaceInf const StringRefNull &name) { for (auto *iface : ifaces) { - if (iface->name == name) { + if (iface->instance_name == name) { return iface; } } @@ -514,8 +654,8 @@ static StageInterfaceInfo *find_interface_by_name(const Vector<StageInterfaceInf std::string GLShader::geometry_interface_declare(const ShaderCreateInfo &info) const { - std::stringstream ss; + ss << "\n/* Interfaces. */\n"; for (const StageInterfaceInfo *iface : info.vertex_out_interfaces_) { bool has_matching_output_iface = find_interface_by_name(info.geometry_out_interfaces_, @@ -549,6 +689,76 @@ std::string GLShader::compute_layout_declare(const ShaderCreateInfo &info) const ss << "\n"; return ss.str(); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Passthrough geometry shader emulation + * + * \{ */ + +std::string GLShader::workaround_geometry_shader_source_create( + const shader::ShaderCreateInfo &info) +{ + std::stringstream ss; + + const bool do_layer_workaround = !GLContext::layered_rendering_support && + bool(info.builtins_ & BuiltinBits::LAYER); + const bool do_barycentric_workaround = !GLContext::native_barycentric_support && + bool(info.builtins_ & BuiltinBits::BARYCENTRIC_COORD); + + shader::ShaderCreateInfo info_modified = info; + info_modified.geometry_out_interfaces_ = info_modified.vertex_out_interfaces_; + /** + * NOTE(@fclem): Assuming we will render TRIANGLES. This will not work with other primitive + * types. In this case, it might not trigger an error on some implementations. + */ + info_modified.geometry_layout(PrimitiveIn::TRIANGLES, PrimitiveOut::TRIANGLE_STRIP, 3); + + ss << geometry_layout_declare(info_modified); + ss << geometry_interface_declare(info_modified); + if (do_layer_workaround) { + ss << "in int gpu_Layer[];\n"; + } + if (do_barycentric_workaround) { + ss << "smooth out vec3 gpu_BaryCoord;\n"; + ss << "noperspective out vec3 gpu_BaryCoordNoPersp;\n"; + } + ss << "\n"; + + ss << "void main()\n"; + ss << "{\n"; + if (do_layer_workaround) { + ss << " gl_Layer = gpu_Layer[0];\n"; + } + for (auto i : IndexRange(3)) { + for (auto iface : info_modified.vertex_out_interfaces_) { + for (auto &inout : iface->inouts) { + ss << " " << iface->instance_name << "_out." << inout.name; + ss << " = " << iface->instance_name << "_in[" << i << "]." << inout.name << ";\n"; + } + } + if (do_barycentric_workaround) { + ss << " gpu_BaryCoordNoPersp = gpu_BaryCoord ="; + ss << " vec3(" << int(i == 0) << ", " << int(i == 1) << ", " << int(i == 2) << ");\n"; + } + ss << " gl_Position = gl_in[" << i << "].gl_Position;\n"; + ss << " EmitVertex();\n"; + } + ss << "}\n"; + return ss.str(); +} + +bool GLShader::do_geometry_shader_injection(const shader::ShaderCreateInfo *info) +{ + BuiltinBits builtins = info->builtins_; + if (!GLContext::native_barycentric_support && bool(builtins & BuiltinBits::BARYCENTRIC_COORD)) { + return true; + } + if (!GLContext::layered_rendering_support && bool(builtins & BuiltinBits::LAYER)) { + return true; + } + return false; +} /** \} */ @@ -559,7 +769,7 @@ std::string GLShader::compute_layout_declare(const ShaderCreateInfo &info) const static char *glsl_patch_default_get() { /** Used for shader patching. Init once. */ - static char patch[700] = "\0"; + static char patch[1024] = "\0"; if (patch[0] != '\0') { return patch; } @@ -596,13 +806,20 @@ static char *glsl_patch_default_get() STR_CONCAT(patch, slen, "#extension GL_ARB_texture_cube_map_array : enable\n"); STR_CONCAT(patch, slen, "#define GPU_ARB_texture_cube_map_array\n"); } - if (GLEW_ARB_conservative_depth) { + if (!GLEW_VERSION_4_2 && GLEW_ARB_conservative_depth) { STR_CONCAT(patch, slen, "#extension GL_ARB_conservative_depth : enable\n"); } if (GPU_shader_image_load_store_support()) { STR_CONCAT(patch, slen, "#extension GL_ARB_shader_image_load_store: enable\n"); STR_CONCAT(patch, slen, "#extension GL_ARB_shading_language_420pack: enable\n"); } + if (GLContext::layered_rendering_support) { + STR_CONCAT(patch, slen, "#extension GL_AMD_vertex_shader_layer: enable\n"); + STR_CONCAT(patch, slen, "#define gpu_Layer gl_Layer\n"); + } + if (GLContext::native_barycentric_support) { + STR_CONCAT(patch, slen, "#extension GL_AMD_shader_explicit_vertex_parameter: enable\n"); + } /* Fallbacks. */ if (!GLContext::shader_draw_parameters_support) { @@ -612,6 +829,9 @@ static char *glsl_patch_default_get() /* Vulkan GLSL compat. */ STR_CONCAT(patch, slen, "#define gpu_InstanceIndex (gl_InstanceID + gpu_BaseInstance)\n"); + /* Array compat. */ + STR_CONCAT(patch, slen, "#define array(_type) _type[]\n"); + /* Derivative sign can change depending on implementation. */ STR_CONCATF(patch, slen, "#define DFDX_SIGN %1.1f\n", GLContext::derivative_signs[0]); STR_CONCATF(patch, slen, "#define DFDY_SIGN %1.1f\n", GLContext::derivative_signs[1]); @@ -719,6 +939,14 @@ bool GLShader::finalize(const shader::ShaderCreateInfo *info) return false; } + if (info && do_geometry_shader_injection(info)) { + std::string source = workaround_geometry_shader_source_create(*info); + Vector<const char *> sources; + sources.append("version"); + sources.append(source.c_str()); + geometry_shader_from_glsl(sources); + } + glLinkProgram(shader_program_); GLint status; diff --git a/source/blender/gpu/opengl/gl_shader.hh b/source/blender/gpu/opengl/gl_shader.hh index a82ab026c16..cc1c93142f8 100644 --- a/source/blender/gpu/opengl/gl_shader.hh +++ b/source/blender/gpu/opengl/gl_shader.hh @@ -94,6 +94,14 @@ class GLShader : public Shader { /** Create, compile and attach the shader stage to the shader program. */ GLuint create_shader_stage(GLenum gl_stage, MutableSpan<const char *> sources); + /** + * \brief features available on newer implementation such as native barycentric coordinates + * and layered rendering, necessitate a geometry shader to work on older hardware. + */ + std::string workaround_geometry_shader_source_create(const shader::ShaderCreateInfo &info); + + bool do_geometry_shader_injection(const shader::ShaderCreateInfo *info); + MEM_CXX_CLASS_ALLOC_FUNCS("GLShader"); }; diff --git a/source/blender/gpu/opengl/gl_shader_interface.cc b/source/blender/gpu/opengl/gl_shader_interface.cc index 71b908665d3..0a31f8dee7f 100644 --- a/source/blender/gpu/opengl/gl_shader_interface.cc +++ b/source/blender/gpu/opengl/gl_shader_interface.cc @@ -117,7 +117,28 @@ static inline int image_binding(int32_t program, switch (type) { case GL_IMAGE_1D: case GL_IMAGE_2D: - case GL_IMAGE_3D: { + case GL_IMAGE_3D: + case GL_IMAGE_CUBE: + case GL_IMAGE_BUFFER: + case GL_IMAGE_1D_ARRAY: + case GL_IMAGE_2D_ARRAY: + case GL_IMAGE_CUBE_MAP_ARRAY: + case GL_INT_IMAGE_1D: + case GL_INT_IMAGE_2D: + case GL_INT_IMAGE_3D: + case GL_INT_IMAGE_CUBE: + case GL_INT_IMAGE_BUFFER: + case GL_INT_IMAGE_1D_ARRAY: + case GL_INT_IMAGE_2D_ARRAY: + case GL_INT_IMAGE_CUBE_MAP_ARRAY: + case GL_UNSIGNED_INT_IMAGE_1D: + case GL_UNSIGNED_INT_IMAGE_2D: + case GL_UNSIGNED_INT_IMAGE_3D: + case GL_UNSIGNED_INT_IMAGE_CUBE: + case GL_UNSIGNED_INT_IMAGE_BUFFER: + case GL_UNSIGNED_INT_IMAGE_1D_ARRAY: + case GL_UNSIGNED_INT_IMAGE_2D_ARRAY: + case GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY: { /* 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; @@ -298,6 +319,7 @@ GLShaderInterface::GLShaderInterface(GLuint program) input->binding = input->location = binding; name_buffer_offset += this->set_input_name(input, name, name_len); + enabled_ssbo_mask_ |= (input->binding != -1) ? (1lu << input->binding) : 0lu; } /* Builtin Uniforms */ @@ -455,7 +477,7 @@ GLShaderInterface::GLShaderInterface(GLuint program, const shader::ShaderCreateI if (res.bind_type == ShaderCreateInfo::Resource::BindType::STORAGE_BUFFER) { copy_input_name(input, res.storagebuf.name, name_buffer_, name_buffer_offset); input->location = input->binding = res.slot; - enabled_ubo_mask_ |= (1 << input->binding); + enabled_ssbo_mask_ |= (1 << input->binding); input++; } } @@ -497,7 +519,7 @@ GLShaderInterface::~GLShaderInterface() void GLShaderInterface::ref_add(GLVaoCache *ref) { for (int i = 0; i < refs_.size(); i++) { - if (refs_[i] == NULL) { + if (refs_[i] == nullptr) { refs_[i] = ref; return; } @@ -509,7 +531,7 @@ void GLShaderInterface::ref_remove(GLVaoCache *ref) { for (int i = 0; i < refs_.size(); i++) { if (refs_[i] == ref) { - refs_[i] = NULL; + refs_[i] = nullptr; break; /* cannot have duplicates */ } } diff --git a/source/blender/gpu/opengl/gl_shader_log.cc b/source/blender/gpu/opengl/gl_shader_log.cc index 174cc63ad81..0ee70b54f52 100644 --- a/source/blender/gpu/opengl/gl_shader_log.cc +++ b/source/blender/gpu/opengl/gl_shader_log.cc @@ -60,6 +60,15 @@ char *GLLogParser::parse_line(char *log_line, GPULogItem &log_item) log_item.cursor.row = log_item.cursor.column; log_item.cursor.column = -1; } + else if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_UNIX, GPU_DRIVER_OFFICIAL) && + /* WORKAROUND(@fclem): Both Mesa and amdgpu-pro are reported as official. */ + StringRefNull(GPU_platform_version()).find(" Mesa ") == -1) { + /* source:row */ + log_item.cursor.source = log_item.cursor.row; + log_item.cursor.row = log_item.cursor.column; + log_item.cursor.column = -1; + log_item.source_base_row = true; + } else { /* line:char */ } diff --git a/source/blender/gpu/opengl/gl_state.hh b/source/blender/gpu/opengl/gl_state.hh index 83ff3ffc9e9..5985f1583f2 100644 --- a/source/blender/gpu/opengl/gl_state.hh +++ b/source/blender/gpu/opengl/gl_state.hh @@ -124,11 +124,20 @@ static inline GLbitfield to_gl(eGPUBarrier barrier_bits) if (barrier_bits & GPU_BARRIER_SHADER_IMAGE_ACCESS) { barrier |= GL_SHADER_IMAGE_ACCESS_BARRIER_BIT; } + if (barrier_bits & GPU_BARRIER_SHADER_STORAGE) { + barrier |= GL_SHADER_STORAGE_BARRIER_BIT; + } if (barrier_bits & GPU_BARRIER_TEXTURE_FETCH) { barrier |= GL_TEXTURE_FETCH_BARRIER_BIT; } - if (barrier_bits & GPU_BARRIER_SHADER_STORAGE) { - barrier |= GL_SHADER_STORAGE_BARRIER_BIT; + if (barrier_bits & GPU_BARRIER_TEXTURE_UPDATE) { + barrier |= GL_TEXTURE_UPDATE_BARRIER_BIT; + } + if (barrier_bits & GPU_BARRIER_COMMAND) { + barrier |= GL_COMMAND_BARRIER_BIT; + } + if (barrier_bits & GPU_BARRIER_FRAMEBUFFER) { + barrier |= GL_FRAMEBUFFER_BARRIER_BIT; } if (barrier_bits & GPU_BARRIER_VERTEX_ATTRIB_ARRAY) { barrier |= GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT; |