Fix for fuzzer-discovered error in SPIR-V compilation.

Unused InterfaceBlocks were not added to the ProgramUsage map. The
ProgramUsageVisitor now makes sure to account for them during its
initial scan.

Change-Id: If3afac8e954c5b685ddc6b63b0f771d8c0b8f207
Bug: oss-fuzz:33405
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/398016
Auto-Submit: John Stiles <johnstiles@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
diff --git a/gn/sksl_tests.gni b/gn/sksl_tests.gni
index 68ef838..5dcd55a 100644
--- a/gn/sksl_tests.gni
+++ b/gn/sksl_tests.gni
@@ -237,6 +237,7 @@
   "/sksl/spirv/OpaqueTypeInArray.sksl",
   "/sksl/workarounds/RewriteMatrixVectorMultiply.sksl",
   "/sksl/errors/UndefinedFunction.sksl",
+  "/sksl/errors/UnusedInterfaceBlock.sksl",
 ]
 
 sksl_shared_tests = [
diff --git a/resources/sksl/errors/UnusedInterfaceBlock.sksl b/resources/sksl/errors/UnusedInterfaceBlock.sksl
new file mode 100644
index 0000000..353cd9e
--- /dev/null
+++ b/resources/sksl/errors/UnusedInterfaceBlock.sksl
@@ -0,0 +1,2 @@
+in s { int I; };
+void main() {}
diff --git a/src/sksl/SkSLAnalysis.cpp b/src/sksl/SkSLAnalysis.cpp
index 52301d2..23384a0 100644
--- a/src/sksl/SkSLAnalysis.cpp
+++ b/src/sksl/SkSLAnalysis.cpp
@@ -210,6 +210,9 @@
                 // they are unread and unwritten.
                 fUsage->fVariableCounts[param];
             }
+        } else if (pe.is<InterfaceBlock>()) {
+            // Ensure interface-block variables exist in the variable usage map.
+            fUsage->fVariableCounts[&pe.as<InterfaceBlock>().variable()];
         }
         return INHERITED::visitProgramElement(pe);
     }
diff --git a/src/sksl/codegen/SkSLSPIRVCodeGenerator.cpp b/src/sksl/codegen/SkSLSPIRVCodeGenerator.cpp
index 907187e..c00ef53 100644
--- a/src/sksl/codegen/SkSLSPIRVCodeGenerator.cpp
+++ b/src/sksl/codegen/SkSLSPIRVCodeGenerator.cpp
@@ -3521,8 +3521,7 @@
             SpvId id = this->writeInterfaceBlock(intf);
 
             const Modifiers& modifiers = intf.variable().modifiers();
-            if (((modifiers.fFlags & Modifiers::kIn_Flag) ||
-                 (modifiers.fFlags & Modifiers::kOut_Flag)) &&
+            if ((modifiers.fFlags & (Modifiers::kIn_Flag | Modifiers::kOut_Flag)) &&
                 modifiers.fLayout.fBuiltin == -1 &&
                 !is_dead(intf.variable(), fProgram.fUsage.get())) {
                 interfaceVars.insert(id);
@@ -3561,8 +3560,7 @@
     for (auto entry : fVariableMap) {
         const Variable* var = entry.first;
         if (var->storage() == Variable::Storage::kGlobal &&
-            ((var->modifiers().fFlags & Modifiers::kIn_Flag) ||
-             (var->modifiers().fFlags & Modifiers::kOut_Flag)) &&
+            (var->modifiers().fFlags & (Modifiers::kIn_Flag | Modifiers::kOut_Flag)) &&
             !is_dead(*var, fProgram.fUsage.get())) {
             interfaceVars.insert(entry.second);
         }
diff --git a/tests/sksl/errors/UnusedInterfaceBlock.asm.frag b/tests/sksl/errors/UnusedInterfaceBlock.asm.frag
new file mode 100644
index 0000000..177aabe
--- /dev/null
+++ b/tests/sksl/errors/UnusedInterfaceBlock.asm.frag
@@ -0,0 +1,32 @@
+### Compilation failed:
+
+error: SPIR-V validation error: Member index 0 is missing a location assignment
+  %s = OpTypeStruct %int
+
+OpCapability Shader
+%1 = OpExtInstImport "GLSL.std.450"
+OpMemoryModel Logical GLSL450
+OpEntryPoint Fragment %main "main" %3 %sk_Clockwise
+OpExecutionMode %main OriginUpperLeft
+OpName %s "s"
+OpMemberName %s 0 "I"
+OpName %sk_Clockwise "sk_Clockwise"
+OpName %main "main"
+OpMemberDecorate %s 0 Offset 0
+OpDecorate %s Block
+OpDecorate %sk_Clockwise BuiltIn FrontFacing
+%int = OpTypeInt 32 1
+%s = OpTypeStruct %int
+%_ptr_Input_s = OpTypePointer Input %s
+%3 = OpVariable %_ptr_Input_s Input
+%bool = OpTypeBool
+%_ptr_Input_bool = OpTypePointer Input %bool
+%sk_Clockwise = OpVariable %_ptr_Input_bool Input
+%void = OpTypeVoid
+%11 = OpTypeFunction %void
+%main = OpFunction %void None %11
+%12 = OpLabel
+OpReturn
+OpFunctionEnd
+
+1 error