Implement rasterization state for render pipeline - Part 1

This change adds rasterization state into dawn.json. It includes
back face culling and depth bias. It also adds validation code
and default values for rasterization state in ComboRenderPipelineDesc
to pass dawn_unittests.

Validation for back face culling and depth bias related parameters
is quite easy, so unittests are not needed.

BUG=dawn:43

Change-Id: I332cbf3f72545cfa8e62b3534d5a6a6e8fdc6d2a
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/6460
Commit-Queue: Kai Ninomiya <kainino@chromium.org>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
diff --git a/dawn.json b/dawn.json
index 82b243a..7528d46 100644
--- a/dawn.json
+++ b/dawn.json
@@ -378,6 +378,14 @@
             {"name": "compute stage", "type": "pipeline stage descriptor", "annotation": "const*"}
         ]
     },
+    "cull mode": {
+        "category": "enum",
+        "values": [
+            {"value": 0, "name": "none"},
+            {"value": 1, "name": "front"},
+            {"value": 2, "name": "back"}
+        ]
+    },
     "device": {
         "category": "object",
         "methods": [
@@ -550,6 +558,13 @@
     "float": {
         "category": "native"
     },
+    "front face": {
+        "category": "enum",
+        "values": [
+            {"value": 0, "name": "CCW"},
+            {"value": 1, "name": "CW"}
+        ]
+    },
     "index format": {
         "category": "enum",
         "values": [
@@ -671,6 +686,18 @@
         ]
     },
 
+    "rasterization state descriptor": {
+        "category": "structure",
+        "extensible": true,
+        "members": [
+            {"name": "front face", "type": "front face"},
+            {"name": "cull mode", "type": "cull mode"},
+            {"name": "depth bias", "type": "int32_t"},
+            {"name": "depth bias slope scale", "type": "float"},
+            {"name": "depth bias clamp", "type": "float"}
+        ]
+    },
+
     "render pass color attachment descriptor": {
         "category": "structure",
         "members": [
@@ -824,6 +851,7 @@
             {"name": "fragment stage", "type": "pipeline stage descriptor", "annotation": "const*"},
             {"name": "input state", "type": "input state descriptor", "annotation": "const*"},
             {"name": "primitive topology", "type": "primitive topology"},
+            {"name": "rasterization state", "type": "rasterization state descriptor", "annotation": "const*"},
             {"name": "sample count", "type": "uint32_t"},
             {"name": "depth stencil state", "type": "depth stencil state descriptor", "annotation": "const*", "optional": true},
             {"name": "color state count", "type": "uint32_t"},
@@ -1094,6 +1122,9 @@
     "uint32_t": {
         "category": "native"
     },
+    "int32_t": {
+        "category": "native"
+    },
     "uint64_t": {
         "category": "native"
     },
diff --git a/examples/CHelloTriangle.cpp b/examples/CHelloTriangle.cpp
index c79f557..d999868 100644
--- a/examples/CHelloTriangle.cpp
+++ b/examples/CHelloTriangle.cpp
@@ -102,6 +102,15 @@
         inputState.attributes = nullptr;
         descriptor.inputState = &inputState;
 
+        DawnRasterizationStateDescriptor rasterizationState;
+        rasterizationState.nextInChain = nullptr;
+        rasterizationState.frontFace = DAWN_FRONT_FACE_CCW;
+        rasterizationState.cullMode = DAWN_CULL_MODE_NONE;
+        rasterizationState.depthBias = 0;
+        rasterizationState.depthBiasSlopeScale = 0.0;
+        rasterizationState.depthBiasClamp = 0.0;
+        descriptor.rasterizationState = &rasterizationState;
+
         descriptor.primitiveTopology = DAWN_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
 
         descriptor.depthStencilState = nullptr;
diff --git a/src/dawn_native/RenderPipeline.cpp b/src/dawn_native/RenderPipeline.cpp
index eb8a7b8..7fddfc0 100644
--- a/src/dawn_native/RenderPipeline.cpp
+++ b/src/dawn_native/RenderPipeline.cpp
@@ -97,6 +97,16 @@
             return {};
         }
 
+        MaybeError ValidateRasterizationStateDescriptor(
+            const RasterizationStateDescriptor* descriptor) {
+            if (descriptor->nextInChain != nullptr) {
+                return DAWN_VALIDATION_ERROR("nextInChain must be nullptr");
+            }
+            DAWN_TRY(ValidateFrontFace(descriptor->frontFace));
+            DAWN_TRY(ValidateCullMode(descriptor->cullMode));
+            return {};
+        }
+
         MaybeError ValidateColorStateDescriptor(const ColorStateDescriptor* descriptor) {
             if (descriptor->nextInChain != nullptr) {
                 return DAWN_VALIDATION_ERROR("nextInChain must be nullptr");
@@ -264,6 +274,7 @@
                                                  descriptor->layout, dawn::ShaderStage::Vertex));
         DAWN_TRY(ValidatePipelineStageDescriptor(device, descriptor->fragmentStage,
                                                  descriptor->layout, dawn::ShaderStage::Fragment));
+        DAWN_TRY(ValidateRasterizationStateDescriptor(descriptor->rasterizationState));
 
         if ((descriptor->vertexStage->module->GetUsedVertexAttributes() & ~attributesSetMask)
                 .any()) {
@@ -323,6 +334,7 @@
                        dawn::ShaderStageBit::Vertex | dawn::ShaderStageBit::Fragment),
           mInputState(*descriptor->inputState),
           mPrimitiveTopology(descriptor->primitiveTopology),
+          mRasterizationState(*descriptor->rasterizationState),
           mHasDepthStencilAttachment(descriptor->depthStencilState != nullptr),
           mSampleCount(descriptor->sampleCount) {
         uint32_t location = 0;
diff --git a/src/dawn_native/RenderPipeline.h b/src/dawn_native/RenderPipeline.h
index 3d8fbea..186de2c 100644
--- a/src/dawn_native/RenderPipeline.h
+++ b/src/dawn_native/RenderPipeline.h
@@ -75,6 +75,7 @@
         std::bitset<kMaxVertexInputs> mInputsSetMask;
         std::array<VertexInputDescriptor, kMaxVertexInputs> mInputInfos;
         dawn::PrimitiveTopology mPrimitiveTopology;
+        RasterizationStateDescriptor mRasterizationState;
         DepthStencilStateDescriptor mDepthStencilState;
         std::array<ColorStateDescriptor, kMaxColorAttachments> mColorStates;
 
diff --git a/src/tests/unittests/wire/WireArgumentTests.cpp b/src/tests/unittests/wire/WireArgumentTests.cpp
index e96ecd3..dc4c605 100644
--- a/src/tests/unittests/wire/WireArgumentTests.cpp
+++ b/src/tests/unittests/wire/WireArgumentTests.cpp
@@ -105,6 +105,15 @@
     inputState.numAttributes = 0;
     inputState.attributes = nullptr;
 
+    // Create the rasterization state
+    DawnRasterizationStateDescriptor rasterizationState;
+    rasterizationState.nextInChain = nullptr;
+    rasterizationState.frontFace = DAWN_FRONT_FACE_CCW;
+    rasterizationState.cullMode = DAWN_CULL_MODE_NONE;
+    rasterizationState.depthBias = 0;
+    rasterizationState.depthBiasSlopeScale = 0.0;
+    rasterizationState.depthBiasClamp = 0.0;
+
     // Create the depth-stencil state
     DawnStencilStateFaceDescriptor stencilFace;
     stencilFace.compare = DAWN_COMPARE_FUNCTION_ALWAYS;
@@ -155,6 +164,7 @@
     pipelineDescriptor.layout = layout;
     pipelineDescriptor.inputState = &inputState;
     pipelineDescriptor.primitiveTopology = DAWN_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+    pipelineDescriptor.rasterizationState = &rasterizationState;
     pipelineDescriptor.depthStencilState = &depthStencilState;
 
     dawnDeviceCreateRenderPipeline(device, &pipelineDescriptor);
diff --git a/src/tests/unittests/wire/WireOptionalTests.cpp b/src/tests/unittests/wire/WireOptionalTests.cpp
index 29972b1..2cf6c1e 100644
--- a/src/tests/unittests/wire/WireOptionalTests.cpp
+++ b/src/tests/unittests/wire/WireOptionalTests.cpp
@@ -95,6 +95,15 @@
     inputState.numAttributes = 0;
     inputState.attributes = nullptr;
 
+    // Create the rasterization state
+    DawnRasterizationStateDescriptor rasterizationState;
+    rasterizationState.nextInChain = nullptr;
+    rasterizationState.frontFace = DAWN_FRONT_FACE_CCW;
+    rasterizationState.cullMode = DAWN_CULL_MODE_NONE;
+    rasterizationState.depthBias = 0;
+    rasterizationState.depthBiasSlopeScale = 0.0;
+    rasterizationState.depthBiasClamp = 0.0;
+
     // Create the depth-stencil state
     DawnStencilStateFaceDescriptor stencilFace;
     stencilFace.compare = DAWN_COMPARE_FUNCTION_ALWAYS;
@@ -145,6 +154,7 @@
     pipelineDescriptor.layout = layout;
     pipelineDescriptor.inputState = &inputState;
     pipelineDescriptor.primitiveTopology = DAWN_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+    pipelineDescriptor.rasterizationState = &rasterizationState;
 
     // First case: depthStencilState is not null.
     pipelineDescriptor.depthStencilState = &depthStencilState;
diff --git a/src/utils/ComboRenderPipelineDescriptor.cpp b/src/utils/ComboRenderPipelineDescriptor.cpp
index 794760d..c202ee1 100644
--- a/src/utils/ComboRenderPipelineDescriptor.cpp
+++ b/src/utils/ComboRenderPipelineDescriptor.cpp
@@ -68,6 +68,17 @@
         // Set defaults for the input state descriptors.
         descriptor->inputState = &cInputState;
 
+        // Set defaults for the rasterization state descriptor.
+        {
+            cRasterizationState.frontFace = dawn::FrontFace::CCW;
+            cRasterizationState.cullMode = dawn::CullMode::None;
+
+            cRasterizationState.depthBias = 0;
+            cRasterizationState.depthBiasSlopeScale = 0.0;
+            cRasterizationState.depthBiasClamp = 0.0;
+            descriptor->rasterizationState = &cRasterizationState;
+        }
+
         // Set defaults for the color state descriptors.
         {
             descriptor->colorStateCount = 1;
diff --git a/src/utils/ComboRenderPipelineDescriptor.h b/src/utils/ComboRenderPipelineDescriptor.h
index 123f637..69ab688 100644
--- a/src/utils/ComboRenderPipelineDescriptor.h
+++ b/src/utils/ComboRenderPipelineDescriptor.h
@@ -39,6 +39,7 @@
         dawn::PipelineStageDescriptor cFragmentStage;

 

         ComboInputStateDescriptor cInputState;

+        dawn::RasterizationStateDescriptor cRasterizationState;

         std::array<dawn::ColorStateDescriptor*, kMaxColorAttachments> cColorStates;

         dawn::DepthStencilStateDescriptor cDepthStencilState;