Explorar o código

gl_rasterizer: Workaround Intel VAO DSA bug

There is a bug on Intel's blob driver where it fails to properly build a
vertex array object if it's not bound even after creating it with
glCreateVertexArrays. This workaround binds it after creating it to
bypass the issue.
ReinUsesLisp %!s(int64=7) %!d(string=hai) anos
pai
achega
877a978a22

+ 6 - 0
src/video_core/renderer_opengl/gl_rasterizer.cpp

@@ -153,6 +153,12 @@ GLuint RasterizerOpenGL::SetupVertexFormat() {
         vao_entry.Create();
         vao_entry.Create();
         const GLuint vao = vao_entry.handle;
         const GLuint vao = vao_entry.handle;
 
 
+        // Eventhough we are using DSA to create this vertex array, there is a bug on Intel's blob
+        // that fails to properly create the vertex array if it's not bound even after creating it
+        // with glCreateVertexArrays
+        state.draw.vertex_array = vao;
+        state.ApplyVertexArrayState();
+
         glVertexArrayElementBuffer(vao, buffer_cache.GetHandle());
         glVertexArrayElementBuffer(vao, buffer_cache.GetHandle());
 
 
         // Use the vertex array as-is, assumes that the data is formatted correctly for OpenGL.
         // Use the vertex array as-is, assumes that the data is formatted correctly for OpenGL.

+ 7 - 6
src/video_core/renderer_opengl/gl_state.cpp

@@ -503,7 +503,6 @@ void OpenGLState::ApplySamplers() const {
 }
 }
 
 
 void OpenGLState::ApplyFramebufferState() const {
 void OpenGLState::ApplyFramebufferState() const {
-    // Framebuffer
     if (draw.read_framebuffer != cur_state.draw.read_framebuffer) {
     if (draw.read_framebuffer != cur_state.draw.read_framebuffer) {
         glBindFramebuffer(GL_READ_FRAMEBUFFER, draw.read_framebuffer);
         glBindFramebuffer(GL_READ_FRAMEBUFFER, draw.read_framebuffer);
     }
     }
@@ -512,6 +511,12 @@ void OpenGLState::ApplyFramebufferState() const {
     }
     }
 }
 }
 
 
+void OpenGLState::ApplyVertexArrayState() const {
+    if (draw.vertex_array != cur_state.draw.vertex_array) {
+        glBindVertexArray(draw.vertex_array);
+    }
+}
+
 void OpenGLState::ApplyDepthClamp() const {
 void OpenGLState::ApplyDepthClamp() const {
     if (depth_clamp.far_plane == cur_state.depth_clamp.far_plane &&
     if (depth_clamp.far_plane == cur_state.depth_clamp.far_plane &&
         depth_clamp.near_plane == cur_state.depth_clamp.near_plane) {
         depth_clamp.near_plane == cur_state.depth_clamp.near_plane) {
@@ -529,11 +534,7 @@ void OpenGLState::ApplyDepthClamp() const {
 
 
 void OpenGLState::Apply() const {
 void OpenGLState::Apply() const {
     ApplyFramebufferState();
     ApplyFramebufferState();
-
-    // Vertex array
-    if (draw.vertex_array != cur_state.draw.vertex_array) {
-        glBindVertexArray(draw.vertex_array);
-    }
+    ApplyVertexArrayState();
 
 
     // Shader program
     // Shader program
     if (draw.shader_program != cur_state.draw.shader_program) {
     if (draw.shader_program != cur_state.draw.shader_program) {

+ 3 - 1
src/video_core/renderer_opengl/gl_state.h

@@ -204,8 +204,10 @@ public:
     }
     }
     /// Apply this state as the current OpenGL state
     /// Apply this state as the current OpenGL state
     void Apply() const;
     void Apply() const;
-    /// Apply only the state afecting the framebuffer
+    /// Apply only the state affecting the framebuffer
     void ApplyFramebufferState() const;
     void ApplyFramebufferState() const;
+    /// Apply only the state affecting the vertex array
+    void ApplyVertexArrayState() const;
     /// Set the initial OpenGL state
     /// Set the initial OpenGL state
     static void ApplyDefaultState();
     static void ApplyDefaultState();
     /// Resets any references to the given resource
     /// Resets any references to the given resource