Dawn backend: first triangle.

Nothing is cached in this initial version; all the magic happens in
GrDawnGpuRTCommandBuffer::beginDraw(). It builds the program,
sets the uniform data, converts the vertex attributes, initializes
rasterization state and blend state, creates a pipeline and bind group
and sets them.
send[Indexed]InstancedMeshToGpu() encodes the Dawn draw commands.
GrDawnGpuProgramBuilder::beginRenderPass() then finishes
the command encoder and submits the resulting command buffer.

Change-Id: Ie9c160cd18a2c4ef1bde66f86a52227e3bf1b570
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/230457
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Stephen White <senorblanco@chromium.org>
diff --git a/src/gpu/dawn/GrDawnGpuCommandBuffer.cpp b/src/gpu/dawn/GrDawnGpuCommandBuffer.cpp
index d2db9a6..87ede07 100644
--- a/src/gpu/dawn/GrDawnGpuCommandBuffer.cpp
+++ b/src/gpu/dawn/GrDawnGpuCommandBuffer.cpp
@@ -7,15 +7,18 @@
 
 #include "src/gpu/dawn/GrDawnGpuCommandBuffer.h"
 
-#include "include/core/SkRect.h"
 #include "src/gpu/GrFixedClip.h"
 #include "src/gpu/GrMesh.h"
 #include "src/gpu/GrOpFlushState.h"
 #include "src/gpu/GrPipeline.h"
 #include "src/gpu/GrRenderTargetPriv.h"
 #include "src/gpu/GrTexturePriv.h"
+#include "src/gpu/dawn/GrDawnBuffer.h"
 #include "src/gpu/dawn/GrDawnGpu.h"
+#include "src/gpu/dawn/GrDawnProgramBuilder.h"
 #include "src/gpu/dawn/GrDawnRenderTarget.h"
+#include "src/gpu/dawn/GrDawnUtil.h"
+#include "src/sksl/SkSLCompiler.h"
 
 void GrDawnGpuTextureCommandBuffer::copy(GrSurface* src, const SkIRect& srcRect,
                                          const SkIPoint& dstPoint) {
@@ -55,13 +58,31 @@
                                                    const LoadAndStoreInfo& colorInfo,
                                                    const StencilLoadAndStoreInfo& stencilInfo)
         : INHERITED(rt, origin)
