3 Replies
      Latest reply on Mar 5, 2018 9:27 AM by bram
      Changgeng Wang Level 1 Level 1 (0 points)

        I set glView.drawableMultisample = GLKViewDrawableMultisample.multisample4X; in viewDidLoad method,when the GLKView finish drawing a frame , I Got an error "Your app called glInvalidateFrameBuffer before presenting the renderbuffer.This is incorrect. If you call glInvalidateFrameBuffer,do so after presenting."

         

        How to solve this problem?

        • Re: GLKViewDrawableMultisample.multisample4X cause opengl error
          Changgeng Wang Level 1 Level 1 (0 points)

          The full source code

           

          import GLKit

          import OpenGLES

           

           

          func BUFFER_OFFSET(_ i: Int) -> UnsafePointer<Void>? {

              return UnsafePointer<Void>(bitPattern: i)

          }

           

           

          let UNIFORM_MODELVIEWPROJECTION_MATRIX = 0

          let UNIFORM_NORMAL_MATRIX = 1

          var uniforms = [GLint](repeating: 0, count: 2)

           

           

          class GameViewController: GLKViewController {

            

              var program: GLuint = 0

            

              var modelViewProjectionMatrix:GLKMatrix4 = GLKMatrix4Identity

              var normalMatrix: GLKMatrix3 = GLKMatrix3Identity

              var rotation: Float = 0.0

            

              var vertexArray: GLuint = 0

              var vertexBuffer: GLuint = 0

            

              var context: EAGLContext? = nil

              var effect: GLKBaseEffect? = nil

              var panR:UIPanGestureRecognizer? = nil

            

              deinit {

                  self.tearDownGL()

                

                  if EAGLContext.current() === self.context {

                      EAGLContext.setCurrent(nil)

                  }

              }

            

              override func viewDidLoad() {

                  super.viewDidLoad()

                

                  self.context = EAGLContext(api: .openGLES2)

                

                  if !(self.context != nil) {

                      print("Failed to create ES context")

                  }

                

                  let view = self.view as! GLKView

                  view.context = self.context!

                  view.drawableDepthFormat = .format24

                

                  self.setupGL()

                

                  self.panR = UIPanGestureRecognizer(target: self, action: #selector(GameViewController.doPan(panR:)))

                  self.view.addGestureRecognizer(self.panR!)

              }

            

              func doPan(panR:UIPanGestureRecognizer)  {

                

                  self.update()

                  let gView:GLKView = self.view as! GLKView

                  gView.display()

              }

            

              override func viewWillAppear(_ animated: Bool) {

                  self.isPaused = true

                  self.resumeOnDidBecomeActive = false

              }

            

              override func didReceiveMemoryWarning() {

                  super.didReceiveMemoryWarning()

                

                  if self.isViewLoaded() && (self.view.window != nil) {

                      self.view = nil

                    

                      self.tearDownGL()

                    

                      if EAGLContext.current() === self.context {

                          EAGLContext.setCurrent(nil)

                      }

                      self.context = nil

                  }

              }

            

              func setupGL() {

                  EAGLContext.setCurrent(self.context)

                

                  if(self.loadShaders() == false) {

                      print("Failed to load shaders")

                  }

                

                  self.effect = GLKBaseEffect()

                  self.effect!.light0.enabled = GLboolean(GL_TRUE)

                  self.effect!.light0.diffuseColor = GLKVector4Make(1.0, 0.4, 0.4, 1.0)

                  let glView:GLKView = self.view as! GLKView

                

                  glView.context = self.context!

                  self.preferredFramesPerSecond = 60

                

          //        glView.drawableColorFormat = GLKViewDrawableColorFormat.RGBA8888;

          //        glView.drawableDepthFormat = GLKViewDrawableDepthFormat.format24;

          //        glView.drawableStencilFormat = GLKViewDrawableStencilFormat.format8;

                

                  // Enable multisampling

                  glView.drawableMultisample = GLKViewDrawableMultisample.multisample4X;

                

                  glEnable(GLenum(GL_DEPTH_TEST))

                

                  glGenVertexArraysOES(1, &vertexArray)

                  glBindVertexArrayOES(vertexArray)

                

                  glGenBuffers(1, &vertexBuffer)

                  glBindBuffer(GLenum(GL_ARRAY_BUFFER), vertexBuffer)

                  glBufferData(GLenum(GL_ARRAY_BUFFER), GLsizeiptr(sizeof(GLfloat) * gCubeVertexData.count), &gCubeVertexData, GLenum(GL_STATIC_DRAW))

                

                  glEnableVertexAttribArray(GLuint(GLKVertexAttrib.position.rawValue))

                  glVertexAttribPointer(GLuint(GLKVertexAttrib.position.rawValue), 3, GLenum(GL_FLOAT), GLboolean(GL_FALSE), 24, BUFFER_OFFSET(0))

                  glEnableVertexAttribArray(GLuint(GLKVertexAttrib.normal.rawValue))

                  glVertexAttribPointer(GLuint(GLKVertexAttrib.normal.rawValue), 3, GLenum(GL_FLOAT), GLboolean(GL_FALSE), 24, BUFFER_OFFSET(12))

                

                  glBindVertexArrayOES(0)

              }

            

              func tearDownGL() {

                  EAGLContext.setCurrent(self.context)

                

                  glDeleteBuffers(1, &vertexBuffer)

                  glDeleteVertexArraysOES(1, &vertexArray)

                

                  self.effect = nil

                

                  if program != 0 {

                      glDeleteProgram(program)

                      program = 0

                  }

              }

            

            

            

              // MARK: - GLKView and GLKViewController delegate methods

            

              func update() {

                  let aspect = fabsf(Float(self.view.bounds.size.width / self.view.bounds.size.height))

                  let projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0), aspect, 0.1, 100.0)

                

                  self.effect?.transform.projectionMatrix = projectionMatrix

                

                  var baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0, 0.0, -4.0)

                  baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, rotation, 0.0, 1.0, 0.0)

                

                  // Compute the model view matrix for the object rendered with GLKit

                  var modelViewMatrix = GLKMatrix4MakeTranslation(0.0, 0.0, -1.5)

                  modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, rotation, 1.0, 1.0, 1.0)

                  modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix)

                

                  self.effect?.transform.modelviewMatrix = modelViewMatrix

                

                  // Compute the model view matrix for the object rendered with ES2

                  modelViewMatrix = GLKMatrix4MakeTranslation(0.0, 0.0, 1.5)

                  modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, rotation, 1.0, 1.0, 1.0)

                  modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix)

                

                  normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), nil)

                

                  modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix)

                

                  rotation += Float(self.timeSinceLastUpdate * 0.5)

              }

            

              override func glkView(_ view: GLKView, drawIn rect: CGRect) {

                  glClearColor(0.65, 0.65, 0.65, 1.0)

                  glClear(GLbitfield(GL_COLOR_BUFFER_BIT) | GLbitfield(GL_DEPTH_BUFFER_BIT))

                

                  glBindVertexArrayOES(vertexArray)

                

                  // Render the object with GLKit

                  self.effect?.prepareToDraw()

                

                  glDrawArrays(GLenum(GL_TRIANGLES) , 0, 36)

                

                  // Render the object again with ES2

                  glUseProgram(program)

                

                  withUnsafePointer(&modelViewProjectionMatrix, {

                      glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, UnsafePointer($0))

                  })

                

                  withUnsafePointer(&normalMatrix, {

                      glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, UnsafePointer($0))

                  })

                

                  glDrawArrays(GLenum(GL_TRIANGLES), 0, 36)

              }

            

              // MARK: -  OpenGL ES 2 shader compilation

            

              func loadShaders() -> Bool {

                  var vertShader: GLuint = 0

                  var fragShader: GLuint = 0

                  var vertShaderPathname: String

                  var fragShaderPathname: String

                

                  // Create shader program.

                  program = glCreateProgram()

                

                  // Create and compile vertex shader.

                  vertShaderPathname = Bundle.main().pathForResource("Shader", ofType: "vsh")!

                  if self.compileShader(&vertShader, type: GLenum(GL_VERTEX_SHADER), file: vertShaderPathname) == false {

                      print("Failed to compile vertex shader")

                      return false

                  }

                

                  // Create and compile fragment shader.

                  fragShaderPathname = Bundle.main().pathForResource("Shader", ofType: "fsh")!

                  if !self.compileShader(&fragShader, type: GLenum(GL_FRAGMENT_SHADER), file: fragShaderPathname) {

                      print("Failed to compile fragment shader")

                      return false

                  }

                

                  // Attach vertex shader to program.

                  glAttachShader(program, vertShader)

                

                  // Attach fragment shader to program.

                  glAttachShader(program, fragShader)

                

                  // Bind attribute locations.

                  // This needs to be done prior to linking.

                  glBindAttribLocation(program, GLuint(GLKVertexAttrib.position.rawValue), "position")

                  glBindAttribLocation(program, GLuint(GLKVertexAttrib.normal.rawValue), "normal")

                

                  // Link program.

                  if !self.linkProgram(program) {

                      print("Failed to link program: \(program)")

                    

                      if vertShader != 0 {

                          glDeleteShader(vertShader)

                          vertShader = 0

                      }

                      if fragShader != 0 {

                          glDeleteShader(fragShader)

                          fragShader = 0

                      }

                      if program != 0 {

                          glDeleteProgram(program)

                          program = 0

                      }

                    

                      return false

                  }

                

                  // Get uniform locations.

                  uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(program, "modelViewProjectionMatrix")

                  uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(program, "normalMatrix")

                

                  // Release vertex and fragment shaders.

                  if vertShader != 0 {

                      glDetachShader(program, vertShader)

                      glDeleteShader(vertShader)

                  }

                  if fragShader != 0 {

                      glDetachShader(program, fragShader)

                      glDeleteShader(fragShader)

                  }

                

                  return true

              }

            

            

              func compileShader(_ shader: inout GLuint, type: GLenum, file: String) -> Bool {

                  var status: GLint = 0

                  var source: UnsafePointer<Int8>

                  do {

                      source = try NSString(contentsOfFile: file, encoding: String.Encoding.utf8.rawValue).utf8String!

                  } catch {

                      print("Failed to load vertex shader")

                      return false

                  }

                  var castSource: UnsafePointer<GLchar>? = UnsafePointer<GLchar>(source)

                

                  shader = glCreateShader(type)

                  glShaderSource(shader, 1, &castSource, nil)

                  glCompileShader(shader)

                

                  //#if defined(DEBUG)

                  //        var logLength: GLint = 0

                  //        glGetShaderiv(shader, GLenum(GL_INFO_LOG_LENGTH), &logLength)

                  //        if logLength > 0 {

                  //            var log = UnsafeMutablePointer<GLchar>(malloc(Int(logLength)))

                  //            glGetShaderInfoLog(shader, logLength, &logLength, log)

                  //            NSLog("Shader compile log: \n%s", log)

                  //            free(log)

                  //        }

                  //#endif

                

                  glGetShaderiv(shader, GLenum(GL_COMPILE_STATUS), &status)

                  if status == 0 {

                      glDeleteShader(shader)

                      return false

                  }

                  return true

              }

            

              func linkProgram(_ prog: GLuint) -> Bool {

                  var status: GLint = 0

                  glLinkProgram(prog)

                

                  //#if defined(DEBUG)

                  //        var logLength: GLint = 0

                  //        glGetShaderiv(shader, GLenum(GL_INFO_LOG_LENGTH), &logLength)

                  //        if logLength > 0 {

                  //            var log = UnsafeMutablePointer<GLchar>(malloc(Int(logLength)))

                  //            glGetShaderInfoLog(shader, logLength, &logLength, log)

                  //            NSLog("Shader compile log: \n%s", log)

                  //            free(log)

                  //        }

                  //#endif

                

                  glGetProgramiv(prog, GLenum(GL_LINK_STATUS), &status)

                  if status == 0 {

                      return false

                  }

                

                  return true

              }

            

              func validateProgram(prog: GLuint) -> Bool {

                  var logLength: GLsizei = 0

                  var status: GLint = 0

                

                  glValidateProgram(prog)

                  glGetProgramiv(prog, GLenum(GL_INFO_LOG_LENGTH), &logLength)

                  if logLength > 0 {

                      var log: [GLchar] = [GLchar](repeating: 0, count: Int(logLength))

                      glGetProgramInfoLog(prog, logLength, &logLength, &log)

                      print("Program validate log: \n\(log)")

                  }

                

                  glGetProgramiv(prog, GLenum(GL_VALIDATE_STATUS), &status)

                  var returnVal = true

                  if status == 0 {

                      returnVal = false

                  }

                  return returnVal

              }

          }

           

           

          var gCubeVertexData: [GLfloat] = [

              // Data layout for each line below is:

              // positionX, positionY, positionZ,     normalX, normalY, normalZ,

              0.5, -0.5, -0.5,        1.0, 0.0, 0.0,

              0.5, 0.5, -0.5,         1.0, 0.0, 0.0,

              0.5, -0.5, 0.5,         1.0, 0.0, 0.0,

              0.5, -0.5, 0.5,         1.0, 0.0, 0.0,

              0.5, 0.5, -0.5,         1.0, 0.0, 0.0,

              0.5, 0.5, 0.5,          1.0, 0.0, 0.0,

            

              0.5, 0.5, -0.5,         0.0, 1.0, 0.0,

              -0.5, 0.5, -0.5,        0.0, 1.0, 0.0,

              0.5, 0.5, 0.5,          0.0, 1.0, 0.0,

              0.5, 0.5, 0.5,          0.0, 1.0, 0.0,

              -0.5, 0.5, -0.5,        0.0, 1.0, 0.0,

              -0.5, 0.5, 0.5,         0.0, 1.0, 0.0,

            

              -0.5, 0.5, -0.5,        -1.0, 0.0, 0.0,

              -0.5, -0.5, -0.5,      -1.0, 0.0, 0.0,

              -0.5, 0.5, 0.5,         -1.0, 0.0, 0.0,

              -0.5, 0.5, 0.5,         -1.0, 0.0, 0.0,

              -0.5, -0.5, -0.5,      -1.0, 0.0, 0.0,

              -0.5, -0.5, 0.5,        -1.0, 0.0, 0.0,

            

              -0.5, -0.5, -0.5,      0.0, -1.0, 0.0,

              0.5, -0.5, -0.5,        0.0, -1.0, 0.0,

              -0.5, -0.5, 0.5,        0.0, -1.0, 0.0,

              -0.5, -0.5, 0.5,        0.0, -1.0, 0.0,

              0.5, -0.5, -0.5,        0.0, -1.0, 0.0,

              0.5, -0.5, 0.5,         0.0, -1.0, 0.0,

            

              0.5, 0.5, 0.5,          0.0, 0.0, 1.0,

              -0.5, 0.5, 0.5,         0.0, 0.0, 1.0,

              0.5, -0.5, 0.5,         0.0, 0.0, 1.0,

              0.5, -0.5, 0.5,         0.0, 0.0, 1.0,

              -0.5, 0.5, 0.5,         0.0, 0.0, 1.0,

              -0.5, -0.5, 0.5,        0.0, 0.0, 1.0,

            

              0.5, -0.5, -0.5,        0.0, 0.0, -1.0,

              -0.5, -0.5, -0.5,      0.0, 0.0, -1.0,

              0.5, 0.5, -0.5,         0.0, 0.0, -1.0,

              0.5, 0.5, -0.5,         0.0, 0.0, -1.0,

              -0.5, -0.5, -0.5,      0.0, 0.0, -1.0,

              -0.5, 0.5, -0.5,        0.0, 0.0, -1.0

          ]

          • Re: GLKViewDrawableMultisample.multisample4X cause opengl error
            bram Level 1 Level 1 (10 points)

            This is almost certainly a false alarm by XCode's GPU Report.

             

            When presenting, both the multi sample buffer and the depth buffer are no longer required.

            The multi sample buffer has already been resolved, and the present the pixels, the depth values are no longer necessary.

             

            This means that GLKView does the correct thing: invalidate them before presenting.

             

            Note: the false warning goes away with GLKViewDrawableMultisampleNone instead of 4x.

             

            So in GLK's case, it is triggered by the invalidation of the multi sample buffer after resolving.