Split Pipeline in Render and Compute, OpenGL part
diff --git a/src/backend/CMakeLists.txt b/src/backend/CMakeLists.txt
index e94e605..eb4681c 100644
--- a/src/backend/CMakeLists.txt
+++ b/src/backend/CMakeLists.txt
@@ -42,6 +42,8 @@
         ${OPENGL_DIR}/BufferGL.h
         ${OPENGL_DIR}/CommandBufferGL.cpp
         ${OPENGL_DIR}/CommandBufferGL.h
+        ${OPENGL_DIR}/ComputePipelineGL.cpp
+        ${OPENGL_DIR}/ComputePipelineGL.h
         ${OPENGL_DIR}/DepthStencilStateGL.cpp
         ${OPENGL_DIR}/DepthStencilStateGL.h
         ${OPENGL_DIR}/OpenGLBackend.cpp
@@ -52,6 +54,8 @@
         ${OPENGL_DIR}/PipelineGL.h
         ${OPENGL_DIR}/PipelineLayoutGL.cpp
         ${OPENGL_DIR}/PipelineLayoutGL.h
+        ${OPENGL_DIR}/RenderPipelineGL.cpp
+        ${OPENGL_DIR}/RenderPipelineGL.h
         ${OPENGL_DIR}/SamplerGL.cpp
         ${OPENGL_DIR}/SamplerGL.h
         ${OPENGL_DIR}/ShaderModuleGL.cpp
diff --git a/src/backend/opengl/CommandBufferGL.cpp b/src/backend/opengl/CommandBufferGL.cpp
index 5470895..53c371b 100644
--- a/src/backend/opengl/CommandBufferGL.cpp
+++ b/src/backend/opengl/CommandBufferGL.cpp
@@ -16,10 +16,11 @@
 
 #include "backend/Commands.h"
 #include "backend/opengl/BufferGL.h"
+#include "backend/opengl/ComputePipelineGL.h"
 #include "backend/opengl/OpenGLBackend.h"
 #include "backend/opengl/PersistentPipelineStateGL.h"
-#include "backend/opengl/PipelineGL.h"
 #include "backend/opengl/PipelineLayoutGL.h"
+#include "backend/opengl/RenderPipelineGL.h"
 #include "backend/opengl/SamplerGL.h"
 #include "backend/opengl/TextureGL.h"
 
@@ -61,7 +62,9 @@
 
     void CommandBuffer::Execute() {
         Command type;
-        Pipeline* lastPipeline = nullptr;
+        PipelineBase* lastPipeline = nullptr;
+        PipelineGL* lastGLPipeline = nullptr;
+        RenderPipeline* lastRenderPipeline = nullptr;
         uint32_t indexBufferOffset = 0;
         nxt::IndexFormat indexBufferFormat = nxt::IndexFormat::Uint16;
 
@@ -281,10 +284,21 @@
                     }
                     break;
 
-                case Command::SetPipeline:
+                case Command::SetComputePipeline:
                     {
-                        SetPipelineCmd* cmd = commands.NextCommand<SetPipelineCmd>();
+                        SetComputePipelineCmd* cmd = commands.NextCommand<SetComputePipelineCmd>();
+                        ToBackend(cmd->pipeline)->ApplyNow();
+                        lastGLPipeline = ToBackend(cmd->pipeline).Get();
+                        lastPipeline = ToBackend(cmd->pipeline).Get();
+                    }
+                    break;
+
+                case Command::SetRenderPipeline:
+                    {
+                        SetRenderPipelineCmd* cmd = commands.NextCommand<SetRenderPipelineCmd>();
                         ToBackend(cmd->pipeline)->ApplyNow(persistentPipelineState);
+                        lastRenderPipeline = ToBackend(cmd->pipeline).Get();
+                        lastGLPipeline = ToBackend(cmd->pipeline).Get();
                         lastPipeline = ToBackend(cmd->pipeline).Get();
                     }
                     break;