-        , fGpu(gpu) {
-    this->init();
+        , fGpu(gpu)
+        , fColorInfo(colorInfo) {
+    fEncoder = fGpu->device().CreateCommandEncoder();
+    fPassEncoder = beginRenderPass();
 }
 
-void GrDawnGpuRTCommandBuffer::init() {
-}
+dawn::RenderPassEncoder GrDawnGpuRTCommandBuffer::beginRenderPass() {
+    dawn::Texture texture = static_cast<GrDawnRenderTarget*>(fRenderTarget)->texture();
+    dawn::TextureView colorView = texture.CreateDefaultView();
+    const float *c = fColorInfo.fClearColor.vec();
+    dawn::LoadOp colorOp = to_dawn_load_op(fColorInfo.fLoadOp);
 
+    dawn::RenderPassColorAttachmentDescriptor colorAttachment;
+    colorAttachment.attachment = colorView;
+    colorAttachment.resolveTarget = nullptr;
+    colorAttachment.clearColor = { c[0], c[1], c[2], c[3] };
+    colorAttachment.loadOp = colorOp;
+    colorAttachment.storeOp = dawn::StoreOp::Store;
+    dawn::RenderPassColorAttachmentDescriptor* colorAttachments = { &colorAttachment };
+    dawn::RenderPassDescriptor renderPassDescriptor;
+    renderPassDescriptor.colorAttachmentCount = 1;
+    renderPassDescriptor.colorAttachments = &colorAttachments;
+    renderPassDescriptor.depthStencilAttachment = nullptr;
+    return fEncoder.BeginRenderPass(&renderPassDescriptor);
+}
 
 GrDawnGpuRTCommandBuffer::~GrDawnGpuRTCommandBuffer() {
 }
@@ -69,11 +90,13 @@
 GrGpu* GrDawnGpuRTCommandBuffer::gpu() { return fGpu; }
 
 void GrDawnGpuRTCommandBuffer::end() {
+    fPassEncoder.EndPass();
 }
 
 void GrDawnGpuRTCommandBuffer::submit() {
-    if (fCommandBuffer) {
-        fGpu->queue().Submit(1, &fCommandBuffer);
+    dawn::CommandBuffer commandBuffer = fEncoder.Finish();
+    if (commandBuffer) {
+        fGpu->queue().Submit(1, &commandBuffer);
     }
 }
 
@@ -111,9 +134,130 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-void GrDawnGpuRTCommandBuffer::bindGeometry(const GrBuffer* indexBuffer,
-                                            const GrBuffer* vertexBuffer,
-                                            const GrBuffer* instanceBuffer) {
+static dawn::VertexFormat to_dawn_vertex_format(GrVertexAttribType type) {
+    switch (type) {
+    case kFloat_GrVertexAttribType:
+    case kHalf_GrVertexAttribType:
+        return dawn::VertexFormat::Float;
+    case kFloat2_GrVertexAttribType:
+    case kHalf2_GrVertexAttribType:
+        return dawn::VertexFormat::Float2;
+    case kFloat3_GrVertexAttribType:
+    case kHalf3_GrVertexAttribType:
+        return dawn::VertexFormat::Float3;
+    case kFloat4_GrVertexAttribType:
+    case kHalf4_GrVertexAttribType:
+        return dawn::VertexFormat::Float4;
+    case kUShort2_GrVertexAttribType:
+        return dawn::VertexFormat::UShort2;
+    case kUByte4_norm_GrVertexAttribType:
+        return dawn::VertexFormat::UChar4Norm;
+    default:
+        SkASSERT(!"unsupported vertex format");
+        return dawn::VertexFormat::Float4;
+    }
+}
+
+void GrDawnGpuRTCommandBuffer::beginDraw(const GrPipeline& pipeline,
+                                         const GrPrimitiveProcessor& primProc,
+                                         const GrTextureProxy* const primProcProxies[],
+                                         bool hasPoints) {
+    GrProgramDesc desc;
+    GrProgramDesc::Build(&desc, fRenderTarget, primProc, hasPoints, pipeline, fGpu);
+    dawn::TextureFormat colorFormat;
+    SkAssertResult(GrPixelConfigToDawnFormat(fRenderTarget->config(), &colorFormat));
+    sk_sp<GrDawnProgram> program = GrDawnProgramBuilder::Build(fGpu, fRenderTarget, fOrigin,
+                                                               pipeline, primProc, primProcProxies,
+                                                               colorFormat, &desc);
+    SkASSERT(program);
+    program->setData(primProc, fRenderTarget, fOrigin, pipeline);
+
+    std::vector<dawn::VertexBufferDescriptor> inputs;
+    std::vector<dawn::VertexAttributeDescriptor> vertexAttributes;
+    if (primProc.numVertexAttributes() > 0) {
+        size_t offset = 0;
+        int i = 0;
+        for (const auto& attrib : primProc.vertexAttributes()) {
+            dawn::VertexAttributeDescriptor attribute;
+            attribute.shaderLocation = i;
+            attribute.offset = offset;
+            attribute.format = to_dawn_vertex_format(attrib.cpuType());
+            vertexAttributes.push_back(attribute);
+            offset += attrib.sizeAlign4();
+            i++;
+        }
+        dawn::VertexBufferDescriptor input;
+        input.stride = offset;
+        input.stepMode = dawn::InputStepMode::Vertex;
+        input.attributes = &vertexAttributes.front();
+        input.attributeCount = vertexAttributes.size();
+        inputs.push_back(input);
+    }
+    std::vector<dawn::VertexAttributeDescriptor> instanceAttributes;
+    if (primProc.numInstanceAttributes() > 0) {
+        size_t offset = 0;
+        int i = 0;
+        for (const auto& attrib : primProc.instanceAttributes()) {
+            dawn::VertexAttributeDescriptor attribute;
+            attribute.shaderLocation = i;
+            attribute.offset = offset;
+            attribute.format = to_dawn_vertex_format(attrib.cpuType());
+            instanceAttributes.push_back(attribute);
+            offset += attrib.sizeAlign4();
+            i++;
+        }
+        dawn::VertexBufferDescriptor input;
+        input.stride = offset;
+        input.stepMode = dawn::InputStepMode::Instance;
+        input.attributes = &instanceAttributes.front();
+        input.attributeCount = instanceAttributes.size();
+        inputs.push_back(input);
+    }
+    dawn::VertexInputDescriptor vertexInput;
+    vertexInput.bufferCount = inputs.size();
+    vertexInput.buffers = &inputs.front();
+    vertexInput.indexFormat = dawn::IndexFormat::Uint16;
+
+    dawn::PipelineStageDescriptor vsDesc;
+    vsDesc.module = program->fVSModule;
+    vsDesc.entryPoint = "main";
+
+    dawn::PipelineStageDescriptor fsDesc;
+    fsDesc.module = program->fFSModule;
+    fsDesc.entryPoint = "main";
+
+    dawn::StencilStateFaceDescriptor stencilFace;
+    stencilFace.compare = dawn::CompareFunction::Always;
+    stencilFace.failOp = dawn::StencilOperation::Keep;
+    stencilFace.depthFailOp = dawn::StencilOperation::Keep;
+    stencilFace.passOp = dawn::StencilOperation::Replace;
+
+    dawn::RasterizationStateDescriptor rastDesc;
+
+    rastDesc.frontFace = dawn::FrontFace::CW;
+    rastDesc.cullMode = dawn::CullMode::None;
+    rastDesc.depthBias = 0;
+    rastDesc.depthBiasSlopeScale = 0.0f;
+    rastDesc.depthBiasClamp = 0.0f;
+
+    dawn::RenderPipelineDescriptor rpDesc;
+    rpDesc.layout = program->fPipelineLayout;
+    rpDesc.vertexStage = &vsDesc;
+    rpDesc.fragmentStage = &fsDesc;
+    rpDesc.vertexInput = &vertexInput;
+    rpDesc.rasterizationState = &rastDesc;
+    rpDesc.primitiveTopology = dawn::PrimitiveTopology::TriangleList;
+    rpDesc.sampleCount = 1;
+    rpDesc.depthStencilState = nullptr;
+    rpDesc.colorStateCount = 1;
+    dawn::ColorStateDescriptor* colorStates[] = { &program->fColorState };
+    rpDesc.colorStates = colorStates;
+    dawn::RenderPipeline renderPipeline = fGpu->device().CreateRenderPipeline(&rpDesc);
+    fPassEncoder.SetPipeline(renderPipeline);
+    fPassEncoder.SetBindGroup(0, program->fUniformBindGroup, 0, nullptr);
+}
+
+void GrDawnGpuRTCommandBuffer::endDraw() {
 }
 
 void GrDawnGpuRTCommandBuffer::onDraw(const GrPrimitiveProcessor& primProc,
@@ -126,12 +270,24 @@
     if (!meshCount) {
         return;
     }
-    GrFragmentProcessor::Iter iter(pipeline);
-
+    bool hasPoints = false;
     for (int i = 0; i < meshCount; ++i) {
-        const GrMesh& mesh = meshes[i];
-        mesh.sendToGpu(this);
+        if (meshes[i].primitiveType() == GrPrimitiveType::kPoints) {
+            hasPoints = true;
+        }
     }
+    const GrTextureProxy* const* primProcProxies = nullptr;
+    if (dynamicStateArrays && dynamicStateArrays->fPrimitiveProcessorTextures) {
+        primProcProxies = dynamicStateArrays->fPrimitiveProcessorTextures;
+    } else if (fixedDynamicState) {
+        primProcProxies = fixedDynamicState->fPrimitiveProcessorTextures;
+    }
+
+    beginDraw(pipeline, primProc, primProcProxies, hasPoints);
+    for (int i = 0; i < meshCount; ++i) {
+        meshes[i].sendToGpu(this);
+    }
+    endDraw();
 }
 
 void GrDawnGpuRTCommandBuffer::sendInstancedMeshToGpu(GrPrimitiveType,
@@ -141,7 +297,10 @@
                                                       const GrBuffer* instanceBuffer,
                                                       int instanceCount,
                                                       int baseInstance) {
-    this->bindGeometry(nullptr, vertexBuffer, instanceBuffer);
+    static const uint64_t vertexBufferOffsets[1] = {0};
+    dawn::Buffer vb = static_cast<const GrDawnBuffer*>(vertexBuffer)->get();
+    fPassEncoder.SetVertexBuffers(0, 1, &vb, vertexBufferOffsets);
+    fPassEncoder.Draw(vertexCount, 1, baseVertex, baseInstance);
     fGpu->stats()->incNumDraws();
 }
 
@@ -155,7 +314,12 @@
                                                              int instanceCount,
                                                              int baseInstance,
                                                              GrPrimitiveRestart restart) {
-    this->bindGeometry(indexBuffer, vertexBuffer, instanceBuffer);
+    uint64_t vertexBufferOffsets[1];
+    vertexBufferOffsets[0] = 0;
+    dawn::Buffer vb = static_cast<const GrDawnBuffer*>(vertexBuffer)->get();
+    dawn::Buffer ib = static_cast<const GrDawnBuffer*>(indexBuffer)->get();
+    fPassEncoder.SetIndexBuffer(ib, 0);
+    fPassEncoder.SetVertexBuffers(0, 1, &vb, vertexBufferOffsets);
+    fPassEncoder.DrawIndexed(indexCount, 1, baseIndex, baseVertex, baseInstance);
     fGpu->stats()->incNumDraws();
 }
-