| 110 | } |
| 111 | |
| 112 | std::string GenerateShaderAccessChain(const std::string& storage_class, |
| 113 | const std::string& capabilities, |
| 114 | const std::string& extensions) { |
| 115 | std::string spirv = R"( |
| 116 | OpCapability Shader |
| 117 | OpCapability Linkage |
| 118 | OpCapability AtomicStorage |
| 119 | )" + capabilities + R"( |
| 120 | OpExtension "SPV_KHR_storage_buffer_storage_class" |
| 121 | )" + |
| 122 | extensions + R"( |
| 123 | OpMemoryModel Logical GLSL450 |
| 124 | OpName %var "var" |
| 125 | OpName %gep "gep" |
| 126 | %void = OpTypeVoid |
| 127 | %int = OpTypeInt 32 0 |
| 128 | %int2 = OpTypeVector %int 2 |
| 129 | %int_0 = OpConstant %int 0 |
| 130 | %ptr = OpTypePointer )" + storage_class + R"( %int2 |
| 131 | %ptr2 = OpTypePointer )" + |
| 132 | storage_class + R"( %int |
| 133 | %caller_ty = OpTypeFunction %void |
| 134 | %callee_ty = OpTypeFunction %void %ptr2 |
| 135 | )"; |
| 136 | |
| 137 | if (storage_class != "Function") { |
| 138 | spirv += "%var = OpVariable %ptr " + storage_class; |
| 139 | } |
| 140 | |
| 141 | spirv += R"( |
| 142 | %caller = OpFunction %void None %caller_ty |
| 143 | %1 = OpLabel |
| 144 | )"; |
| 145 | |
| 146 | if (storage_class == "Function") { |
| 147 | spirv += "%var = OpVariable %ptr Function"; |
| 148 | } |
| 149 | |
| 150 | spirv += R"( |
| 151 | %gep = OpAccessChain %ptr2 %var %int_0 |
| 152 | %call = OpFunctionCall %void %callee %gep |
| 153 | OpReturn |
| 154 | OpFunctionEnd |
| 155 | %callee = OpFunction %void None %callee_ty |
| 156 | %param = OpFunctionParameter %ptr2 |
| 157 | %2 = OpLabel |
| 158 | OpReturn |
| 159 | OpFunctionEnd |
| 160 | )"; |
| 161 | |
| 162 | return spirv; |
| 163 | } |
| 164 | |
| 165 | TEST_P(ValidateFunctionCall, VariableNoVariablePointers) { |
| 166 | const std::string storage_class = GetParam(); |