| 170 | } |
| 171 | |
| 172 | uint32_t GcnCompiler::emitComputeDivergence() |
| 173 | { |
| 174 | // For compute shader, we use even subgroup against low 32 bits of exec |
| 175 | // and odd subgroup for high 32 bits. |
| 176 | /* |
| 177 | * if (mod(gl_SubgroupID, 2.0) < 1.0) |
| 178 | * { |
| 179 | * value = exec_lo |
| 180 | * } |
| 181 | * else |
| 182 | * { |
| 183 | * value = exec_hi |
| 184 | * } |
| 185 | * result = (value & gl_SubgroupEqMask.x) != 0; |
| 186 | */ |
| 187 | const uint32_t utypeId = getScalarTypeId(GcnScalarType::Uint32); |
| 188 | const uint32_t ftypeId = getScalarTypeId(GcnScalarType::Float32); |
| 189 | const uint32_t btypeId = m_module.defBoolType(); |
| 190 | |
| 191 | auto subgroupId = emitCommonSystemValueLoad(GcnSystemValue::SubgroupID, GcnRegMask::select(0)); |
| 192 | // float modulo should be faster than integer modulo |
| 193 | auto subFId = m_module.opConvertUtoF(ftypeId, subgroupId.id); |
| 194 | auto isEven = m_module.opFOrdLessThan(btypeId, subFId, m_module.constf32(1.0)); |
| 195 | |
| 196 | uint32_t labelEven = m_module.allocateId(); |
| 197 | uint32_t labelOdd = m_module.allocateId(); |
| 198 | uint32_t labelMerge = m_module.allocateId(); |
| 199 | |
| 200 | m_module.opSelectionMerge(labelMerge, spv::SelectionControlMaskNone); |
| 201 | m_module.opBranchConditional(isEven, labelEven, labelOdd); |
| 202 | m_module.opLabel(labelEven); |
| 203 | |
| 204 | auto execLo = m_state.exec.emitLoad(GcnRegMask::select(0)); |
| 205 | |
| 206 | m_module.opBranch(labelMerge); |
| 207 | m_module.opLabel(labelOdd); |
| 208 | |
| 209 | auto execHi = m_state.exec.emitLoad(GcnRegMask::select(1)); |
| 210 | |
| 211 | m_module.opBranch(labelMerge); |
| 212 | m_module.opLabel(labelMerge); |
| 213 | |
| 214 | // Merge the result with a phi function |
| 215 | const std::array<SpirvPhiLabel, 2> phiLabels = { { |
| 216 | { execLo.low.id, labelEven }, |
| 217 | { execHi.low.id, labelOdd }, |
| 218 | } }; |
| 219 | |
| 220 | uint32_t exec = m_module.opPhi( |
| 221 | utypeId, phiLabels.size(), phiLabels.data()); |
| 222 | auto mask = emitCommonSystemValueLoad( |
| 223 | GcnSystemValue::SubgroupEqMask, GcnRegMask::select(0)); |
| 224 | |
| 225 | auto value = m_module.opBitwiseAnd(utypeId, exec, mask.id); |
| 226 | uint32_t result = m_module.opINotEqual(btypeId, value, m_module.constu32(0)); |
| 227 | return result; |
| 228 | } |
| 229 |
nothing calls this directly
no test coverage detected