MCPcopy Create free account
hub / github.com/Inori/GPCS4 / emitComputeDivergence

Method emitComputeDivergence

GPCS4/Graphics/Gcn/GcnCompilerFlowControl.cpp:172–228  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

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

Callers

nothing calls this directly

Calls 15

defBoolTypeMethod · 0.80
opConvertUtoFMethod · 0.80
opFOrdLessThanMethod · 0.80
constf32Method · 0.80
allocateIdMethod · 0.80
opSelectionMergeMethod · 0.80
opBranchConditionalMethod · 0.80
opLabelMethod · 0.80
emitLoadMethod · 0.80
opBranchMethod · 0.80
opPhiMethod · 0.80
opBitwiseAndMethod · 0.80

Tested by

no test coverage detected