[sksl] Emit SPIR-V 1.3

Bump the SPIR-V version emitted by SkSL from 1.0 to 1.3. SPIR-V 1.3 is
the newest version Vulkan 1.1 (Skia's minimum) is required to accept,
and the first version with GroupNonUniform (subgroup) operations.

The SPIRV-Tools target environment used for validation (SkSL validator,
skslc golden disassembly, and viewer) moves from SPV_ENV_VULKAN_1_0 to
SPV_ENV_VULKAN_1_1 accordingly.

Storage buffers still use Uniform + BufferBlock, which is deprecated but
valid through SPIR-V 1.3. No change in generated golden output.

Clients must create their VkInstance with apiVersion >= 1.1 and set

VulkanBackendContext::fMaxAPIVersion to match; see the release note.
Change-Id: Ifa6d0853e8035f58142d1ba0afe573cd1c9b9823
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/1378479
Reviewed-by: Nathan Sanchez <nathanasanchez@google.com>
Commit-Queue: Thomas Smith <thomsmit@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
diff --git a/src/sksl/codegen/SkSLSPIRVCodeGenerator.cpp b/src/sksl/codegen/SkSLSPIRVCodeGenerator.cpp
index d981436..1d3677e 100644
--- a/src/sksl/codegen/SkSLSPIRVCodeGenerator.cpp
+++ b/src/sksl/codegen/SkSLSPIRVCodeGenerator.cpp
@@ -131,10 +131,11 @@
         case StorageClass::kUniform: return SpvStorageClassUniform;
         // Note: In SPIR-V 1.3, a storage buffer can be declared with the "StorageBuffer"
         // storage class and the "Block" decoration and the <1.3 approach we use here ("Uniform"
-        // storage class and the "BufferBlock" decoration) is deprecated. Since we target SPIR-V
-        // 1.0, we have to use the deprecated approach which is well supported in Vulkan and
+        // storage class and the "BufferBlock" decoration) is deprecated. The deprecated approach
+        // is still valid in SPIR-V 1.3 (which we target), is well supported in Vulkan, and
         // addresses SkSL use cases (notably SkSL currently doesn't support pointer features that
-        // would benefit from SPV_KHR_variable_pointers capabilities).
+        // would benefit from SPV_KHR_variable_pointers capabilities). BufferBlock is removed in
+        // SPIR-V 1.4, so targeting 1.4+ will require switching to the StorageBuffer approach.
         case StorageClass::kStorageBuffer: return SpvStorageClassUniform;
         case StorageClass::kOutput: return SpvStorageClassOutput;
         case StorageClass::kWorkgroup: return SpvStorageClassWorkgroup;
diff --git a/src/sksl/codegen/SkSLSPIRVCodeGenerator.h b/src/sksl/codegen/SkSLSPIRVCodeGenerator.h
index 41a41b5..6ab600f 100644
--- a/src/sksl/codegen/SkSLSPIRVCodeGenerator.h
+++ b/src/sksl/codegen/SkSLSPIRVCodeGenerator.h
@@ -27,7 +27,12 @@
 // This is intentionally independent of SpvVersion in spirv.h, which tracks the newest version the
 // header describes. Tools that validate or disassemble SkSL's SPIR-V output must use a
 // spvtools target environment that accepts this version.
-inline constexpr uint32_t kSPIRVVersion = 0x00010000;  // SPIR-V 1.0
+//
+// SPIR-V 1.3 is the newest version a Vulkan 1.1 device (Skia's minimum) is required to accept, and
+// the first to include GroupNonUniform (subgroup) operations. Note that the device's effective API
+// version is min(VkApplicationInfo::apiVersion, VkPhysicalDeviceProperties::apiVersion), which is
+// why VulkanBackendContext::fMaxAPIVersion must match the instance's apiVersion.
+inline constexpr uint32_t kSPIRVVersion = 0x00010300;  // SPIR-V 1.3
 
 /**
  * Converts a Program into a SPIR-V binary. Prefer the std::vector<uint32_t> variant bacause the
diff --git a/src/sksl/codegen/SkSLSPIRVValidator.cpp b/src/sksl/codegen/SkSLSPIRVValidator.cpp
index 4585218..ac07f20 100644
--- a/src/sksl/codegen/SkSLSPIRVValidator.cpp
+++ b/src/sksl/codegen/SkSLSPIRVValidator.cpp
@@ -17,7 +17,8 @@
 static bool validate_spirv(ErrorReporter& reporter,
                            SkSpan<const uint32_t> program,
                            bool disassemble) {
-    spvtools::SpirvTools tools(SPV_ENV_VULKAN_1_0);
+    // Vulkan 1.1 accepts SPIR-V 1.0-1.3. This must accept SkSL::kSPIRVVersion.
+    spvtools::SpirvTools tools(SPV_ENV_VULKAN_1_1);
     std::string errors;
     auto msgFn = [&errors](spv_message_level_t, const char*, const spv_position_t&, const char* m) {
         errors += "SPIR-V validation error: ";
diff --git a/tools/skslc/Main.cpp b/tools/skslc/Main.cpp
index 3209377..cd2aa70 100644
--- a/tools/skslc/Main.cpp
+++ b/tools/skslc/Main.cpp
@@ -657,7 +657,9 @@
                         return false;
                     }
                     // Convert the string-stream to a SPIR-V disassembly.
-                    spvtools::SpirvTools tools(SPV_ENV_VULKAN_1_0);
+                    static_assert(SkSL::kSPIRVVersion <= 0x00010300,
+                                  "SPV_ENV_VULKAN_1_1 only accepts SPIR-V up to 1.3");
+                    spvtools::SpirvTools tools(SPV_ENV_VULKAN_1_1);
                     std::string disassembly;
                     uint32_t options = spvtools::SpirvTools::kDefaultDisassembleOption;
                     options |= SPV_BINARY_TO_TEXT_OPTION_COMMENT |
diff --git a/tools/viewer/Viewer.cpp b/tools/viewer/Viewer.cpp
index 0b94e93..8a305f8 100644
--- a/tools/viewer/Viewer.cpp
+++ b/tools/viewer/Viewer.cpp
@@ -3221,7 +3221,8 @@
 #if defined(SK_VULKAN)
                     if (isVulkan && !sksl) {
                         // Disassemble the SPIR-V into its textual form.
-                        spvtools::SpirvTools tools(SPV_ENV_VULKAN_1_0);
+                        // Vulkan 1.1 accepts SPIR-V 1.0-1.3, matching SkSL::kSPIRVVersion.
+                        spvtools::SpirvTools tools(SPV_ENV_VULKAN_1_1);
                         uint32_t options = spvtools::SpirvTools::kDefaultDisassembleOption;
                         options |= SPV_BINARY_TO_TEXT_OPTION_COMMENT |
                                    SPV_BINARY_TO_TEXT_OPTION_INDENT |