Permit UConvert spec-constant op for SPV_AMD_gpu_shader_int16 (#2264)

See https://github.com/KhronosGroup/glslang/issues/848
diff --git a/source/val/validate_constants.cpp b/source/val/validate_constants.cpp
index eab25ec..e2f20f6 100644
--- a/source/val/validate_constants.cpp
+++ b/source/val/validate_constants.cpp
@@ -329,11 +329,19 @@
       }
       break;
 
+    case SpvOpUConvert:
+      if (!_.features().uconvert_spec_constant_op &&
+          !_.HasCapability(SpvCapabilityKernel)) {
+        return _.diag(SPV_ERROR_INVALID_ID, inst)
+               << "UConvert requires Kernel capability or extension "
+                  "SPV_AMD_gpu_shader_int16";
+      }
+      break;
+
     case SpvOpConvertFToS:
     case SpvOpConvertSToF:
     case SpvOpConvertFToU:
     case SpvOpConvertUToF:
-    case SpvOpUConvert:
     case SpvOpConvertPtrToU:
     case SpvOpConvertUToPtr:
     case SpvOpGenericCastToPtr:
diff --git a/source/val/validation_state.cpp b/source/val/validation_state.cpp
index a07cab9..4a42935 100644
--- a/source/val/validation_state.cpp
+++ b/source/val/validation_state.cpp
@@ -412,6 +412,11 @@
       // https://github.com/KhronosGroup/SPIRV-Tools/issues/1375
       features_.declare_float16_type = true;
       break;
+    case kSPV_AMD_gpu_shader_int16:
+      // This is not yet in the extension, but it's recommended for it.
+      // See https://github.com/KhronosGroup/glslang/issues/848
+      features_.uconvert_spec_constant_op = true;
+      break;
     case kSPV_AMD_shader_ballot:
       // The grammar doesn't encode the fact that SPV_AMD_shader_ballot
       // enables the use of group operations Reduce, InclusiveScan,
diff --git a/source/val/validation_state.h b/source/val/validation_state.h
index f292aca..63f40c5 100644
--- a/source/val/validation_state.h
+++ b/source/val/validation_state.h
@@ -104,6 +104,10 @@
     // - ArrayStride and MatrixStride are multiples of scalar alignment
     // Members need not be listed in offset order
     bool scalar_block_layout = false;
+
+    // Permit UConvert as an OpSpecConstantOp operation.
+    // The Kernel capability already enables it, separately from this flag.
+    bool uconvert_spec_constant_op = false;
   };
 
   ValidationState_t(const spv_const_context context,
diff --git a/test/val/val_constants_test.cpp b/test/val/val_constants_test.cpp
index 80bc970..824d6fd 100644
--- a/test/val/val_constants_test.cpp
+++ b/test/val/val_constants_test.cpp
@@ -280,6 +280,20 @@
                       "InBoundsPtrAccessChain"),
     }));
 
+INSTANTIATE_TEST_CASE_P(
+    UConvertInAMD_gpu_shader_int16, ValidateConstantOp,
+    ValuesIn(std::vector<ConstantOpCase>{
+        // SPV_AMD_gpu_shader_int16 should enable UConvert for OpSpecConstantOp
+        // https://github.com/KhronosGroup/glslang/issues/848
+        {SPV_ENV_UNIVERSAL_1_0,
+         "OpCapability Shader "
+         "OpCapability Linkage ; So we don't need to define a function\n"
+         "OpExtension \"SPV_AMD_gpu_shader_int16\" "
+         "OpMemoryModel Logical Simple " kBasicTypes
+         "%v = OpSpecConstantOp %uint UConvert %uint_0",
+         true, ""},
+    }));
+
 }  // namespace
 }  // namespace val
 }  // namespace spvtools