GLKViewDrawableMultisample.multisample4X cause opengl error

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?

Replies

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

]

+1 I have the same issue. Did you find a solution?

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.