Use default texture if hasBinding is false.

Check the result of a `hasBinding` before doing a `getBinding`. If
`hasBinding` is false then return the default texture for that binding
type.

Bug: 441985246
Change-Id: Ib953c7416b581b12cd71cc9a3eb2aa20adf224c3
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/259855
Commit-Queue: dan sinclair <dsinclair@chromium.org>
Reviewed-by: James Price <jrprice@google.com>
diff --git a/src/tint/lang/core/ir/transform/resource_binding.cc b/src/tint/lang/core/ir/transform/resource_binding.cc
index ee5265f..16f744b 100644
--- a/src/tint/lang/core/ir/transform/resource_binding.cc
+++ b/src/tint/lang/core/ir/transform/resource_binding.cc
@@ -85,6 +85,14 @@
 
             auto alias_for_type =
                 helper->GenerateAliases(b, var, iter->second.default_binding_type_order);
+
+            std::unordered_map<ResourceType, uint32_t> resource_type_to_idx;
+            size_t def_size = iter->second.default_binding_type_order.size();
+            for (size_t i = 0; i < def_size; ++i) {
+                auto res_ty = static_cast<ResourceType>(iter->second.default_binding_type_order[i]);
+                resource_type_to_idx.insert({res_ty, uint32_t(i)});
+            }
+
             auto* sb = InjectStorageBuffer(var, iter->second);
 
             std::vector<core::ir::Value*> to_fix;
@@ -111,50 +119,22 @@
                                         break;
                                     }
                                     case core::BuiltinFn::kHasBinding: {
+                                        auto* binding_ty = call->ExplicitTemplateParams()[0];
                                         auto* idx = call->Args()[1];
-
                                         if (idx->Type()->IsSignedIntegerScalar()) {
                                             idx = b.Convert(ty.u32(), idx)->Result();
                                         }
-
-                                        auto* length =
-                                            b.Access(ty.ptr<storage, u32, read>(), sb, 0_u);
-                                        auto* len_check =
-                                            b.LessThan(ty.bool_(), idx, b.Load(length));
-
-                                        auto* has_check = b.If(len_check);
-                                        has_check->SetResult(call->DetachResult());
-
-                                        b.Append(has_check->True(), [&] {
-                                            auto* type_val = b.Access(ty.ptr<storage, u32, read>(),
-                                                                      sb, 1_u, idx);
-
-                                            auto* v = b.Load(type_val);
-                                            auto* eq = b.Equal(
-                                                ty.bool_(), v,
-                                                u32(static_cast<uint32_t>(
-                                                    core::type::TypeToResourceType(
-                                                        call->ExplicitTemplateParams()[0]))));
-                                            b.ExitIf(has_check, eq);
-                                        });
-
-                                        b.Append(has_check->False(),
-                                                 [&] { b.ExitIf(has_check, b.Constant(false)); });
-
+                                        GenHasBinding(call->DetachResult(), binding_ty, idx, sb);
                                         break;
                                     }
                                     case core::BuiltinFn::kGetBinding: {
                                         auto* binding_ty = call->ExplicitTemplateParams()[0];
-                                        auto alias = alias_for_type.Get(binding_ty);
-                                        TINT_ASSERT(alias);
-
-                                        // TODO(439627523): Check hasBinding matches for type
-
-                                        // TODO(439627523): Fix pointer access
-                                        auto* access =
-                                            b.Access(ty.ptr(handle, binding_ty, read),
-                                                     (*alias)->Result(), call->Args()[1]);
-                                        b.LoadWithResult(call->DetachResult(), access);
+                                        auto* idx = call->Args()[1];
+                                        if (idx->Type()->IsSignedIntegerScalar()) {
+                                            idx = b.Convert(ty.u32(), idx)->Result();
+                                        }
+                                        GenGetBinding(call->DetachResult(), binding_ty, idx, sb,
+                                                      alias_for_type, resource_type_to_idx);
                                         break;
                                     }
                                     default:
