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();
}
-