From ea4928393f164723e904cf2192a5b724f11ef844 Mon Sep 17 00:00:00 2001
From: ReinUsesLisp <reinuseslisp@airmail.cc>
Date: Sun, 6 Jan 2019 00:28:01 -0300
Subject: [PATCH 1/4] gl_state: Drop uniform buffer state tracking

---
 src/video_core/renderer_opengl/gl_state.cpp        | 8 --------
 src/video_core/renderer_opengl/gl_state.h          | 1 -
 src/video_core/renderer_opengl/renderer_opengl.cpp | 1 -
 3 files changed, 10 deletions(-)

diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp
index dc0a5ed5e5..e54aff995a 100644
--- a/src/video_core/renderer_opengl/gl_state.cpp
+++ b/src/video_core/renderer_opengl/gl_state.cpp
@@ -84,7 +84,6 @@ OpenGLState::OpenGLState() {
     draw.draw_framebuffer = 0;
     draw.vertex_array = 0;
     draw.vertex_buffer = 0;
-    draw.uniform_buffer = 0;
     draw.shader_program = 0;
     draw.program_pipeline = 0;
 
@@ -544,10 +543,6 @@ void OpenGLState::ApplyDepthClamp() const {
 void OpenGLState::Apply() const {
     ApplyFramebufferState();
     ApplyVertexBufferState();
-    // Uniform buffer
-    if (draw.uniform_buffer != cur_state.draw.uniform_buffer) {
-        glBindBuffer(GL_UNIFORM_BUFFER, draw.uniform_buffer);
-    }
 
     // Shader program
     if (draw.shader_program != cur_state.draw.shader_program) {
@@ -642,9 +637,6 @@ OpenGLState& OpenGLState::ResetBuffer(GLuint handle) {
     if (draw.vertex_buffer == handle) {
         draw.vertex_buffer = 0;
     }
-    if (draw.uniform_buffer == handle) {
-        draw.uniform_buffer = 0;
-    }
     return *this;
 }
 
diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h
index 439bfbc984..170dd40470 100644
--- a/src/video_core/renderer_opengl/gl_state.h
+++ b/src/video_core/renderer_opengl/gl_state.h
@@ -155,7 +155,6 @@ public:
         GLuint draw_framebuffer; // GL_DRAW_FRAMEBUFFER_BINDING
         GLuint vertex_array;     // GL_VERTEX_ARRAY_BINDING
         GLuint vertex_buffer;    // GL_ARRAY_BUFFER_BINDING
-        GLuint uniform_buffer;   // GL_UNIFORM_BUFFER_BINDING
         GLuint shader_program;   // GL_CURRENT_PROGRAM
         GLuint program_pipeline; // GL_PROGRAM_PIPELINE_BINDING
     } draw;
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index 235732d863..4947f06fdd 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -248,7 +248,6 @@ void RendererOpenGL::InitOpenGLObjects() {
 
     state.draw.vertex_array = vertex_array.handle;
     state.draw.vertex_buffer = vertex_buffer.handle;
-    state.draw.uniform_buffer = 0;
     state.Apply();
 
     // Attach vertex data to VAO

From 35c095898bf51098d9b2a71447850f3e1b0fc350 Mon Sep 17 00:00:00 2001
From: ReinUsesLisp <reinuseslisp@airmail.cc>
Date: Sun, 6 Jan 2019 01:53:27 -0300
Subject: [PATCH 2/4] gl_rasterizer: Use DSA for vertex array objects

---
 .../renderer_opengl/gl_rasterizer.cpp         | 62 +++++++++----------
 .../renderer_opengl/gl_rasterizer.h           |  6 +-
 .../renderer_opengl/gl_resource_manager.cpp   |  5 +-
 src/video_core/renderer_opengl/gl_state.cpp   | 26 ++------
 src/video_core/renderer_opengl/gl_state.h     |  4 --
 .../renderer_opengl/renderer_opengl.cpp       | 29 +++++----
 6 files changed, 53 insertions(+), 79 deletions(-)

diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 089daf96f1..7ce8c2bcc5 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -135,27 +135,25 @@ void RasterizerOpenGL::CheckExtensions() {
     }
 }
 
-void RasterizerOpenGL::SetupVertexFormat() {
+GLuint RasterizerOpenGL::SetupVertexFormat() {
     auto& gpu = Core::System::GetInstance().GPU().Maxwell3D();
     const auto& regs = gpu.regs;
 
-    if (!gpu.dirty_flags.vertex_attrib_format)
-        return;
+    if (!gpu.dirty_flags.vertex_attrib_format) {
+        return state.draw.vertex_array;
+    }
     gpu.dirty_flags.vertex_attrib_format = false;
 
     MICROPROFILE_SCOPE(OpenGL_VAO);
 
     auto [iter, is_cache_miss] = vertex_array_cache.try_emplace(regs.vertex_attrib_format);
-    auto& VAO = iter->second;
+    auto& vao_entry = iter->second;
 
     if (is_cache_miss) {
-        VAO.Create();
-        state.draw.vertex_array = VAO.handle;
-        state.ApplyVertexBufferState();
+        vao_entry.Create();
+        const GLuint vao = vao_entry.handle;
 
-        // The index buffer binding is stored within the VAO. Stupid OpenGL, but easy to work
-        // around.
-        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer_cache.GetHandle());
+        glVertexArrayElementBuffer(vao, buffer_cache.GetHandle());
 
         // Use the vertex array as-is, assumes that the data is formatted correctly for OpenGL.
         // Enables the first 16 vertex attributes always, as we don't know which ones are actually
@@ -163,7 +161,7 @@ void RasterizerOpenGL::SetupVertexFormat() {
         // for now to avoid OpenGL errors.
         // TODO(Subv): Analyze the shader to identify which attributes are actually used and don't
         // assume every shader uses them all.
-        for (unsigned index = 0; index < 16; ++index) {
+        for (u32 index = 0; index < 16; ++index) {
             const auto& attrib = regs.vertex_attrib_format[index];
 
             // Ignore invalid attributes.
@@ -178,28 +176,29 @@ void RasterizerOpenGL::SetupVertexFormat() {
 
             ASSERT(buffer.IsEnabled());
 
-            glEnableVertexAttribArray(index);
+            glEnableVertexArrayAttrib(vao, index);
             if (attrib.type == Tegra::Engines::Maxwell3D::Regs::VertexAttribute::Type::SignedInt ||
                 attrib.type ==
                     Tegra::Engines::Maxwell3D::Regs::VertexAttribute::Type::UnsignedInt) {
-                glVertexAttribIFormat(index, attrib.ComponentCount(),
-                                      MaxwellToGL::VertexType(attrib), attrib.offset);
+                glVertexArrayAttribIFormat(vao, index, attrib.ComponentCount(),
+                                           MaxwellToGL::VertexType(attrib), attrib.offset);
             } else {
-                glVertexAttribFormat(index, attrib.ComponentCount(),
-                                     MaxwellToGL::VertexType(attrib),
-                                     attrib.IsNormalized() ? GL_TRUE : GL_FALSE, attrib.offset);
+                glVertexArrayAttribFormat(
+                    vao, index, attrib.ComponentCount(), MaxwellToGL::VertexType(attrib),
+                    attrib.IsNormalized() ? GL_TRUE : GL_FALSE, attrib.offset);
             }
-            glVertexAttribBinding(index, attrib.buffer);
+            glVertexArrayAttribBinding(vao, index, attrib.buffer);
         }
     }
-    state.draw.vertex_array = VAO.handle;
-    state.ApplyVertexBufferState();
 
     // Rebinding the VAO invalidates the vertex buffer bindings.
     gpu.dirty_flags.vertex_array = 0xFFFFFFFF;
+
+    state.draw.vertex_array = vao_entry.handle;
+    return vao_entry.handle;
 }
 
-void RasterizerOpenGL::SetupVertexBuffer() {
+void RasterizerOpenGL::SetupVertexBuffer(GLuint vao) {
     auto& gpu = Core::System::GetInstance().GPU().Maxwell3D();
     const auto& regs = gpu.regs;
 
@@ -217,7 +216,7 @@ void RasterizerOpenGL::SetupVertexBuffer() {
         if (!vertex_array.IsEnabled())
             continue;
 
-        Tegra::GPUVAddr start = vertex_array.StartAddress();
+        const Tegra::GPUVAddr start = vertex_array.StartAddress();
         const Tegra::GPUVAddr end = regs.vertex_array_limit[index].LimitAddress();
 
         ASSERT(end > start);
@@ -225,21 +224,18 @@ void RasterizerOpenGL::SetupVertexBuffer() {
         const GLintptr vertex_buffer_offset = buffer_cache.UploadMemory(start, size);
 
         // Bind the vertex array to the buffer at the current offset.
-        glBindVertexBuffer(index, buffer_cache.GetHandle(), vertex_buffer_offset,
-                           vertex_array.stride);
+        glVertexArrayVertexBuffer(vao, index, buffer_cache.GetHandle(), vertex_buffer_offset,
+                                  vertex_array.stride);
 
         if (regs.instanced_arrays.IsInstancingEnabled(index) && vertex_array.divisor != 0) {
             // Enable vertex buffer instancing with the specified divisor.
-            glVertexBindingDivisor(index, vertex_array.divisor);
+            glVertexArrayBindingDivisor(vao, index, vertex_array.divisor);
         } else {
             // Disable the vertex buffer instancing.
-            glVertexBindingDivisor(index, 0);
+            glVertexArrayBindingDivisor(vao, index, 0);
         }
     }
 
-    // Implicit set by glBindVertexBuffer. Stupid glstate handling...
-    state.draw.vertex_buffer = buffer_cache.GetHandle();
-
     gpu.dirty_flags.vertex_array = 0;
 }
 
@@ -689,9 +685,6 @@ void RasterizerOpenGL::DrawArrays() {
     // Draw the vertex batch
     const bool is_indexed = accelerate_draw == AccelDraw::Indexed;
 
-    state.draw.vertex_buffer = buffer_cache.GetHandle();
-    state.ApplyVertexBufferState();
-
     std::size_t buffer_size = CalculateVertexArraysSize();
 
     // Add space for index buffer (keeping in mind non-core primitives)
@@ -721,8 +714,9 @@ void RasterizerOpenGL::DrawArrays() {
         gpu.dirty_flags.vertex_array = 0xFFFFFFFF;
     }
 
-    SetupVertexFormat();
-    SetupVertexBuffer();
+    const GLuint vao = SetupVertexFormat();
+    SetupVertexBuffer(vao);
+
     DrawParameters params = SetupDraw();
     SetupShaders(params.primitive_mode);
 
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index 8a891ffc7b..bac5de91ef 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -209,8 +209,10 @@ private:
 
     std::size_t CalculateIndexBufferSize() const;
 
-    void SetupVertexFormat();
-    void SetupVertexBuffer();
+    /// Updates and returns a vertex array object representing current vertex format
+    GLuint SetupVertexFormat();
+
+    void SetupVertexBuffer(GLuint vao);
 
     DrawParameters SetupDraw();
 
diff --git a/src/video_core/renderer_opengl/gl_resource_manager.cpp b/src/video_core/renderer_opengl/gl_resource_manager.cpp
index c17d5ac003..1da744158c 100644
--- a/src/video_core/renderer_opengl/gl_resource_manager.cpp
+++ b/src/video_core/renderer_opengl/gl_resource_manager.cpp
@@ -117,7 +117,7 @@ void OGLBuffer::Create() {
         return;
 
     MICROPROFILE_SCOPE(OpenGL_ResourceCreation);
-    glGenBuffers(1, &handle);
+    glCreateBuffers(1, &handle);
 }
 
 void OGLBuffer::Release() {
@@ -126,7 +126,6 @@ void OGLBuffer::Release() {
 
     MICROPROFILE_SCOPE(OpenGL_ResourceDeletion);
     glDeleteBuffers(1, &handle);
-    OpenGLState::GetCurState().ResetBuffer(handle).Apply();
     handle = 0;
 }
 
@@ -152,7 +151,7 @@ void OGLVertexArray::Create() {
         return;
 
     MICROPROFILE_SCOPE(OpenGL_ResourceCreation);
-    glGenVertexArrays(1, &handle);
+    glCreateVertexArrays(1, &handle);
 }
 
 void OGLVertexArray::Release() {
diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp
index e54aff995a..79bb52ddf7 100644
--- a/src/video_core/renderer_opengl/gl_state.cpp
+++ b/src/video_core/renderer_opengl/gl_state.cpp
@@ -83,7 +83,6 @@ OpenGLState::OpenGLState() {
     draw.read_framebuffer = 0;
     draw.draw_framebuffer = 0;
     draw.vertex_array = 0;
-    draw.vertex_buffer = 0;
     draw.shader_program = 0;
     draw.program_pipeline = 0;
 
@@ -513,18 +512,6 @@ void OpenGLState::ApplyFramebufferState() const {
     }
 }
 
-void OpenGLState::ApplyVertexBufferState() const {
-    // Vertex array
-    if (draw.vertex_array != cur_state.draw.vertex_array) {
-        glBindVertexArray(draw.vertex_array);
-    }
-
-    // Vertex buffer
-    if (draw.vertex_buffer != cur_state.draw.vertex_buffer) {
-        glBindBuffer(GL_ARRAY_BUFFER, draw.vertex_buffer);
-    }
-}
-
 void OpenGLState::ApplyDepthClamp() const {
     if (depth_clamp.far_plane == cur_state.depth_clamp.far_plane &&
         depth_clamp.near_plane == cur_state.depth_clamp.near_plane) {
@@ -542,7 +529,11 @@ void OpenGLState::ApplyDepthClamp() const {
 
 void OpenGLState::Apply() const {
     ApplyFramebufferState();
-    ApplyVertexBufferState();
+
+    // Vertex array
+    if (draw.vertex_array != cur_state.draw.vertex_array) {
+        glBindVertexArray(draw.vertex_array);
+    }
 
     // Shader program
     if (draw.shader_program != cur_state.draw.shader_program) {
@@ -633,13 +624,6 @@ OpenGLState& OpenGLState::ResetPipeline(GLuint handle) {
     return *this;
 }
 
-OpenGLState& OpenGLState::ResetBuffer(GLuint handle) {
-    if (draw.vertex_buffer == handle) {
-        draw.vertex_buffer = 0;
-    }
-    return *this;
-}
-
 OpenGLState& OpenGLState::ResetVertexArray(GLuint handle) {
     if (draw.vertex_array == handle) {
         draw.vertex_array = 0;
diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h
index 170dd40470..9dc3f0cc89 100644
--- a/src/video_core/renderer_opengl/gl_state.h
+++ b/src/video_core/renderer_opengl/gl_state.h
@@ -154,7 +154,6 @@ public:
         GLuint read_framebuffer; // GL_READ_FRAMEBUFFER_BINDING
         GLuint draw_framebuffer; // GL_DRAW_FRAMEBUFFER_BINDING
         GLuint vertex_array;     // GL_VERTEX_ARRAY_BINDING
-        GLuint vertex_buffer;    // GL_ARRAY_BUFFER_BINDING
         GLuint shader_program;   // GL_CURRENT_PROGRAM
         GLuint program_pipeline; // GL_PROGRAM_PIPELINE_BINDING
     } draw;
@@ -207,8 +206,6 @@ public:
     void Apply() const;
     /// Apply only the state afecting the framebuffer
     void ApplyFramebufferState() const;
-    /// Apply only the state afecting the vertex buffer
-    void ApplyVertexBufferState() const;
     /// Set the initial OpenGL state
     static void ApplyDefaultState();
     /// Resets any references to the given resource
@@ -216,7 +213,6 @@ public:
     OpenGLState& ResetSampler(GLuint handle);
     OpenGLState& ResetProgram(GLuint handle);
     OpenGLState& ResetPipeline(GLuint handle);
-    OpenGLState& ResetBuffer(GLuint handle);
     OpenGLState& ResetVertexArray(GLuint handle);
     OpenGLState& ResetFramebuffer(GLuint handle);
     void EmulateViewportWithScissor();
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index 4947f06fdd..c268c9686f 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -245,19 +245,20 @@ void RendererOpenGL::InitOpenGLObjects() {
 
     // Generate VAO
     vertex_array.Create();
-
     state.draw.vertex_array = vertex_array.handle;
-    state.draw.vertex_buffer = vertex_buffer.handle;
-    state.Apply();
 
     // Attach vertex data to VAO
-    glBufferData(GL_ARRAY_BUFFER, sizeof(ScreenRectVertex) * 4, nullptr, GL_STREAM_DRAW);
-    glVertexAttribPointer(attrib_position, 2, GL_FLOAT, GL_FALSE, sizeof(ScreenRectVertex),
-                          (GLvoid*)offsetof(ScreenRectVertex, position));
-    glVertexAttribPointer(attrib_tex_coord, 2, GL_FLOAT, GL_FALSE, sizeof(ScreenRectVertex),
-                          (GLvoid*)offsetof(ScreenRectVertex, tex_coord));
-    glEnableVertexAttribArray(attrib_position);
-    glEnableVertexAttribArray(attrib_tex_coord);
+    glNamedBufferData(vertex_buffer.handle, sizeof(ScreenRectVertex) * 4, nullptr, GL_STREAM_DRAW);
+    glVertexArrayAttribFormat(vertex_array.handle, attrib_position, 2, GL_FLOAT, GL_FALSE,
+                              offsetof(ScreenRectVertex, position));
+    glVertexArrayAttribFormat(vertex_array.handle, attrib_tex_coord, 2, GL_FLOAT, GL_FALSE,
+                              offsetof(ScreenRectVertex, tex_coord));
+    glVertexArrayAttribBinding(vertex_array.handle, attrib_position, 0);
+    glVertexArrayAttribBinding(vertex_array.handle, attrib_tex_coord, 0);
+    glEnableVertexArrayAttrib(vertex_array.handle, attrib_position);
+    glEnableVertexArrayAttrib(vertex_array.handle, attrib_tex_coord);
+    glVertexArrayVertexBuffer(vertex_array.handle, 0, vertex_buffer.handle, 0,
+                              sizeof(ScreenRectVertex));
 
     // Allocate textures for the screen
     screen_info.texture.resource.Create();
@@ -369,14 +370,12 @@ void RendererOpenGL::DrawScreenTriangles(const ScreenInfo& screen_info, float x,
     state.texture_units[0].texture = screen_info.display_texture;
     state.texture_units[0].swizzle = {GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA};
     // Workaround brigthness problems in SMO by enabling sRGB in the final output
-    // if it has been used in the frame
-    // Needed because of this bug in QT
-    // QTBUG-50987
+    // if it has been used in the frame. Needed because of this bug in QT: QTBUG-50987
     state.framebuffer_srgb.enabled = OpenGLState::GetsRGBUsed();
     state.Apply();
-    glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices.data());
+    glNamedBufferSubData(vertex_buffer.handle, 0, sizeof(vertices), vertices.data());
     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
-    // restore default state
+    // Restore default state
     state.framebuffer_srgb.enabled = false;
     state.texture_units[0].texture = 0;
     state.Apply();

From 5933b3ea967341eb8e891b8141015c6ecd815830 Mon Sep 17 00:00:00 2001
From: ReinUsesLisp <reinuseslisp@airmail.cc>
Date: Sun, 6 Jan 2019 02:07:20 -0300
Subject: [PATCH 3/4] gl_stream_buffer: Use DSA for buffer management

---
 .../renderer_opengl/gl_buffer_cache.cpp       |  2 +-
 .../renderer_opengl/gl_stream_buffer.cpp      | 26 +++++++++----------
 .../renderer_opengl/gl_stream_buffer.h        |  3 +--
 3 files changed, 14 insertions(+), 17 deletions(-)

diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.cpp b/src/video_core/renderer_opengl/gl_buffer_cache.cpp
index 46a6c03089..bd2b30e77d 100644
--- a/src/video_core/renderer_opengl/gl_buffer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_buffer_cache.cpp
@@ -14,7 +14,7 @@
 namespace OpenGL {
 
 OGLBufferCache::OGLBufferCache(RasterizerOpenGL& rasterizer, std::size_t size)
-    : RasterizerCache{rasterizer}, stream_buffer(GL_ARRAY_BUFFER, size) {}
+    : RasterizerCache{rasterizer}, stream_buffer(size, true) {}
 
 GLintptr OGLBufferCache::UploadMemory(Tegra::GPUVAddr gpu_addr, std::size_t size,
                                       std::size_t alignment, bool cache) {
diff --git a/src/video_core/renderer_opengl/gl_stream_buffer.cpp b/src/video_core/renderer_opengl/gl_stream_buffer.cpp
index b97b895a44..d0b14b3f6d 100644
--- a/src/video_core/renderer_opengl/gl_stream_buffer.cpp
+++ b/src/video_core/renderer_opengl/gl_stream_buffer.cpp
@@ -15,13 +15,12 @@ MICROPROFILE_DEFINE(OpenGL_StreamBuffer, "OpenGL", "Stream Buffer Orphaning",
 
 namespace OpenGL {
 
-OGLStreamBuffer::OGLStreamBuffer(GLenum target, GLsizeiptr size, bool prefer_coherent)
-    : gl_target(target), buffer_size(size) {
+OGLStreamBuffer::OGLStreamBuffer(GLsizeiptr size, bool vertex_data_usage, bool prefer_coherent)
+    : buffer_size(size) {
     gl_buffer.Create();
-    glBindBuffer(gl_target, gl_buffer.handle);
 
     GLsizeiptr allocate_size = size;
-    if (target == GL_ARRAY_BUFFER) {
+    if (vertex_data_usage) {
         // On AMD GPU there is a strange crash in indexed drawing. The crash happens when the buffer
         // read position is near the end and is an out-of-bound access to the vertex buffer. This is
         // probably a bug in the driver and is related to the usage of vec3<byte> attributes in the
@@ -35,18 +34,17 @@ OGLStreamBuffer::OGLStreamBuffer(GLenum target, GLsizeiptr size, bool prefer_coh
         coherent = prefer_coherent;
         const GLbitfield flags =
             GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | (coherent ? GL_MAP_COHERENT_BIT : 0);
-        glBufferStorage(gl_target, allocate_size, nullptr, flags);
-        mapped_ptr = static_cast<u8*>(glMapBufferRange(
-            gl_target, 0, buffer_size, flags | (coherent ? 0 : GL_MAP_FLUSH_EXPLICIT_BIT)));
+        glNamedBufferStorage(gl_buffer.handle, allocate_size, nullptr, flags);
+        mapped_ptr = static_cast<u8*>(glMapNamedBufferRange(
+            gl_buffer.handle, 0, buffer_size, flags | (coherent ? 0 : GL_MAP_FLUSH_EXPLICIT_BIT)));
     } else {
-        glBufferData(gl_target, allocate_size, nullptr, GL_STREAM_DRAW);
+        glNamedBufferData(gl_buffer.handle, allocate_size, nullptr, GL_STREAM_DRAW);
     }
 }
 
 OGLStreamBuffer::~OGLStreamBuffer() {
     if (persistent) {
-        glBindBuffer(gl_target, gl_buffer.handle);
-        glUnmapBuffer(gl_target);
+        glUnmapNamedBuffer(gl_buffer.handle);
     }
     gl_buffer.Release();
 }
@@ -74,7 +72,7 @@ std::tuple<u8*, GLintptr, bool> OGLStreamBuffer::Map(GLsizeiptr size, GLintptr a
         invalidate = true;
 
         if (persistent) {
-            glUnmapBuffer(gl_target);
+            glUnmapNamedBuffer(gl_buffer.handle);
         }
     }
 
@@ -84,7 +82,7 @@ std::tuple<u8*, GLintptr, bool> OGLStreamBuffer::Map(GLsizeiptr size, GLintptr a
                            (coherent ? GL_MAP_COHERENT_BIT : GL_MAP_FLUSH_EXPLICIT_BIT) |
                            (invalidate ? GL_MAP_INVALIDATE_BUFFER_BIT : GL_MAP_UNSYNCHRONIZED_BIT);
         mapped_ptr = static_cast<u8*>(
-            glMapBufferRange(gl_target, buffer_pos, buffer_size - buffer_pos, flags));
+            glMapNamedBufferRange(gl_buffer.handle, buffer_pos, buffer_size - buffer_pos, flags));
         mapped_offset = buffer_pos;
     }
 
@@ -95,11 +93,11 @@ void OGLStreamBuffer::Unmap(GLsizeiptr size) {
     ASSERT(size <= mapped_size);
 
     if (!coherent && size > 0) {
-        glFlushMappedBufferRange(gl_target, buffer_pos - mapped_offset, size);
+        glFlushMappedNamedBufferRange(gl_buffer.handle, buffer_pos - mapped_offset, size);
     }
 
     if (!persistent) {
-        glUnmapBuffer(gl_target);
+        glUnmapNamedBuffer(gl_buffer.handle);
     }
 
     buffer_pos += size;
diff --git a/src/video_core/renderer_opengl/gl_stream_buffer.h b/src/video_core/renderer_opengl/gl_stream_buffer.h
index ae7961bd7e..3d18ecb4da 100644
--- a/src/video_core/renderer_opengl/gl_stream_buffer.h
+++ b/src/video_core/renderer_opengl/gl_stream_buffer.h
@@ -13,7 +13,7 @@ namespace OpenGL {
 
 class OGLStreamBuffer : private NonCopyable {
 public:
-    explicit OGLStreamBuffer(GLenum target, GLsizeiptr size, bool prefer_coherent = false);
+    explicit OGLStreamBuffer(GLsizeiptr size, bool vertex_data_usage, bool prefer_coherent = false);
     ~OGLStreamBuffer();
 
     GLuint GetHandle() const;
@@ -33,7 +33,6 @@ public:
 
 private:
     OGLBuffer gl_buffer;
-    GLenum gl_target;
 
     bool coherent = false;
     bool persistent = false;

From 877a978a221d0418953338fe9644dc2b1d8b7b15 Mon Sep 17 00:00:00 2001
From: ReinUsesLisp <reinuseslisp@airmail.cc>
Date: Wed, 9 Jan 2019 02:40:19 -0300
Subject: [PATCH 4/4] 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.
---
 src/video_core/renderer_opengl/gl_rasterizer.cpp |  6 ++++++
 src/video_core/renderer_opengl/gl_state.cpp      | 13 +++++++------
 src/video_core/renderer_opengl/gl_state.h        |  4 +++-
 3 files changed, 16 insertions(+), 7 deletions(-)

diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 7ce8c2bcc5..61ccfa1048 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -153,6 +153,12 @@ GLuint RasterizerOpenGL::SetupVertexFormat() {
         vao_entry.Create();
         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());
 
         // Use the vertex array as-is, assumes that the data is formatted correctly for OpenGL.
diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp
index 79bb52ddf7..b7ba59350d 100644
--- a/src/video_core/renderer_opengl/gl_state.cpp
+++ b/src/video_core/renderer_opengl/gl_state.cpp
@@ -503,7 +503,6 @@ void OpenGLState::ApplySamplers() const {
 }
 
 void OpenGLState::ApplyFramebufferState() const {
-    // Framebuffer
     if (draw.read_framebuffer != cur_state.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 {
     if (depth_clamp.far_plane == cur_state.depth_clamp.far_plane &&
         depth_clamp.near_plane == cur_state.depth_clamp.near_plane) {
@@ -529,11 +534,7 @@ void OpenGLState::ApplyDepthClamp() const {
 
 void OpenGLState::Apply() const {
     ApplyFramebufferState();
-
-    // Vertex array
-    if (draw.vertex_array != cur_state.draw.vertex_array) {
-        glBindVertexArray(draw.vertex_array);
-    }
+    ApplyVertexArrayState();
 
     // Shader program
     if (draw.shader_program != cur_state.draw.shader_program) {
diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h
index 9dc3f0cc89..a5a7c09205 100644
--- a/src/video_core/renderer_opengl/gl_state.h
+++ b/src/video_core/renderer_opengl/gl_state.h
@@ -204,8 +204,10 @@ public:
     }
     /// Apply this state as the current OpenGL state
     void Apply() const;
-    /// Apply only the state afecting the framebuffer
+    /// Apply only the state affecting the framebuffer
     void ApplyFramebufferState() const;
+    /// Apply only the state affecting the vertex array
+    void ApplyVertexArrayState() const;
     /// Set the initial OpenGL state
     static void ApplyDefaultState();
     /// Resets any references to the given resource