@@ -177,6 +157,67 @@
         }
     }
 
+    // Note, assumes it's called inside a builder append block.
+    void GenHasBinding(core::ir::InstructionResult* result,
+                       const core::type::Type* type,
+                       core::ir::Value* idx,
+                       core::ir::Var* storage_buffer) {
+        auto* length = b.Access(ty.ptr<storage, u32, read>(), storage_buffer, 0_u);
+        auto* len_check = b.LessThan(ty.bool_(), idx, b.Load(length));
+
+        auto* has_check = b.If(len_check);
+        has_check->SetResult(result);
+
+        b.Append(has_check->True(), [&] {
+            auto* type_val = b.Access(ty.ptr<storage, u32, read>(), storage_buffer, 1_u, idx);
+
+            auto* v = b.Load(type_val);
+            auto* eq = b.Equal(ty.bool_(), v,
+                               u32(static_cast<uint32_t>(core::type::TypeToResourceType(type))));
+            b.ExitIf(has_check, eq);
+        });
+
+        b.Append(has_check->False(), [&] { b.ExitIf(has_check, b.Constant(false)); });
+    }
+
+    // Note, assumes it's called inside a builder append block.
+    void GenGetBinding(core::ir::InstructionResult* result,
+                       const core::type::Type* type,
+                       core::ir::Value* idx,
+                       core::ir::Var* storage_buffer,
+                       const Hashmap<const core::type::Type*, core::ir::Var*, 4>& alias_for_type,
+                       const std::unordered_map<ResourceType, uint32_t>& resource_type_to_idx) {
+        auto* has_result = b.InstructionResult(ty.bool_());
+        GenHasBinding(has_result, type, idx, storage_buffer);
+
+        auto* get_check = b.If(has_result);
+        auto* res = b.InstructionResult(ty.u32());
+        get_check->SetResult(res);
+
+        auto alias = alias_for_type.Get(type);
+        TINT_ASSERT(alias);
+
+        b.Append(get_check->True(), [&] { b.ExitIf(get_check, idx); });
+
+        b.Append(get_check->False(), [&] {
+            auto res_type = core::type::TypeToResourceType(type);
+            auto idx_iter = resource_type_to_idx.find(res_type);
+            TINT_ASSERT(idx_iter != resource_type_to_idx.end());
+
+            auto* len_access = b.Access(ty.ptr<storage, u32, read>(), storage_buffer, 0_u);
+            auto* num_elements = b.Load(len_access);
+
+            auto* r = b.Add(ty.u32(), u32(idx_iter->second), num_elements);
+
+            b.ExitIf(get_check, r);
+        });
+
+        // TODO(439627523): Fix pointer access
+        auto* ptr_ty = ty.ptr(handle, type, read);
+        auto* access = b.Access(ptr_ty, (*alias)->Result(), res);
+        b.LoadWithResult(result, access);
+    }
+
     core::ir::Var* InjectStorageBuffer(core::ir::Var* var, const ResourceBindingInfo& info) {
         core::ir::Var* sb = nullptr;
         b.InsertBefore(var, [&] {
diff --git a/test/tint/extensions/dynamic_binding/access_as_constant.wgsl.expected.spvasm b/test/tint/extensions/dynamic_binding/access_as_constant.wgsl.expected.spvasm
index 9951326..708ad45 100644
--- a/test/tint/extensions/dynamic_binding/access_as_constant.wgsl.expected.spvasm
+++ b/test/tint/extensions/dynamic_binding/access_as_constant.wgsl.expected.spvasm
@@ -1,14 +1,14 @@
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 1
-; Bound: 33
+; Bound: 55
 ; Schema: 0
                OpCapability Shader
                OpCapability RuntimeDescriptorArray
                OpCapability Sampled1D
                OpCapability ImageQuery
                OpExtension "SPV_EXT_descriptor_indexing"
-         %26 = OpExtInstImport "GLSL.std.450"
+         %44 = OpExtInstImport "GLSL.std.450"
                OpMemoryModel Logical GLSL450
                OpEntryPoint Fragment %fs "fs"
                OpExecutionMode %fs OriginUpperLeft
@@ -38,24 +38,54 @@
           %6 = OpVariable %_ptr_StorageBuffer_tint_resource_binding_buffer_tint_explicit_layout StorageBuffer
        %void = OpTypeVoid
          %13 = OpTypeFunction %void
-%_ptr_UniformConstant_4 = OpTypePointer UniformConstant %4
         %int = OpTypeInt 32 1
       %int_2 = OpConstant %int 2
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+     %uint_0 = OpConstant %uint 0
+       %bool = OpTypeBool
+      %false = OpConstantFalse %bool
+%_ptr_UniformConstant_4 = OpTypePointer UniformConstant %4
      %uint_1 = OpConstant %uint 1
       %int_0 = OpConstant %int 0
     %v4float = OpTypeVector %float 4
          %fs = OpFunction %void None %13
          %14 = OpLabel
-         %15 = OpAccessChain %_ptr_UniformConstant_4 %1 %int_2
-         %19 = OpLoad %4 %15 None
-         %20 = OpImageQueryLevels %uint %19
-         %21 = OpISub %uint %20 %uint_1
-         %23 = OpBitcast %uint %int_0
-         %25 = OpExtInst %uint %26 UMin %23 %21
-         %27 = OpImageQuerySizeLod %uint %19 %25
-         %28 = OpISub %uint %27 %uint_1
-         %29 = OpBitcast %uint %int_0
-         %30 = OpExtInst %uint %26 UMin %29 %28
-%texture_load = OpImageFetch %v4float %19 %30 Lod %25
+         %15 = OpBitcast %uint %int_2
+         %18 = OpAccessChain %_ptr_StorageBuffer_uint %6 %uint_0
+         %21 = OpLoad %uint %18 None
+         %22 = OpULessThan %bool %15 %21
+               OpSelectionMerge %24 None
+               OpBranchConditional %22 %25 %26
+         %25 = OpLabel
+         %51 = OpAccessChain %_ptr_StorageBuffer_uint %6 %uint_1 %15
+         %52 = OpLoad %uint %51 None
+         %28 = OpIEqual %bool %52 %uint_1
+               OpBranch %24
+         %26 = OpLabel
+               OpBranch %24
+         %24 = OpLabel
+         %27 = OpPhi %bool %28 %25 %false %26
+               OpSelectionMerge %30 None
+               OpBranchConditional %27 %31 %32
+         %31 = OpLabel
+               OpBranch %30
+         %32 = OpLabel
+         %53 = OpAccessChain %_ptr_StorageBuffer_uint %6 %uint_0
+         %54 = OpLoad %uint %53 None
+         %34 = OpIAdd %uint %uint_0 %54
+               OpBranch %30
+         %30 = OpLabel
+         %33 = OpPhi %uint %15 %31 %34 %32
+         %35 = OpAccessChain %_ptr_UniformConstant_4 %1 %33
+         %37 = OpLoad %4 %35 None
+         %38 = OpImageQueryLevels %uint %37
+         %39 = OpISub %uint %38 %uint_1
+         %41 = OpBitcast %uint %int_0
+         %43 = OpExtInst %uint %44 UMin %41 %39
+         %45 = OpImageQuerySizeLod %uint %37 %43
+         %46 = OpISub %uint %45 %uint_1
+         %47 = OpBitcast %uint %int_0
+         %48 = OpExtInst %uint %44 UMin %47 %46
+%texture_load = OpImageFetch %v4float %37 %48 Lod %43
                OpReturn
                OpFunctionEnd
diff --git a/test/tint/extensions/dynamic_binding/access_as_uniform.wgsl.expected.spvasm b/test/tint/extensions/dynamic_binding/access_as_uniform.wgsl.expected.spvasm
index 6ac7b85..9efde4d 100644
--- a/test/tint/extensions/dynamic_binding/access_as_uniform.wgsl.expected.spvasm
+++ b/test/tint/extensions/dynamic_binding/access_as_uniform.wgsl.expected.spvasm
@@ -1,13 +1,13 @@
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 1
-; Bound: 43
+; Bound: 64
 ; Schema: 0
                OpCapability Shader
                OpCapability RuntimeDescriptorArray
                OpCapability ImageQuery
                OpExtension "SPV_EXT_descriptor_indexing"
-         %32 = OpExtInstImport "GLSL.std.450"
+         %48 = OpExtInstImport "GLSL.std.450"
                OpMemoryModel Logical GLSL450
                OpEntryPoint Fragment %fs "fs"
                OpExecutionMode %fs OriginUpperLeft
@@ -49,29 +49,58 @@
          %16 = OpTypeFunction %void
 %_ptr_Uniform_uint = OpTypePointer Uniform %uint
      %uint_0 = OpConstant %uint 0
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+       %bool = OpTypeBool
+      %false = OpConstantFalse %bool
 %_ptr_UniformConstant_8 = OpTypePointer UniformConstant %8
      %uint_1 = OpConstant %uint 1
         %int = OpTypeInt 32 1
       %int_0 = OpConstant %int 0
      %v3uint = OpTypeVector %uint 3
-         %36 = OpConstantComposite %v3uint %uint_1 %uint_1 %uint_1
+         %52 = OpConstantComposite %v3uint %uint_1 %uint_1 %uint_1
       %v3int = OpTypeVector %int 3
-         %38 = OpConstantNull %v3int
+         %54 = OpConstantNull %v3int
     %v4float = OpTypeVector %float 4
+    %uint_10 = OpConstant %uint 10
          %fs = OpFunction %void None %16
          %17 = OpLabel
          %18 = OpAccessChain %_ptr_Uniform_uint %1 %uint_0
          %21 = OpLoad %uint %18 None
-         %22 = OpAccessChain %_ptr_UniformConstant_8 %5 %21
-         %24 = OpLoad %8 %22 None
-         %25 = OpImageQueryLevels %uint %24
-         %26 = OpISub %uint %25 %uint_1
-         %28 = OpBitcast %uint %int_0
-         %31 = OpExtInst %uint %32 UMin %28 %26
-         %33 = OpImageQuerySizeLod %v3uint %24 %31
-         %35 = OpISub %v3uint %33 %36
-         %37 = OpBitcast %v3uint %38
-         %40 = OpExtInst %v3uint %32 UMin %37 %35
-%texture_load = OpImageFetch %v4float %24 %40 Lod %31
+         %22 = OpAccessChain %_ptr_StorageBuffer_uint %10 %uint_0
+         %24 = OpLoad %uint %22 None
+         %25 = OpULessThan %bool %21 %24
+               OpSelectionMerge %27 None
+               OpBranchConditional %25 %28 %29
+         %28 = OpLabel
+         %59 = OpAccessChain %_ptr_StorageBuffer_uint %10 %uint_1 %21
+         %60 = OpLoad %uint %59 None
+         %31 = OpIEqual %bool %60 %uint_10
+               OpBranch %27
+         %29 = OpLabel
+               OpBranch %27
+         %27 = OpLabel
+         %30 = OpPhi %bool %31 %28 %false %29
+               OpSelectionMerge %33 None
+               OpBranchConditional %30 %34 %35
+         %34 = OpLabel
+               OpBranch %33
+         %35 = OpLabel
+         %62 = OpAccessChain %_ptr_StorageBuffer_uint %10 %uint_0
+         %63 = OpLoad %uint %62 None
+         %37 = OpIAdd %uint %uint_0 %63
+               OpBranch %33
+         %33 = OpLabel
+         %36 = OpPhi %uint %21 %34 %37 %35
+         %38 = OpAccessChain %_ptr_UniformConstant_8 %5 %36
+         %40 = OpLoad %8 %38 None
+         %41 = OpImageQueryLevels %uint %40
+         %42 = OpISub %uint %41 %uint_1
+         %44 = OpBitcast %uint %int_0
+         %47 = OpExtInst %uint %48 UMin %44 %42
+         %49 = OpImageQuerySizeLod %v3uint %40 %47
+         %51 = OpISub %v3uint %49 %52
+         %53 = OpBitcast %v3uint %54
+         %56 = OpExtInst %v3uint %48 UMin %53 %51
+%texture_load = OpImageFetch %v4float %40 %56 Lod %47
                OpReturn
                OpFunctionEnd
diff --git a/test/tint/extensions/dynamic_binding/access_multiple.wgsl.expected.spvasm b/test/tint/extensions/dynamic_binding/access_multiple.wgsl.expected.spvasm
index 48cc9ce..48cc9b2 100644
--- a/test/tint/extensions/dynamic_binding/access_multiple.wgsl.expected.spvasm
+++ b/test/tint/extensions/dynamic_binding/access_multiple.wgsl.expected.spvasm
@@ -1,14 +1,14 @@
 ; SPIR-V
 ; Version: 1.3
 ; Generator: Google Tint Compiler; 1
-; Bound: 76
+; Bound: 137
 ; Schema: 0
                OpCapability Shader
                OpCapability RuntimeDescriptorArray
                OpCapability Sampled1D
                OpCapability ImageQuery
                OpExtension "SPV_EXT_descriptor_indexing"
-         %34 = OpExtInstImport "GLSL.std.450"
+         %52 = OpExtInstImport "GLSL.std.450"
                OpMemoryModel Logical GLSL450
                OpEntryPoint Fragment %fs "fs"
                OpExecutionMode %fs OriginUpperLeft
@@ -53,58 +53,143 @@
          %16 = OpVariable %_ptr_StorageBuffer_tint_resource_binding_buffer_tint_explicit_layout StorageBuffer
        %void = OpTypeVoid
          %22 = OpTypeFunction %void
-%_ptr_UniformConstant_4 = OpTypePointer UniformConstant %4
       %int_2 = OpConstant %int 2
+%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
+     %uint_0 = OpConstant %uint 0
+       %bool = OpTypeBool
+      %false = OpConstantFalse %bool
+%_ptr_UniformConstant_4 = OpTypePointer UniformConstant %4
      %uint_1 = OpConstant %uint 1
       %int_0 = OpConstant %int 0
     %v4float = OpTypeVector %float 4
-%_ptr_UniformConstant_9 = OpTypePointer UniformConstant %9
       %int_1 = OpConstant %int 1
+%_ptr_UniformConstant_9 = OpTypePointer UniformConstant %9
      %v2uint = OpTypeVector %uint 2
-         %52 = OpConstantComposite %v2uint %uint_1 %uint_1
+         %84 = OpConstantComposite %v2uint %uint_1 %uint_1
       %v2int = OpTypeVector %int 2
-         %54 = OpConstantComposite %v2int %int_0 %int_1
+         %86 = OpConstantComposite %v2int %int_0 %int_1
       %v4int = OpTypeVector %int 4
 %_ptr_UniformConstant_14 = OpTypePointer UniformConstant %14
      %v3uint = OpTypeVector %uint 3
-         %69 = OpConstantComposite %v3uint %uint_1 %uint_1 %uint_1
+        %115 = OpConstantComposite %v3uint %uint_1 %uint_1 %uint_1
       %v3int = OpTypeVector %int 3
-         %71 = OpConstantComposite %v3int %int_2 %int_1 %int_0
+        %117 = OpConstantComposite %v3int %int_2 %int_1 %int_0
      %v4uint = OpTypeVector %uint 4
+     %uint_5 = OpConstant %uint 5
+    %uint_12 = OpConstant %uint 12
+     %uint_2 = OpConstant %uint 2
          %fs = OpFunction %void None %22
          %23 = OpLabel
-         %24 = OpAccessChain %_ptr_UniformConstant_4 %1 %int_2
-         %27 = OpLoad %4 %24 None
-         %28 = OpImageQueryLevels %uint %27
-         %29 = OpISub %uint %28 %uint_1
-         %31 = OpBitcast %uint %int_0
-         %33 = OpExtInst %uint %34 UMin %31 %29
-         %35 = OpImageQuerySizeLod %uint %27 %33
-         %36 = OpISub %uint %35 %uint_1
-         %37 = OpBitcast %uint %int_0
-         %38 = OpExtInst %uint %34 UMin %37 %36
-        %t1d = OpImageFetch %v4float %27 %38 Lod %33
-         %41 = OpAccessChain %_ptr_UniformConstant_9 %6 %int_1
-         %44 = OpLoad %9 %41 None
-         %45 = OpImageQueryLevels %uint %44
-         %46 = OpISub %uint %45 %uint_1
-         %47 = OpBitcast %uint %int_0
-         %48 = OpExtInst %uint %34 UMin %47 %46
-         %49 = OpImageQuerySizeLod %v2uint %44 %48
-         %51 = OpISub %v2uint %49 %52
-         %53 = OpBitcast %v2uint %54
-         %56 = OpExtInst %v2uint %34 UMin %53 %51
-        %t2d = OpImageFetch %v4int %44 %56 Lod %48
-         %59 = OpAccessChain %_ptr_UniformConstant_14 %11 %int_1
-         %61 = OpLoad %14 %59 None
-         %62 = OpImageQueryLevels %uint %61
-         %63 = OpISub %uint %62 %uint_1
-         %64 = OpBitcast %uint %int_0
-         %65 = OpExtInst %uint %34 UMin %64 %63
-         %66 = OpImageQuerySizeLod %v3uint %61 %65
-         %68 = OpISub %v3uint %66 %69
-         %70 = OpBitcast %v3uint %71
-         %73 = OpExtInst %v3uint %34 UMin %70 %68
-      %tcube = OpImageFetch %v4uint %61 %73 Lod %65
+         %24 = OpBitcast %uint %int_2
+         %26 = OpAccessChain %_ptr_StorageBuffer_uint %16 %uint_0
+         %29 = OpLoad %uint %26 None
+         %30 = OpULessThan %bool %24 %29
+               OpSelectionMerge %32 None
+               OpBranchConditional %30 %33 %34
+         %33 = OpLabel
+        %122 = OpAccessChain %_ptr_StorageBuffer_uint %16 %uint_1 %24
+        %123 = OpLoad %uint %122 None
+         %36 = OpIEqual %bool %123 %uint_1
+               OpBranch %32
+         %34 = OpLabel
+               OpBranch %32
+         %32 = OpLabel
+         %35 = OpPhi %bool %36 %33 %false %34
+               OpSelectionMerge %38 None
+               OpBranchConditional %35 %39 %40
+         %39 = OpLabel
+               OpBranch %38
+         %40 = OpLabel
+        %124 = OpAccessChain %_ptr_StorageBuffer_uint %16 %uint_0
+        %125 = OpLoad %uint %124 None
+         %42 = OpIAdd %uint %uint_0 %125
+               OpBranch %38
+         %38 = OpLabel
+         %41 = OpPhi %uint %24 %39 %42 %40
+         %43 = OpAccessChain %_ptr_UniformConstant_4 %1 %41
+         %45 = OpLoad %4 %43 None
+         %46 = OpImageQueryLevels %uint %45
+         %47 = OpISub %uint %46 %uint_1
+         %49 = OpBitcast %uint %int_0
+         %51 = OpExtInst %uint %52 UMin %49 %47
+         %53 = OpImageQuerySizeLod %uint %45 %51
+         %54 = OpISub %uint %53 %uint_1
+         %55 = OpBitcast %uint %int_0
+         %56 = OpExtInst %uint %52 UMin %55 %54
+        %t1d = OpImageFetch %v4float %45 %56 Lod %51
+         %59 = OpBitcast %uint %int_1
+         %61 = OpAccessChain %_ptr_StorageBuffer_uint %16 %uint_0
+         %62 = OpLoad %uint %61 None
+         %63 = OpULessThan %bool %59 %62
+               OpSelectionMerge %64 None
+               OpBranchConditional %63 %65 %66
+         %65 = OpLabel
+        %126 = OpAccessChain %_ptr_StorageBuffer_uint %16 %uint_1 %59
+        %127 = OpLoad %uint %126 None
+         %68 = OpIEqual %bool %127 %uint_5
+               OpBranch %64
+         %66 = OpLabel
+               OpBranch %64
+         %64 = OpLabel
+         %67 = OpPhi %bool %68 %65 %false %66
+               OpSelectionMerge %69 None
+               OpBranchConditional %67 %70 %71
+         %70 = OpLabel
+               OpBranch %69
+         %71 = OpLabel
+        %129 = OpAccessChain %_ptr_StorageBuffer_uint %16 %uint_0
+        %130 = OpLoad %uint %129 None
+         %73 = OpIAdd %uint %uint_1 %130
+               OpBranch %69
+         %69 = OpLabel
+         %72 = OpPhi %uint %59 %70 %73 %71
+         %74 = OpAccessChain %_ptr_UniformConstant_9 %6 %72
+         %76 = OpLoad %9 %74 None
+         %77 = OpImageQueryLevels %uint %76
+         %78 = OpISub %uint %77 %uint_1
+         %79 = OpBitcast %uint %int_0
+         %80 = OpExtInst %uint %52 UMin %79 %78
+         %81 = OpImageQuerySizeLod %v2uint %76 %80
+         %83 = OpISub %v2uint %81 %84
+         %85 = OpBitcast %v2uint %86
+         %88 = OpExtInst %v2uint %52 UMin %85 %83
+        %t2d = OpImageFetch %v4int %76 %88 Lod %80
+         %91 = OpBitcast %uint %int_1
+         %92 = OpAccessChain %_ptr_StorageBuffer_uint %16 %uint_0
+         %93 = OpLoad %uint %92 None
+         %94 = OpULessThan %bool %91 %93
+               OpSelectionMerge %95 None
+               OpBranchConditional %94 %96 %97
+         %96 = OpLabel
+        %131 = OpAccessChain %_ptr_StorageBuffer_uint %16 %uint_1 %91
+        %132 = OpLoad %uint %131 None
+         %99 = OpIEqual %bool %132 %uint_12
+               OpBranch %95
+         %97 = OpLabel
+               OpBranch %95
+         %95 = OpLabel
+         %98 = OpPhi %bool %99 %96 %false %97
+               OpSelectionMerge %100 None
+               OpBranchConditional %98 %101 %102
+        %101 = OpLabel
+               OpBranch %100
+        %102 = OpLabel
+        %134 = OpAccessChain %_ptr_StorageBuffer_uint %16 %uint_0
+        %135 = OpLoad %uint %134 None
+        %104 = OpIAdd %uint %uint_2 %135
+               OpBranch %100
+        %100 = OpLabel
+        %103 = OpPhi %uint %91 %101 %104 %102
+        %105 = OpAccessChain %_ptr_UniformConstant_14 %11 %103
+        %107 = OpLoad %14 %105 None
+        %108 = OpImageQueryLevels %uint %107
+        %109 = OpISub %uint %108 %uint_1
+        %110 = OpBitcast %uint %int_0
+        %111 = OpExtInst %uint %52 UMin %110 %109
+        %112 = OpImageQuerySizeLod %v3uint %107 %111
+        %114 = OpISub %v3uint %112 %115
+        %116 = OpBitcast %v3uint %117
+        %119 = OpExtInst %v3uint %52 UMin %116 %114
+      %tcube = OpImageFetch %v4uint %107 %119 Lod %111
                OpReturn
                OpFunctionEnd