Move src/backend to src/dawn_native
diff --git a/src/dawn_native/opengl/PipelineGL.cpp b/src/dawn_native/opengl/PipelineGL.cpp
new file mode 100644
index 0000000..b2e7e65
--- /dev/null
+++ b/src/dawn_native/opengl/PipelineGL.cpp
@@ -0,0 +1,215 @@
+// Copyright 2017 The Dawn 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 "dawn_native/opengl/PipelineGL.h"
+
+#include "common/BitSetIterator.h"
+#include "dawn_native/BindGroupLayout.h"
+#include "dawn_native/opengl/Forward.h"
+#include "dawn_native/opengl/PersistentPipelineStateGL.h"
+#include "dawn_native/opengl/PipelineLayoutGL.h"
+#include "dawn_native/opengl/ShaderModuleGL.h"
+
+#include <iostream>
+#include <set>
+
+namespace backend { namespace opengl {
+
+    namespace {
+
+        GLenum GLShaderType(dawn::ShaderStage stage) {
+            switch (stage) {
+                case dawn::ShaderStage::Vertex:
+                    return GL_VERTEX_SHADER;
+                case dawn::ShaderStage::Fragment:
+                    return GL_FRAGMENT_SHADER;
+                case dawn::ShaderStage::Compute:
+                    return GL_COMPUTE_SHADER;
+                default:
+                    UNREACHABLE();
+            }
+        }
+
+    }  // namespace
+
+    PipelineGL::PipelineGL(PipelineBase* parent, PipelineBuilder* builder) {
+        auto CreateShader = [](GLenum type, const char* source) -> GLuint {
+            GLuint shader = glCreateShader(type);
+            glShaderSource(shader, 1, &source, nullptr);
+            glCompileShader(shader);
+
+            GLint compileStatus = GL_FALSE;
+            glGetShaderiv(shader, GL_COMPILE_STATUS, &compileStatus);
+            if (compileStatus == GL_FALSE) {
+                GLint infoLogLength = 0;
+                glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
+
+                if (infoLogLength > 1) {
+                    std::vector<char> buffer(infoLogLength);
+                    glGetShaderInfoLog(shader, infoLogLength, nullptr, &buffer[0]);
+                    std::cout << source << std::endl;
+                    std::cout << "Program compilation failed:\n";
+                    std::cout << buffer.data() << std::endl;
+                }
+            }
+            return shader;
+        };
+
+        auto FillPushConstants = [](const ShaderModule* module, GLPushConstantInfo* info,
+                                    GLuint program) {
+            const auto& moduleInfo = module->GetPushConstants();
+            for (uint32_t i = 0; i < moduleInfo.names.size(); i++) {
+                (*info)[i] = -1;
+
+                unsigned int size = moduleInfo.sizes[i];
+                if (size == 0) {
+                    continue;
+                }
+
+                GLint location = glGetUniformLocation(program, moduleInfo.names[i].c_str());
+                if (location == -1) {
+                    continue;
+                }
+
+                for (uint32_t offset = 0; offset < size; offset++) {
+                    (*info)[i + offset] = location + offset;
+                }
+                i += size - 1;
+            }
+        };
+
+        mProgram = glCreateProgram();
+
+        for (auto stage : IterateStages(parent->GetStageMask())) {
+            const ShaderModule* module = ToBackend(builder->GetStageInfo(stage).module.Get());
+
+            GLuint shader = CreateShader(GLShaderType(stage), module->GetSource());
+            glAttachShader(mProgram, shader);
+        }
+
+        glLinkProgram(mProgram);
+
+        GLint linkStatus = GL_FALSE;
+        glGetProgramiv(mProgram, GL_LINK_STATUS, &linkStatus);
+        if (linkStatus == GL_FALSE) {
+            GLint infoLogLength = 0;
+            glGetProgramiv(mProgram, GL_INFO_LOG_LENGTH, &infoLogLength);
+
+            if (infoLogLength > 1) {
+                std::vector<char> buffer(infoLogLength);
+                glGetProgramInfoLog(mProgram, infoLogLength, nullptr, &buffer[0]);
+                std::cout << "Program link failed:\n";
+                std::cout << buffer.data() << std::endl;
+            }
+        }
+
+        for (auto stage : IterateStages(parent->GetStageMask())) {
+            const ShaderModule* module = ToBackend(builder->GetStageInfo(stage).module.Get());
+            FillPushConstants(module, &mGlPushConstants[stage], mProgram);
+        }
+
+        glUseProgram(mProgram);
+
+        // The uniforms are part of the program state so we can pre-bind buffer units, texture units
+        // etc.
+        const auto& layout = ToBackend(parent->GetLayout());
+        const auto& indices = layout->GetBindingIndexInfo();
+
+        for (uint32_t group : IterateBitSet(layout->GetBindGroupLayoutsMask())) {
+            const auto& groupInfo = layout->GetBindGroupLayout(group)->GetBindingInfo();
+
+            for (uint32_t binding = 0; binding < kMaxBindingsPerGroup; ++binding) {
+                if (!groupInfo.mask[binding]) {
+                    continue;
+                }
+
+                std::string name = GetBindingName(group, binding);
+                switch (groupInfo.types[binding]) {
+                    case dawn::BindingType::UniformBuffer: {
+                        GLint location = glGetUniformBlockIndex(mProgram, name.c_str());
+                        glUniformBlockBinding(mProgram, location, indices[group][binding]);
+                    } break;
+
+                    case dawn::BindingType::StorageBuffer: {
+                        GLuint location = glGetProgramResourceIndex(
+                            mProgram, GL_SHADER_STORAGE_BLOCK, name.c_str());
+                        glShaderStorageBlockBinding(mProgram, location, indices[group][binding]);
+                    } break;
+
+                    case dawn::BindingType::Sampler:
+                    case dawn::BindingType::SampledTexture:
+                        // These binding types are handled in the separate sampler and texture
+                        // emulation
+                        break;
+                }
+            }
+        }
+
+        // Compute links between stages for combined samplers, then bind them to texture units
+        {
+            std::set<CombinedSampler> combinedSamplersSet;
+            for (auto stage : IterateStages(parent->GetStageMask())) {
+                const auto& module = ToBackend(builder->GetStageInfo(stage).module);
+
+                for (const auto& combined : module->GetCombinedSamplerInfo()) {
+                    combinedSamplersSet.insert(combined);
+                }
+            }
+
+            mUnitsForSamplers.resize(layout->GetNumSamplers());
+            mUnitsForTextures.resize(layout->GetNumSampledTextures());
+
+            GLuint textureUnit = layout->GetTextureUnitsUsed();
+            for (const auto& combined : combinedSamplersSet) {
+                std::string name = combined.GetName();
+                GLint location = glGetUniformLocation(mProgram, name.c_str());
+                glUniform1i(location, textureUnit);
+
+                GLuint samplerIndex =
+                    indices[combined.samplerLocation.group][combined.samplerLocation.binding];
+                mUnitsForSamplers[samplerIndex].push_back(textureUnit);
+
+                GLuint textureIndex =
+                    indices[combined.textureLocation.group][combined.textureLocation.binding];
+                mUnitsForTextures[textureIndex].push_back(textureUnit);
+
+                textureUnit++;
+            }
+        }
+    }
+
+    const PipelineGL::GLPushConstantInfo& PipelineGL::GetGLPushConstants(
+        dawn::ShaderStage stage) const {
+        return mGlPushConstants[stage];
+    }
+
+    const std::vector<GLuint>& PipelineGL::GetTextureUnitsForSampler(GLuint index) const {
+        ASSERT(index < mUnitsForSamplers.size());
+        return mUnitsForSamplers[index];
+    }
+
+    const std::vector<GLuint>& PipelineGL::GetTextureUnitsForTexture(GLuint index) const {
+        ASSERT(index < mUnitsForSamplers.size());
+        return mUnitsForTextures[index];
+    }
+
+    GLuint PipelineGL::GetProgramHandle() const {
+        return mProgram;
+    }
+
+    void PipelineGL::ApplyNow() {
+        glUseProgram(mProgram);
+    }
+
+}}  // namespace backend::opengl