shader: share control flow labels

This commit is contained in:
nmzik
2026-09-08 12:44:42 +04:00
parent cb4c8f3878
commit cd62693792
6 changed files with 7 additions and 50 deletions
@@ -319,8 +319,7 @@ std::vector<uint32_t> EmitProgram(const IR::Program& program,
ValidateNativeProgram(program);
IR::ValidateProgram(program, true);
EmitterState state(program, input_info);
state.stage = program.stage;
state.wave_size = program.wave_size;
state.stage = program.stage;
const auto* workgroup = ShaderWorkgroupInput(program.stage, input_info);
state.lane_count =
workgroup != nullptr && program.wave_size == 64u && workgroup->host_subgroup_size == 32u
@@ -6,13 +6,6 @@
namespace Libs::Graphics::ShaderRecompiler::Spirv::Emitter {
uint32_t PixelParameterMappedLocation(const EmitterState& state, uint32_t attr) {
if (state.stage != ShaderType::Pixel) {
return attr;
}
return ShaderPixelParameterMappedLocation(*state.input_info.pixel, attr);
}
uint32_t PixelParameterLocation(const EmitterState& state, uint32_t attr) {
std::array<uint32_t, 32> active_inputs {};
uint32_t active_count = 0;
@@ -210,7 +210,7 @@ uint32_t EmitBallotLaneActiveBool(EmitterState& state, uint32_t active_ballot, u
const auto low = state.builder.AllocateId();
state.builder.AddFunction({OpCompositeExtract, TypeU32(state), low, active_ballot, 0});
uint32_t mask = low;
if (state.wave_size == 64u) {
if (state.program.wave_size == 64u) {
const auto high = state.builder.AllocateId();
const auto in_high = state.builder.AllocateId();
const auto selected = state.builder.AllocateId();
@@ -235,7 +235,7 @@ uint32_t EmitBallotLaneActiveBool(EmitterState& state, uint32_t active_ballot, u
state.builder.AddFunction({OpBitwiseAnd, TypeU32(state), hit, mask, bit});
state.builder.AddFunction({OpINotEqual, TypeBool(state), active, hit, ConstantU32(state, 0)});
state.builder.AddFunction(
{OpULessThan, TypeBool(state), in_range, lane, ConstantU32(state, state.wave_size)});
{OpULessThan, TypeBool(state), in_range, lane, ConstantU32(state, state.program.wave_size)});
state.builder.AddFunction({OpLogicalAnd, TypeBool(state), ret, active, in_range});
return ret;
}
@@ -360,7 +360,6 @@ struct EmitterState {
ShaderStageInputInfo input_info;
const IR::SpirvRequirements& requirements;
ShaderType stage = ShaderType::Unknown;
uint32_t wave_size = 64;
uint32_t lane_count = 1;
uint32_t lane_half = 0;
uint32_t storage_buffer_variable = 0;
@@ -401,6 +400,7 @@ struct EmitterState {
std::vector<InputBinding> inputs;
std::vector<OutputBinding> outputs;
std::vector<uint32_t> interface_variables;
std::unordered_map<const IR::Block*, uint32_t> labels;
};
uint32_t TypeVoid(EmitterState& state);
@@ -462,7 +462,6 @@ struct ValueEmitContext {
EmitterState& state;
const IR::Program& program;
std::unordered_map<const IR::Inst*, uint32_t> definitions;
std::unordered_map<const IR::Block*, uint32_t> labels;
const std::unordered_map<const IR::Inst*, uint32_t>* dispatcher_spills = nullptr;
std::unordered_map<const IR::Inst*, std::pair<uint32_t, uint32_t>> dispatcher_block_loads;
const IR::Block* current_block = nullptr;
@@ -496,8 +495,6 @@ struct F32Class {
uint32_t zero = 0;
};
uint32_t PixelParameterMappedLocation(const EmitterState& state, uint32_t attr);
uint32_t PixelParameterLocation(const EmitterState& state, uint32_t attr);
bool PixelParameterIsFlat(const EmitterState& state, uint32_t attr);
@@ -512,9 +509,6 @@ uint32_t VertexParameterScalarType(EmitterState& state, VertexInputScalarKind ki
uint32_t VertexParameterScalarPointerType(EmitterState& state, VertexInputScalarKind kind);
uint32_t VertexParameterVectorOrScalarType(EmitterState& state, VertexInputScalarKind kind,
uint32_t components);
uint32_t VertexParameterInputPointerType(EmitterState& state, VertexInputScalarKind kind,
uint32_t components);
@@ -360,34 +360,6 @@ uint32_t VertexParameterScalarPointerType(EmitterState& state, VertexInputScalar
}
}
uint32_t VertexParameterVectorOrScalarType(EmitterState& state, VertexInputScalarKind kind,
uint32_t components) {
switch (kind) {
case VertexInputScalarKind::Sint:
switch (components) {
case 1: return TypeI32(state);
case 2: return TypeI32Vector(state, 2);
case 3: return TypeI32Vector(state, 3);
default: return TypeI32Vector(state, 4);
}
case VertexInputScalarKind::Uint:
switch (components) {
case 1: return TypeU32(state);
case 2: return TypeU32Vector(state, 2);
case 3: return TypeU32Vector(state, 3);
default: return TypeU32Vector(state, 4);
}
case VertexInputScalarKind::Float:
default:
switch (components) {
case 1: return TypeF32(state);
case 2: return TypeF32Vector(state, 2);
case 3: return TypeF32Vector(state, 3);
default: return TypeF32Vector(state, 4);
}
}
}
uint32_t VertexParameterInputPointerType(EmitterState& state, VertexInputScalarKind kind,
uint32_t components) {
switch (kind) {
@@ -239,7 +239,7 @@ void EmitStructuredInstruction(ValueEmitContext& ctx, StructuredFunctionState& s
}
for (size_t index = 0; index < inst.NumArgs(); index++) {
const auto* predecessor = inst.PhiBlock(index);
if (predecessor == nullptr || !ctx.labels.contains(predecessor)) {
if (predecessor == nullptr || !ctx.state.labels.contains(predecessor)) {
ctx.Fail(inst, "has a predecessor outside the structured function");
}
}
@@ -579,7 +579,7 @@ const IR::ExportInfo& ValueEmitContext::Export(const IR::Inst& inst) const {
}
uint32_t ValueEmitContext::Label(const IR::Block* block) const {
return labels.at(block);
return state.labels.at(block);
}
[[noreturn]] void ValueEmitContext::Fail(const char* reason) const {
@@ -610,8 +610,7 @@ void EmitProgram(EmitterState& state, const IR::Program& program) {
}
for (const auto* block: program.blocks) {
const auto label = state.builder.AllocateId();
ctx.labels.emplace(block, label);
high.labels.emplace(block, label);
state.labels.emplace(block, label);
}
if (state.program.dispatcher_fallback) {
auto& dispatch = dispatcher.emplace();