@@ -298,7 +312,7 @@
 
                         for (auto stage : IterateStages(cmd->stage)) {
                             const auto& pushConstants = lastPipeline->GetPushConstants(stage);
-                            const auto& glPushConstants = lastPipeline->GetGLPushConstants(stage);
+                            const auto& glPushConstants = lastGLPipeline->GetGLPushConstants(stage);
                             for (size_t i = 0; i < cmd->count; i++) {
                                 GLint location = glPushConstants[cmd->offset + i];
 
@@ -356,7 +370,7 @@
                                         GLuint sampler = ToBackend(group->GetBindingAsSampler(binding))->GetHandle();
                                         GLuint samplerIndex = indices[binding];
 
-                                        for (auto unit : lastPipeline->GetTextureUnitsForSampler(samplerIndex)) {
+                                        for (auto unit : lastGLPipeline->GetTextureUnitsForSampler(samplerIndex)) {
                                             glBindSampler(unit, sampler);
                                         }
                                     }
@@ -370,7 +384,7 @@
                                         GLenum target = texture->GetGLTarget();
                                         GLuint textureIndex = indices[binding];
 
-                                        for (auto unit : lastPipeline->GetTextureUnitsForTexture(textureIndex)) {
+                                        for (auto unit : lastGLPipeline->GetTextureUnitsForTexture(textureIndex)) {
                                             glActiveTexture(GL_TEXTURE0 + unit);
                                             glBindTexture(target, handle);
                                         }
@@ -408,7 +422,7 @@
                         auto buffers = commands.NextData<Ref<BufferBase>>(cmd->count);
                         auto offsets = commands.NextData<uint32_t>(cmd->count);
 
-                        auto inputState = lastPipeline->GetInputState();
+                        auto inputState = lastRenderPipeline->GetInputState();
 
                         auto& attributesSetMask = inputState->GetAttributesSetMask();
                         for (uint32_t location = 0; location < attributesSetMask.size(); ++location) {
diff --git a/src/backend/opengl/ComputePipelineGL.cpp b/src/backend/opengl/ComputePipelineGL.cpp
new file mode 100644
index 0000000..d2fd8ad
--- /dev/null
+++ b/src/backend/opengl/ComputePipelineGL.cpp
@@ -0,0 +1,29 @@
+// Copyright 2017 The NXT Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "backend/opengl/ComputePipelineGL.h"
+
+namespace backend {
+namespace opengl {
+
+    ComputePipeline::ComputePipeline(ComputePipelineBuilder* builder)
+        : ComputePipelineBase(builder), PipelineGL(this, builder) {
+    }
+
+    void ComputePipeline::ApplyNow() {
+        PipelineGL::ApplyNow();
+    }
+
+}
+}
diff --git a/src/backend/opengl/ComputePipelineGL.h b/src/backend/opengl/ComputePipelineGL.h
new file mode 100644
index 0000000..c0678c3
--- /dev/null
+++ b/src/backend/opengl/ComputePipelineGL.h
@@ -0,0 +1,37 @@
+// Copyright 2017 The NXT Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef BACKEND_OPENGL_COMPUTEPIPELINEGL_H_
+#define BACKEND_OPENGL_COMPUTEPIPELINEGL_H_
+
+#include "backend/ComputePipeline.h"
+
+#include "backend/opengl/PipelineGL.h"
+
+#include "glad/glad.h"
+
+namespace backend {
+namespace opengl {
+
+    class ComputePipeline : public ComputePipelineBase, public PipelineGL {
+        public:
+            ComputePipeline(ComputePipelineBuilder* builder);
+
+            void ApplyNow();
+    };
+
+}
+}
+
+#endif // BACKEND_OPENGL_COMPUTEPIPELINEGL_H_
diff --git a/src/backend/opengl/GeneratedCodeIncludes.h b/src/backend/opengl/GeneratedCodeIncludes.h
index 1ee13ad..f6330b7 100644
--- a/src/backend/opengl/GeneratedCodeIncludes.h
+++ b/src/backend/opengl/GeneratedCodeIncludes.h
@@ -15,10 +15,11 @@
 #include "backend/opengl/OpenGLBackend.h"
 #include "backend/opengl/BufferGL.h"
 #include "backend/opengl/CommandBufferGL.h"
+#include "backend/opengl/ComputePipelineGL.h"
 #include "backend/opengl/DepthStencilStateGL.h"
 #include "backend/opengl/PersistentPipelineStateGL.h"
-#include "backend/opengl/PipelineGL.h"
 #include "backend/opengl/PipelineLayoutGL.h"
+#include "backend/opengl/RenderPipelineGL.h"
 #include "backend/opengl/SamplerGL.h"
 #include "backend/opengl/ShaderModuleGL.h"
 #include "backend/opengl/TextureGL.h"
diff --git a/src/backend/opengl/OpenGLBackend.cpp b/src/backend/opengl/OpenGLBackend.cpp
index 6426d9f..59fbe34 100644
--- a/src/backend/opengl/OpenGLBackend.cpp
+++ b/src/backend/opengl/OpenGLBackend.cpp
@@ -16,9 +16,10 @@
 
 #include "backend/opengl/BufferGL.h"
 #include "backend/opengl/CommandBufferGL.h"
+#include "backend/opengl/ComputePipelineGL.h"
 #include "backend/opengl/DepthStencilStateGL.h"
-#include "backend/opengl/PipelineGL.h"
 #include "backend/opengl/PipelineLayoutGL.h"
+#include "backend/opengl/RenderPipelineGL.h"
 #include "backend/opengl/ShaderModuleGL.h"
 #include "backend/opengl/SamplerGL.h"
 #include "backend/opengl/TextureGL.h"
@@ -72,6 +73,9 @@
     CommandBufferBase* Device::CreateCommandBuffer(CommandBufferBuilder* builder) {
         return new CommandBuffer(builder);
     }
+    ComputePipelineBase* Device::CreateComputePipeline(ComputePipelineBuilder* builder) {
+        return new ComputePipeline(builder);
+    }
     DepthStencilStateBase* Device::CreateDepthStencilState(DepthStencilStateBuilder* builder) {
         return new DepthStencilState(builder);
     }
@@ -81,9 +85,6 @@
     FramebufferBase* Device::CreateFramebuffer(FramebufferBuilder* builder) {
         return new Framebuffer(builder);
     }
-    PipelineBase* Device::CreatePipeline(PipelineBuilder* builder) {
-        return new Pipeline(builder);
-    }
     PipelineLayoutBase* Device::CreatePipelineLayout(PipelineLayoutBuilder* builder) {
         return new PipelineLayout(builder);
     }
@@ -93,6 +94,9 @@
     RenderPassBase* Device::CreateRenderPass(RenderPassBuilder* builder) {
         return new RenderPass(builder);
     }
+    RenderPipelineBase* Device::CreateRenderPipeline(RenderPipelineBuilder* builder) {
+        return new RenderPipeline(builder);
+    }
     SamplerBase* Device::CreateSampler(SamplerBuilder* builder) {
         return new Sampler(builder);
     }
diff --git a/src/backend/opengl/OpenGLBackend.h b/src/backend/opengl/OpenGLBackend.h
index 80097ae..0d23285 100644
--- a/src/backend/opengl/OpenGLBackend.h
+++ b/src/backend/opengl/OpenGLBackend.h
@@ -38,19 +38,20 @@
     class Buffer;
     class BufferView;
     class CommandBuffer;
+    class ComputePipeline;
     class DepthStencilState;
     class Device;
+    class Framebuffer;
     class InputState;
     class PersistentPipelineState;
-    class Pipeline;
     class PipelineLayout;
     class Queue;
+    class RenderPass;
+    class RenderPipeline;
     class Sampler;
     class ShaderModule;
     class Texture;
     class TextureView;
-    class Framebuffer;
-    class RenderPass;
 
     struct OpenGLBackendTraits {
         using BindGroupType = BindGroup;
@@ -58,18 +59,19 @@
         using BufferType = Buffer;
         using BufferViewType = BufferView;
         using CommandBufferType = CommandBuffer;
+        using ComputePipelineType = ComputePipeline;
         using DepthStencilStateType = DepthStencilState;
         using DeviceType = Device;
+        using FramebufferType = Framebuffer;
         using InputStateType = InputState;
-        using PipelineType = Pipeline;
         using PipelineLayoutType = PipelineLayout;
         using QueueType = Queue;
+        using RenderPassType = RenderPass;
+        using RenderPipelineType = RenderPipeline;
         using SamplerType = Sampler;
         using ShaderModuleType = ShaderModule;
         using TextureType = Texture;
         using TextureViewType = TextureView;
-        using FramebufferType = Framebuffer;
-        using RenderPassType = RenderPass;
     };
 
     template<typename T>
@@ -85,13 +87,14 @@
             BufferBase* CreateBuffer(BufferBuilder* builder) override;
             BufferViewBase* CreateBufferView(BufferViewBuilder* builder) override;
             CommandBufferBase* CreateCommandBuffer(CommandBufferBuilder* builder) override;
+            ComputePipelineBase* CreateComputePipeline(ComputePipelineBuilder* builder) override;
             DepthStencilStateBase* CreateDepthStencilState(DepthStencilStateBuilder* builder) override;
             InputStateBase* CreateInputState(InputStateBuilder* builder) override;
             FramebufferBase* CreateFramebuffer(FramebufferBuilder* builder) override;
-            PipelineBase* CreatePipeline(PipelineBuilder* builder) override;
             PipelineLayoutBase* CreatePipelineLayout(PipelineLayoutBuilder* builder) override;
             QueueBase* CreateQueue(QueueBuilder* builder) override;
             RenderPassBase* CreateRenderPass(RenderPassBuilder* builder) override;
+            RenderPipelineBase* CreateRenderPipeline(RenderPipelineBuilder* builder) override;
             SamplerBase* CreateSampler(SamplerBuilder* builder) override;
             ShaderModuleBase* CreateShaderModule(ShaderModuleBuilder* builder) override;
             TextureBase* CreateTexture(TextureBuilder* builder) override;
diff --git a/src/backend/opengl/PipelineGL.cpp b/src/backend/opengl/PipelineGL.cpp
index 1fb4746..e029784 100644
--- a/src/backend/opengl/PipelineGL.cpp
+++ b/src/backend/opengl/PipelineGL.cpp
@@ -14,7 +14,6 @@
 
 #include "backend/opengl/PipelineGL.h"
 
-#include "backend/opengl/DepthStencilStateGL.h"
 #include "backend/opengl/OpenGLBackend.h"
 #include "backend/opengl/PersistentPipelineStateGL.h"
 #include "backend/opengl/PipelineLayoutGL.h"
@@ -43,7 +42,7 @@
 
     }
 
-    Pipeline::Pipeline(PipelineBuilder* builder) : PipelineBase(builder) {
+    PipelineGL::PipelineGL(PipelineBase* parent, PipelineBuilder* builder) {
         auto CreateShader = [](GLenum type, const char* source) -> GLuint {
             GLuint shader = glCreateShader(type);
             glShaderSource(shader, 1, &source, nullptr);
@@ -90,7 +89,7 @@
 
         program = glCreateProgram();
 
-        for (auto stage : IterateStages(GetStageMask())) {
+        for (auto stage : IterateStages(parent->GetStageMask())) {
             const ShaderModule* module = ToBackend(builder->GetStageInfo(stage).module.Get());
 
             GLuint shader = CreateShader(GLShaderType(stage), module->GetSource());
@@ -113,7 +112,7 @@
             }
         }
 
-        for (auto stage : IterateStages(GetStageMask())) {
+        for (auto stage : IterateStages(parent->GetStageMask())) {
             const ShaderModule* module = ToBackend(builder->GetStageInfo(stage).module.Get());
             FillPushConstants(module, &glPushConstants[stage], program);
         }
@@ -121,7 +120,7 @@
         glUseProgram(program);
 
         // The uniforms are part of the program state so we can pre-bind buffer units, texture units etc.
-        const auto& layout = ToBackend(GetLayout());
+        const auto& layout = ToBackend(parent->GetLayout());
         const auto& indices = layout->GetBindingIndexInfo();
 
         for (uint32_t group = 0; group < kMaxBindGroups; ++group) {
@@ -160,7 +159,7 @@
         // Compute links between stages for combined samplers, then bind them to texture units
         {
             std::set<CombinedSampler> combinedSamplersSet;
-            for (auto stage : IterateStages(GetStageMask())) {
+            for (auto stage : IterateStages(parent->GetStageMask())) {
                 const auto& module = ToBackend(builder->GetStageInfo(stage).module);
 
                 for (const auto& combined : module->GetCombinedSamplerInfo()) {
@@ -188,32 +187,26 @@
         }
     }
 
-    const Pipeline::GLPushConstantInfo& Pipeline::GetGLPushConstants(nxt::ShaderStage stage) const {
+    const PipelineGL::GLPushConstantInfo& PipelineGL::GetGLPushConstants(nxt::ShaderStage stage) const {
         return glPushConstants[stage];
     }
 
-    const std::vector<GLuint>& Pipeline::GetTextureUnitsForSampler(GLuint index) const {
+    const std::vector<GLuint>& PipelineGL::GetTextureUnitsForSampler(GLuint index) const {
         ASSERT(index >= 0 && index < unitsForSamplers.size());
         return unitsForSamplers[index];
     }
 
-    const std::vector<GLuint>& Pipeline::GetTextureUnitsForTexture(GLuint index) const {
+    const std::vector<GLuint>& PipelineGL::GetTextureUnitsForTexture(GLuint index) const {
         ASSERT(index >= 0 && index < unitsForSamplers.size());
         return unitsForTextures[index];
     }
 
-    GLuint Pipeline::GetProgramHandle() const {
+    GLuint PipelineGL::GetProgramHandle() const {
         return program;
     }
 
-    void Pipeline::ApplyNow(PersistentPipelineState &persistentPipelineState) {
+    void PipelineGL::ApplyNow() {
         glUseProgram(program);
-
-        auto inputState = ToBackend(GetInputState());
-        glBindVertexArray(inputState->GetVAO());
-
-        auto depthStencilState = ToBackend(GetDepthStencilState());
-        depthStencilState->ApplyNow(persistentPipelineState);
     }
 
 }
diff --git a/src/backend/opengl/PipelineGL.h b/src/backend/opengl/PipelineGL.h
index 1dc8af6..f6fe63c 100644
--- a/src/backend/opengl/PipelineGL.h
+++ b/src/backend/opengl/PipelineGL.h
@@ -28,9 +28,9 @@
     class PersistentPipelineState;
     class ShaderModule;
 
-    class Pipeline : public PipelineBase {
+    class PipelineGL {
         public:
-            Pipeline(PipelineBuilder* builder);
+            PipelineGL(PipelineBase* parent, PipelineBuilder* builder);
 
             using GLPushConstantInfo = std::array<GLint, kMaxPushConstants>;
             using BindingLocations = std::array<std::array<GLint, kMaxBindingsPerGroup>, kMaxBindGroups>;
@@ -40,7 +40,7 @@
             const std::vector<GLuint>& GetTextureUnitsForTexture(GLuint index) const;
             GLuint GetProgramHandle() const;
 
-            void ApplyNow(PersistentPipelineState &persistentPipelineState);
+            void ApplyNow();
 
         private:
             GLuint program;
diff --git a/src/backend/opengl/RenderPipelineGL.cpp b/src/backend/opengl/RenderPipelineGL.cpp
new file mode 100644
index 0000000..1492b4f
--- /dev/null
+++ b/src/backend/opengl/RenderPipelineGL.cpp
@@ -0,0 +1,39 @@
+// Copyright 2017 The NXT Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "backend/opengl/RenderPipelineGL.h"
+
+#include "backend/opengl/DepthStencilStateGL.h"
+#include "backend/opengl/PersistentPipelineStateGL.h"
+#include "backend/opengl/OpenGLBackend.h"
+
+namespace backend {
+namespace opengl {
+
+    RenderPipeline::RenderPipeline(RenderPipelineBuilder* builder)
+        : RenderPipelineBase(builder), PipelineGL(this, builder) {
+    }
+
+    void RenderPipeline::ApplyNow(PersistentPipelineState &persistentPipelineState) {
+        PipelineGL::ApplyNow();
+
+        auto inputState = ToBackend(GetInputState());
+        glBindVertexArray(inputState->GetVAO());
+
+        auto depthStencilState = ToBackend(GetDepthStencilState());
+        depthStencilState->ApplyNow(persistentPipelineState);
+    }
+
+}
+}
diff --git a/src/backend/opengl/RenderPipelineGL.h b/src/backend/opengl/RenderPipelineGL.h
new file mode 100644
index 0000000..3c5edde
--- /dev/null
+++ b/src/backend/opengl/RenderPipelineGL.h
@@ -0,0 +1,41 @@
+// Copyright 2017 The NXT Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef BACKEND_OPENGL_RENDERPIPELINEGL_H_
+#define BACKEND_OPENGL_RENDERPIPELINEGL_H_
+
+#include "backend/RenderPipeline.h"
+
+#include "backend/opengl/PipelineGL.h"
+
+#include "glad/glad.h"
+
+#include <vector>
+
+namespace backend {
+namespace opengl {
+
+    class PersistentPipelineState;
+
+    class RenderPipeline : public RenderPipelineBase, public PipelineGL {
+        public:
+            RenderPipeline(RenderPipelineBuilder* builder);
+
+            void ApplyNow(PersistentPipelineState &persistentPipelineState);
+    };
+
+}
+}
+
+#endif // BACKEND_OPENGL_RENDERPIPELINEGL_H_