Reuse whole-wave ballot and first-lane SPIR-V results

This commit is contained in:
nmzik
2026-10-01 22:04:56 +04:00
parent 64eea6b32d
commit f29bd0fe35
2 changed files with 29 additions and 0 deletions
@@ -243,6 +243,12 @@ void Invoke(Return (*emit)(Context&, Args...), ValueEmitContext& ctx, const IR::
}
void EmitDirectInstruction(ValueEmitContext& ctx, const IR::Inst& inst) {
if (ctx.half != 0 && (inst.GetOpcode() == IR::ValueOpcode::Ballot ||
inst.GetOpcode() == IR::ValueOpcode::ReadFirstLane)) {
// Both operations already combine both emulated halves into one whole-wave result.
ctx.Define(inst, ctx.other_half->Result(inst));
return;
}
switch (inst.GetOpcode()) {
#define VALUE_OPCODE(name, ...) \
case IR::ValueOpcode::name: return Invoke(Emit##name, ctx, inst);
+23
View File
@@ -28392,6 +28392,27 @@ TestCase Wave64CrossHalfLaneAndLds() {
return test;
}
void CheckWave64WholeWaveResults() {
const auto test = Wave64CrossHalfLaneAndLds();
const auto native = CompileCase(test, 64);
const auto emulated = CompileCase(test, 32);
spvtools::SpirvTools tools(SPV_ENV_VULKAN_1_2);
std::string native_text, emulated_text;
Require(test.name, "whole-wave disassembly",
tools.Disassemble(native.spirv, &native_text) &&
tools.Disassemble(emulated.spirv, &emulated_text),
"failed to disassemble whole-wave operations");
const auto ballots = CountText(native_text, "OpGroupNonUniformBallot ");
Require(test.name, "whole-wave ballot reuse",
ballots != 0 &&
CountText(emulated_text, "OpGroupNonUniformBallot ") == ballots * 2,
"emulated halves repeated a whole-wave ballot");
// READLANE still emits two shuffles per half; READFIRSTLANE needs one shared pair.
Require(test.name, "whole-wave first-lane reuse",
CountText(emulated_text, "OpGroupNonUniformShuffle ") == 6,
"emulated halves repeated the first-active-lane broadcast");
}
TestCase Wave64RawMasksAndScalarBranch() {
using O = ShaderOpcode;
std::vector<u32> code;
@@ -36487,6 +36508,7 @@ int main(int argc, char **argv) {
return 0;
}
if (argc == 2 && std::strcmp(argv[1], "--wave64-only") == 0) {
CheckWave64WholeWaveResults();
VulkanHarness vulkan;
RunCase(&vulkan, Wave32VccMasksPreserveOtherHalf());
RunCase(&vulkan, DsBpermuteWave64UsesIndependentHalves());
@@ -37011,6 +37033,7 @@ int main(int argc, char **argv) {
CheckPixelParameterAliases();
CheckRectListShaders();
CheckIndirectImageKeySwitch();
CheckWave64WholeWaveResults();
CheckPs5GameExampleImageClearRuntimeShape();
vulkan.CheckSchedulerTimeline();
vulkan.CheckHostImageAllocation();