Validate fragment output location doesn't exceed kMaxColorAttachments

This patch adds the validation on the fragment shader output location to
ensure it will never exceed kMaxColorAttachments.

BUG=dawn:202
TEST=dawn_unittests

Change-Id: I4ac4463fd3dfb3c2e9ffecb370f9d9d59393c26d
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/11580
Commit-Queue: Jiawei Shao <jiawei.shao@intel.com>
Reviewed-by: Austin Eng <enga@chromium.org>
diff --git a/src/dawn_native/ShaderModule.cpp b/src/dawn_native/ShaderModule.cpp
index ccb6e32..e3a95a0 100644
--- a/src/dawn_native/ShaderModule.cpp
+++ b/src/dawn_native/ShaderModule.cpp
@@ -190,6 +190,18 @@
                     return;
                 }
             }
+
+            for (const auto& fragmentOutput : resources.stage_outputs) {
+                ASSERT(
+                    compiler.get_decoration_bitset(fragmentOutput.id).get(spv::DecorationLocation));
+                uint32_t location =
+                    compiler.get_decoration(fragmentOutput.id, spv::DecorationLocation);
+                if (location >= kMaxColorAttachments) {
+                    device->HandleError(dawn::ErrorType::Validation,
+                                        "Fragment output location over limits in the SPIRV");
+                    return;
+                }
+            }
         }
     }
 
diff --git a/src/tests/unittests/validation/ShaderModuleValidationTests.cpp b/src/tests/unittests/validation/ShaderModuleValidationTests.cpp
index b1bda01..6826ce7 100644
--- a/src/tests/unittests/validation/ShaderModuleValidationTests.cpp
+++ b/src/tests/unittests/validation/ShaderModuleValidationTests.cpp
@@ -12,10 +12,14 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+#include "common/Constants.h"
+
 #include "tests/unittests/validation/ValidationTest.h"
 
 #include "utils/DawnHelpers.h"
 
+#include <sstream>
+
 class ShaderModuleValidationTest : public ValidationTest {
 };
 
@@ -89,3 +93,18 @@
     std::string error = GetLastDeviceErrorMessage();
     ASSERT_NE(error.find("OpUndef"), std::string::npos);
 }
+
+// Tests that if the output location exceeds kMaxColorAttachments the fragment shader will fail to
+// be compiled.
+TEST_F(ShaderModuleValidationTest, FragmentOutputLocationExceedsMaxColorAttachments) {
+    std::ostringstream stream;
+    stream << R"(#version 450
+              layout(location = )"
+           << kMaxColorAttachments << R"() out vec4 fragColor;
+              void main() {
+                  fragColor = vec4(0.0, 1.0, 0.0, 1.0);
+              })";
+
+    ASSERT_DEVICE_ERROR(utils::CreateShaderModule(device, utils::SingleShaderStage::Fragment,
+                                                  stream.str().c_str()));
+}