diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp
index a46ed4bd7e8ddc0f531a8c672dbfba636e2b3b11..68f91cc7569617e1980095b81a1fcb47c807b561 100644
--- a/src/video_core/engines/maxwell_3d.cpp
+++ b/src/video_core/engines/maxwell_3d.cpp
@@ -222,6 +222,18 @@ void Maxwell3D::DrawArrays() {
         debug_context->OnEvent(Tegra::DebugContext::Event::FinishedPrimitiveBatch, nullptr);
     }
 
+    // Both instance configuration registers can not be set at the same time.
+    ASSERT_MSG(!regs.draw.instance_next || !regs.draw.instance_cont,
+               "Illegal combination of instancing parameters");
+
+    if (regs.draw.instance_next) {
+        // Increment the current instance *before* drawing.
+        state.current_instance += 1;
+    } else if (!regs.draw.instance_cont) {
+        // Reset the current instance to 0.
+        state.current_instance = 0;
+    }
+
     const bool is_indexed{regs.index_array.count && !regs.vertex_buffer.count};
     rasterizer.AccelerateDrawBatch(is_indexed);
 
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h
index 1b30ce01853c3e77fb56feca183a49ba08fc69d9..771eb5abcb5f448db5af03c98740154272d11dd0 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -638,6 +638,8 @@ public:
                     union {
                         u32 vertex_begin_gl;
                         BitField<0, 16, PrimitiveTopology> topology;
+                        BitField<26, 1, u32> instance_next;
+                        BitField<27, 1, u32> instance_cont;
                     };
                 } draw;
 
@@ -830,6 +832,7 @@ public:
         };
 
         std::array<ShaderStageInfo, Regs::MaxShaderStage> shader_stages;
+        u32 current_instance = 0; ///< Current instance to be used to simulate instanced rendering.
     };
 
     State state{};
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 9d1549fe9e7227ee1e720d87d503a5af1ed3f47a..93eadde7a7b7f720cced4eafab073e2f6d2a7a14 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -124,7 +124,7 @@ std::pair<u8*, GLintptr> RasterizerOpenGL::SetupVertexArrays(u8* array_ptr,
         glBindVertexBuffer(index, stream_buffer.GetHandle(), vertex_buffer_offset,
                            vertex_array.stride);
 
-        ASSERT_MSG(vertex_array.divisor == 0, "Vertex buffer divisor unimplemented");
+        ASSERT_MSG(vertex_array.divisor == 0, "Instanced vertex arrays are not supported");
     }
 
     // Use the vertex array as-is, assumes that the data is formatted correctly for OpenGL.
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index dabf98b742fdc942998816d93070d6be7eb771b6..5a05c79ef2059feaba30c79c342187f2fa32489f 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -538,7 +538,7 @@ private:
             // vertex shader, and what's the value of the fourth element when inside a Tess Eval
             // shader.
             ASSERT(stage == Maxwell3D::Regs::ShaderStage::Vertex);
-            return "vec4(0, 0, uintBitsToFloat(gl_InstanceID), uintBitsToFloat(gl_VertexID))";
+            return "vec4(0, 0, uintBitsToFloat(instance_id.x), uintBitsToFloat(gl_VertexID))";
         default:
             const u32 index{static_cast<u32>(attribute) -
                             static_cast<u32>(Attribute::Index::Attribute_0)};
diff --git a/src/video_core/renderer_opengl/gl_shader_gen.cpp b/src/video_core/renderer_opengl/gl_shader_gen.cpp
index 129c777d18b383a8679fc266b7769daebdd74467..57e0e17261957fa7888d0ea6dd0ab5ad8c848e9c 100644
--- a/src/video_core/renderer_opengl/gl_shader_gen.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_gen.cpp
@@ -38,6 +38,7 @@ out vec4 position;
 
 layout (std140) uniform vs_config {
     vec4 viewport_flip;
+    uvec4 instance_id;
 };
 
 void main() {
@@ -90,6 +91,7 @@ out vec4 color;
 
 layout (std140) uniform fs_config {
     vec4 viewport_flip;
+    uvec4 instance_id;
 };
 
 void main() {
diff --git a/src/video_core/renderer_opengl/gl_shader_manager.cpp b/src/video_core/renderer_opengl/gl_shader_manager.cpp
index 415d42fdacc7675b45b07088cd8b9ed7641ef9e4..f0886caac0c04217a31ee8b292dd0d10f2f72734 100644
--- a/src/video_core/renderer_opengl/gl_shader_manager.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_manager.cpp
@@ -37,11 +37,16 @@ void SetShaderUniformBlockBindings(GLuint shader) {
 } // namespace Impl
 
 void MaxwellUniformData::SetFromRegs(const Maxwell3D::State::ShaderStageInfo& shader_stage) {
-    const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs;
+    const auto& gpu = Core::System::GetInstance().GPU().Maxwell3D();
+    const auto& regs = gpu.regs;
+    const auto& state = gpu.state;
 
     // TODO(bunnei): Support more than one viewport
     viewport_flip[0] = regs.viewport_transform[0].scale_x < 0.0 ? -1.0f : 1.0f;
     viewport_flip[1] = regs.viewport_transform[0].scale_y < 0.0 ? -1.0f : 1.0f;
+
+    // We only assign the instance to the first component of the vector, the rest is just padding.
+    instance_id[0] = state.current_instance;
 }
 
 } // namespace GLShader
diff --git a/src/video_core/renderer_opengl/gl_shader_manager.h b/src/video_core/renderer_opengl/gl_shader_manager.h
index 716933a0b54a1b016122ebb0e10b4b320bbd25ee..75fa7360553e85410b9822c4092d9579b2a1bc3f 100644
--- a/src/video_core/renderer_opengl/gl_shader_manager.h
+++ b/src/video_core/renderer_opengl/gl_shader_manager.h
@@ -24,14 +24,15 @@ void SetShaderUniformBlockBindings(GLuint shader);
 } // namespace Impl
 
 /// Uniform structure for the Uniform Buffer Object, all vectors must be 16-byte aligned
-// NOTE: Always keep a vec4 at the end. The GL spec is not clear wether the alignment at
+// NOTE: Always keep a vec4 at the end. The GL spec is not clear whether the alignment at
 //       the end of a uniform block is included in UNIFORM_BLOCK_DATA_SIZE or not.
 //       Not following that rule will cause problems on some AMD drivers.
 struct MaxwellUniformData {
     void SetFromRegs(const Maxwell3D::State::ShaderStageInfo& shader_stage);
     alignas(16) GLvec4 viewport_flip;
+    alignas(16) GLuvec4 instance_id;
 };
-static_assert(sizeof(MaxwellUniformData) == 16, "MaxwellUniformData structure size is incorrect");
+static_assert(sizeof(MaxwellUniformData) == 32, "MaxwellUniformData structure size is incorrect");
 static_assert(sizeof(MaxwellUniformData) < 16384,
               "MaxwellUniformData structure must be less than 16kb as per the OpenGL spec");