Browse Source

gles2gsg: Fix image load/store support in OpenGL ES 3.1

This does require gl-immutable-texture-storage to be on, so it is not enabled by default unless that variable is set. That is not a breaking change since before this change, support was never enabled to begin with
rdb 2 years ago
parent
commit
89701270dd

+ 1 - 1
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -3098,7 +3098,7 @@ reset() {
   _max_image_units = 0;
   _max_image_units = 0;
 #ifndef OPENGLES_1
 #ifndef OPENGLES_1
 #ifdef OPENGLES
 #ifdef OPENGLES
-  if (is_at_least_gl_version(3, 1)) {
+  if (is_at_least_gles_version(3, 1) && gl_immutable_texture_storage) {
 #else
 #else
   if (is_at_least_gl_version(4, 2) || has_extension("GL_ARB_shader_image_load_store")) {
   if (is_at_least_gl_version(4, 2) || has_extension("GL_ARB_shader_image_load_store")) {
 #endif
 #endif

+ 40 - 4
panda/src/glstuff/glShaderContext_src.cxx

@@ -1744,13 +1744,35 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
 #endif
 #endif
         // This won't really change at runtime, so we might as well bind once
         // This won't really change at runtime, so we might as well bind once
         // and then forget about it.
         // and then forget about it.
-        _glgsg->_glUniform1i(p, _glsl_img_inputs.size());
         {
         {
+#ifdef OPENGLES
+          // In OpenGL ES, we can't choose our own binding, but we can ask the
+          // driver what it assigned (or what the shader specified).
+          GLint binding = 0;
+          glGetUniformiv(_glsl_program, p, &binding);
+          if (GLCAT.is_debug()) {
+            GLCAT.debug()
+              << "Active uniform " << param_name
+              << " is bound to image unit " << binding << "\n";
+          }
+
+          if (binding >= _glsl_img_inputs.size()) {
+            _glsl_img_inputs.resize(binding + 1);
+          }
+
+          ImageInput &input = _glsl_img_inputs[binding];
+          input._name = InternalName::make(param_name);
+#else
+          if (GLCAT.is_debug()) {
+            GLCAT.debug()
+              << "Binding image uniform " << param_name
+              << " to image unit " << _glsl_img_inputs.size() << "\n";
+          }
+          _glgsg->_glUniform1i(p, _glsl_img_inputs.size());
           ImageInput input;
           ImageInput input;
           input._name = InternalName::make(param_name);
           input._name = InternalName::make(param_name);
-          input._writable = false;
-          input._gtc = nullptr;
-          _glsl_img_inputs.push_back(input);
+          _glsl_img_inputs.push_back(std::move(input));
+#endif
         }
         }
         return;
         return;
       default:
       default:
@@ -2749,6 +2771,10 @@ update_shader_texture_bindings(ShaderContext *prev) {
       const ParamTextureImage *param = nullptr;
       const ParamTextureImage *param = nullptr;
       Texture *tex;
       Texture *tex;
 
 
+      if (input._name == nullptr) {
+        continue;
+      }
+
       const ShaderInput &sinp = _glgsg->_target_shader->get_shader_input(input._name);
       const ShaderInput &sinp = _glgsg->_target_shader->get_shader_input(input._name);
       switch (sinp.get_value_type()) {
       switch (sinp.get_value_type()) {
       case ShaderInput::M_texture_image:
       case ShaderInput::M_texture_image:
@@ -2800,6 +2826,16 @@ update_shader_texture_bindings(ShaderContext *prev) {
         // TODO: automatically convert to sized type instead of plain GL_RGBA
         // TODO: automatically convert to sized type instead of plain GL_RGBA
         // If a base type is used, it will crash.
         // If a base type is used, it will crash.
         GLenum internal_format = gtc->_internal_format;
         GLenum internal_format = gtc->_internal_format;
+#ifdef OPENGLES
+        if (!gtc->_immutable) {
+          static bool error_shown = false;
+          if (!error_shown) {
+            error_shown = true;
+            GLCAT.error()
+              << "Enable gl-immutable-texture-storage to use image textures in OpenGL ES.\n";
+          }
+        }
+#endif
         if (internal_format == GL_RGBA || internal_format == GL_RGB) {
         if (internal_format == GL_RGBA || internal_format == GL_RGB) {
           GLCAT.error()
           GLCAT.error()
             << "Texture " << tex->get_name() << " has an unsized format.  Textures bound "
             << "Texture " << tex->get_name() << " has an unsized format.  Textures bound "

+ 2 - 2
panda/src/glstuff/glShaderContext_src.h

@@ -109,8 +109,8 @@ private:
 
 
   struct ImageInput {
   struct ImageInput {
     CPT(InternalName) _name;
     CPT(InternalName) _name;
-    CLP(TextureContext) *_gtc;
-    bool _writable;
+    CLP(TextureContext) *_gtc = nullptr;
+    bool _writable = false;
   };
   };
   pvector<ImageInput> _glsl_img_inputs;
   pvector<ImageInput> _glsl_img_inputs;