shader: share emitter helpers

This commit is contained in:
nmzik
2026-09-08 13:09:56 +04:00
parent de3e86791c
commit 2b3993a595
9 changed files with 50 additions and 95 deletions
@@ -332,7 +332,7 @@ std::vector<uint32_t> EmitProgram(const IR::Program& program,
AllocateInputVariables(state); AllocateInputVariables(state);
AllocateOutputVariables(state); AllocateOutputVariables(state);
DefineModule(state); DefineModule(state);
EmitProgram(state, program); EmitProgram(state);
state.builder.AddEntryPoint(ExecutionModelForStage(state.stage), state.main_func, "main", state.builder.AddEntryPoint(ExecutionModelForStage(state.stage), state.main_func, "main",
state.interface_variables); state.interface_variables);
@@ -184,7 +184,7 @@ uint32_t EmitVertexParameterComponentU32(EmitterState& state, const InputBinding
if (count == 1u) { if (count == 1u) {
state.builder.AddFunction({OpLoad, scalar_type, raw, input.variable_id}); state.builder.AddFunction({OpLoad, scalar_type, raw, input.variable_id});
} else { } else {
const auto pointer_type = VertexParameterScalarPointerType(state, kind); const auto pointer_type = TypePointer(state, StorageClassInput, scalar_type);
const auto pointer = state.builder.AllocateId(); const auto pointer = state.builder.AllocateId();
state.builder.AddFunction({OpAccessChain, pointer_type, pointer, input.variable_id, state.builder.AddFunction({OpAccessChain, pointer_type, pointer, input.variable_id,
ConstantU32(state, component)}); ConstantU32(state, component)});
@@ -768,8 +768,8 @@ bool EmitValueImage(ValueEmitContext& ctx, const IR::Inst& inst) {
return true; return true;
} }
const auto* handle = image_arg.ResolveInstruction(); const auto* handle = image_arg.ResolveInstruction();
const auto* source = image.source < ctx.program.descriptor_sources.size() const auto* source = image.source < state.program.descriptor_sources.size()
? &ctx.program.descriptor_sources[image.source] ? &state.program.descriptor_sources[image.source]
: nullptr; : nullptr;
if (handle == nullptr || source == nullptr || !source->indirect_image.has_value() || if (handle == nullptr || source == nullptr || !source->indirect_image.has_value() ||
source->indirect_image->key_arg >= handle->NumArgs()) { source->indirect_image->key_arg >= handle->NumArgs()) {
@@ -385,6 +385,7 @@ struct EmitterState {
uint32_t mesh_cull = 0; uint32_t mesh_cull = 0;
uint32_t entry_label = 0; uint32_t entry_label = 0;
uint32_t current_label = 0; uint32_t current_label = 0;
const IR::Block* current_block = nullptr;
uint32_t pixel_valid_mask_variable = 0; uint32_t pixel_valid_mask_variable = 0;
uint32_t subgroup_local_invocation_id_variable = 0; uint32_t subgroup_local_invocation_id_variable = 0;
uint32_t per_vertex_variable = 0; uint32_t per_vertex_variable = 0;
@@ -437,8 +438,7 @@ inline void EmitLabel(EmitterState& state, uint32_t label) {
} }
struct ValueEmitContext { struct ValueEmitContext {
ValueEmitContext(EmitterState& state_, const IR::Program& program_) explicit ValueEmitContext(EmitterState& state_): state(state_) {}
: state(state_), program(program_) {}
uint32_t Def(IR::Value value); uint32_t Def(IR::Value value);
uint32_t Arg(const IR::Inst& inst, size_t index); uint32_t Arg(const IR::Inst& inst, size_t index);
@@ -460,11 +460,9 @@ struct ValueEmitContext {
[[noreturn]] void Fail(const IR::Inst& inst, const char* reason) const; [[noreturn]] void Fail(const IR::Inst& inst, const char* reason) const;
EmitterState& state; EmitterState& state;
const IR::Program& program;
std::unordered_map<const IR::Inst*, uint32_t> definitions; std::unordered_map<const IR::Inst*, uint32_t> definitions;
const std::unordered_map<const IR::Inst*, uint32_t>* dispatcher_spills = nullptr; 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; std::unordered_map<const IR::Inst*, std::pair<uint32_t, uint32_t>> dispatcher_block_loads;
const IR::Block* current_block = nullptr;
uint32_t scratch_u32_variable = 0; uint32_t scratch_u32_variable = 0;
ValueEmitContext* other_half = nullptr; ValueEmitContext* other_half = nullptr;
uint32_t half = 0; uint32_t half = 0;
@@ -507,8 +505,6 @@ uint32_t VertexParameterComponentCount(const InputBinding& input);
uint32_t VertexParameterScalarType(EmitterState& state, VertexInputScalarKind kind); uint32_t VertexParameterScalarType(EmitterState& state, VertexInputScalarKind kind);
uint32_t VertexParameterScalarPointerType(EmitterState& state, VertexInputScalarKind kind);
uint32_t VertexParameterInputPointerType(EmitterState& state, VertexInputScalarKind kind, uint32_t VertexParameterInputPointerType(EmitterState& state, VertexInputScalarKind kind,
uint32_t components); uint32_t components);
@@ -669,15 +665,8 @@ uint32_t EmitStorageBufferElementPointer(EmitterState& state,
const MemoryResourceAccess& access, uint32_t index, const MemoryResourceAccess& access, uint32_t index,
uint32_t pointer_type); uint32_t pointer_type);
uint32_t EmitTBufferBitcastF32ToU32(EmitterState& state, uint32_t value);
uint32_t EmitTBufferBitcastU32ToF32(EmitterState& state, uint32_t value);
uint32_t EmitTBufferBitcastU32ToI32(EmitterState& state, uint32_t value); uint32_t EmitTBufferBitcastU32ToI32(EmitterState& state, uint32_t value);
uint32_t EmitTBufferCompareU32Constant(EmitterState& state, uint32_t opcode, uint32_t value,
uint32_t constant);
uint32_t EmitTBufferSelectF32(EmitterState& state, uint32_t condition, uint32_t true_value, uint32_t EmitTBufferSelectF32(EmitterState& state, uint32_t condition, uint32_t true_value,
uint32_t false_value); uint32_t false_value);
@@ -764,7 +753,7 @@ bool EmitValueMemory(ValueEmitContext& ctx, const IR::Inst& inst);
bool EmitValueImage(ValueEmitContext& ctx, const IR::Inst& inst); bool EmitValueImage(ValueEmitContext& ctx, const IR::Inst& inst);
void EmitProgram(EmitterState& state, const IR::Program& program); void EmitProgram(EmitterState& state);
void DefineGetBdaPointer(EmitterState& state); void DefineGetBdaPointer(EmitterState& state);
@@ -188,31 +188,12 @@ uint32_t EmitStorageBufferElementPointer(EmitterState& state,
return pointer; return pointer;
} }
uint32_t EmitTBufferBitcastF32ToU32(EmitterState& state, uint32_t value) {
const auto ret = state.builder.AllocateId();
state.builder.AddFunction({OpBitcast, TypeU32(state), ret, value});
return ret;
}
uint32_t EmitTBufferBitcastU32ToF32(EmitterState& state, uint32_t value) {
const auto ret = state.builder.AllocateId();
state.builder.AddFunction({OpBitcast, TypeF32(state), ret, value});
return ret;
}
uint32_t EmitTBufferBitcastU32ToI32(EmitterState& state, uint32_t value) { uint32_t EmitTBufferBitcastU32ToI32(EmitterState& state, uint32_t value) {
const auto ret = state.builder.AllocateId(); const auto ret = state.builder.AllocateId();
state.builder.AddFunction({OpBitcast, TypeI32(state), ret, value}); state.builder.AddFunction({OpBitcast, TypeI32(state), ret, value});
return ret; return ret;
} }
uint32_t EmitTBufferCompareU32Constant(EmitterState& state, uint32_t opcode, uint32_t value,
uint32_t constant) {
const auto ret = state.builder.AllocateId();
state.builder.AddFunction({opcode, TypeBool(state), ret, value, ConstantU32(state, constant)});
return ret;
}
uint32_t EmitTBufferSelectF32(EmitterState& state, uint32_t condition, uint32_t true_value, uint32_t EmitTBufferSelectF32(EmitterState& state, uint32_t condition, uint32_t true_value,
uint32_t false_value) { uint32_t false_value) {
const auto ret = state.builder.AllocateId(); const auto ret = state.builder.AllocateId();
@@ -231,7 +212,7 @@ uint32_t EmitHalfToF32Bits(EmitterState& state, uint32_t raw) {
state.builder.AddFunction( state.builder.AddFunction(
{OpExtInst, TypeF32Vector(state, 2), unpacked, GlslStd450(state), GlslUnpackHalf2x16, raw}); {OpExtInst, TypeF32Vector(state, 2), unpacked, GlslStd450(state), GlslUnpackHalf2x16, raw});
state.builder.AddFunction({OpCompositeExtract, TypeF32(state), value, unpacked, 0}); state.builder.AddFunction({OpCompositeExtract, TypeF32(state), value, unpacked, 0});
return EmitTBufferBitcastF32ToU32(state, value); return EmitBitcastF32ToU32(state, value);
} }
uint32_t EmitUFloatToF32Bits(EmitterState& state, uint32_t raw, uint32_t bits) { uint32_t EmitUFloatToF32Bits(EmitterState& state, uint32_t raw, uint32_t bits) {
@@ -250,11 +231,11 @@ uint32_t EmitUFloatToF32Bits(EmitterState& state, uint32_t raw, uint32_t bits) {
const auto mantissa_bits_32 = const auto mantissa_bits_32 =
EmitBinaryU32(state, OpShiftLeftLogical, mantissa, ConstantU32(state, 23u - mantissa_bits)); EmitBinaryU32(state, OpShiftLeftLogical, mantissa, ConstantU32(state, 23u - mantissa_bits));
const auto normal_bits = EmitBinaryU32(state, OpBitwiseOr, exponent_bits, mantissa_bits_32); const auto normal_bits = EmitBinaryU32(state, OpBitwiseOr, exponent_bits, mantissa_bits_32);
const auto normal = EmitTBufferBitcastU32ToF32(state, normal_bits); const auto normal = EmitBitcastU32ToF32(state, normal_bits);
const auto special_bits = const auto special_bits =
EmitBinaryU32(state, OpBitwiseOr, ConstantU32(state, 0x7f800000u), mantissa_bits_32); EmitBinaryU32(state, OpBitwiseOr, ConstantU32(state, 0x7f800000u), mantissa_bits_32);
const auto special = EmitTBufferBitcastU32ToF32(state, special_bits); const auto special = EmitBitcastU32ToF32(state, special_bits);
const auto mantissa_f32 = state.builder.AllocateId(); const auto mantissa_f32 = state.builder.AllocateId();
const auto subnormal = state.builder.AllocateId(); const auto subnormal = state.builder.AllocateId();
@@ -263,11 +244,11 @@ uint32_t EmitUFloatToF32Bits(EmitterState& state, uint32_t raw, uint32_t bits) {
{OpFMul, TypeF32(state), subnormal, mantissa_f32, {OpFMul, TypeF32(state), subnormal, mantissa_f32,
ConstantF32Value(state, std::ldexp(1.0f, 1 - 15 - static_cast<int>(mantissa_bits)))}); ConstantF32Value(state, std::ldexp(1.0f, 1 - 15 - static_cast<int>(mantissa_bits)))});
const auto zero_exp = EmitTBufferCompareU32Constant(state, OpIEqual, exponent, 0); const auto zero_exp = EmitCompareU32Constant(state, OpIEqual, exponent, 0);
const auto special_exp = EmitTBufferCompareU32Constant(state, OpIEqual, exponent, 31); const auto special_exp = EmitCompareU32Constant(state, OpIEqual, exponent, 31);
const auto finite = EmitTBufferSelectF32(state, zero_exp, subnormal, normal); const auto finite = EmitTBufferSelectF32(state, zero_exp, subnormal, normal);
const auto result = EmitTBufferSelectF32(state, special_exp, special, finite); const auto result = EmitTBufferSelectF32(state, special_exp, special, finite);
return EmitTBufferBitcastF32ToU32(state, result); return EmitBitcastF32ToU32(state, result);
} }
uint32_t NormalizeFormatComponent(EmitterState& state, const Format::BufferFormatInfo& info, uint32_t NormalizeFormatComponent(EmitterState& state, const Format::BufferFormatInfo& info,
@@ -279,13 +260,13 @@ uint32_t NormalizeFormatComponent(EmitterState& state, const Format::BufferForma
case Format::ComponentType::Uscaled: { case Format::ComponentType::Uscaled: {
const auto value = state.builder.AllocateId(); const auto value = state.builder.AllocateId();
state.builder.AddFunction({OpConvertUToF, TypeF32(state), value, raw}); state.builder.AddFunction({OpConvertUToF, TypeF32(state), value, raw});
return EmitTBufferBitcastF32ToU32(state, value); return EmitBitcastF32ToU32(state, value);
} }
case Format::ComponentType::Sscaled: { case Format::ComponentType::Sscaled: {
const auto signed_raw = EmitTBufferBitcastU32ToI32(state, raw); const auto signed_raw = EmitTBufferBitcastU32ToI32(state, raw);
const auto value = state.builder.AllocateId(); const auto value = state.builder.AllocateId();
state.builder.AddFunction({OpConvertSToF, TypeF32(state), value, signed_raw}); state.builder.AddFunction({OpConvertSToF, TypeF32(state), value, signed_raw});
return EmitTBufferBitcastF32ToU32(state, value); return EmitBitcastF32ToU32(state, value);
} }
case Format::ComponentType::Unorm: { case Format::ComponentType::Unorm: {
const auto value = state.builder.AllocateId(); const auto value = state.builder.AllocateId();
@@ -294,7 +275,7 @@ uint32_t NormalizeFormatComponent(EmitterState& state, const Format::BufferForma
state.builder.AddFunction({OpConvertUToF, TypeF32(state), value, raw}); state.builder.AddFunction({OpConvertUToF, TypeF32(state), value, raw});
state.builder.AddFunction( state.builder.AddFunction(
{OpFDiv, TypeF32(state), normalized, value, ConstantF32Value(state, max_value)}); {OpFDiv, TypeF32(state), normalized, value, ConstantF32Value(state, max_value)});
return EmitTBufferBitcastF32ToU32(state, normalized); return EmitBitcastF32ToU32(state, normalized);
} }
case Format::ComponentType::Snorm: { case Format::ComponentType::Snorm: {
const auto signed_raw = EmitTBufferBitcastU32ToI32(state, raw); const auto signed_raw = EmitTBufferBitcastU32ToI32(state, raw);
@@ -307,7 +288,7 @@ uint32_t NormalizeFormatComponent(EmitterState& state, const Format::BufferForma
{OpFDiv, TypeF32(state), normalized, value, ConstantF32Value(state, max_value)}); {OpFDiv, TypeF32(state), normalized, value, ConstantF32Value(state, max_value)});
state.builder.AddFunction({OpExtInst, TypeF32(state), clamped, GlslStd450(state), state.builder.AddFunction({OpExtInst, TypeF32(state), clamped, GlslStd450(state),
GlslFMax, normalized, ConstantF32Value(state, -1.0f)}); GlslFMax, normalized, ConstantF32Value(state, -1.0f)});
return EmitTBufferBitcastF32ToU32(state, clamped); return EmitBitcastF32ToU32(state, clamped);
} }
case Format::ComponentType::Float: case Format::ComponentType::Float:
if (bits == 32u) { if (bits == 32u) {
@@ -349,17 +349,6 @@ uint32_t VertexParameterScalarType(EmitterState& state, VertexInputScalarKind ki
} }
} }
uint32_t VertexParameterScalarPointerType(EmitterState& state, VertexInputScalarKind kind) {
switch (kind) {
case VertexInputScalarKind::Sint:
return TypePointer(state, StorageClassInput, TypeI32(state));
case VertexInputScalarKind::Uint:
return TypePointer(state, StorageClassInput, TypeU32(state));
case VertexInputScalarKind::Float:
default: return TypePointer(state, StorageClassInput, TypeF32(state));
}
}
uint32_t VertexParameterInputPointerType(EmitterState& state, VertexInputScalarKind kind, uint32_t VertexParameterInputPointerType(EmitterState& state, VertexInputScalarKind kind,
uint32_t components) { uint32_t components) {
switch (kind) { switch (kind) {
@@ -118,18 +118,19 @@ uint32_t BranchCondition(ValueEmitContext& ctx, const IR::BlockInfo& info) {
void EmitStructuredTerminator(ValueEmitContext& ctx, const IR::Block* block, void EmitStructuredTerminator(ValueEmitContext& ctx, const IR::Block* block,
const IR::BlockInfo& info) { const IR::BlockInfo& info) {
const auto& program = ctx.state.program;
const auto& term = info.terminator; const auto& term = info.terminator;
const auto emit_merge = [&]() { const auto emit_merge = [&]() {
if (term.loop_header) { if (term.loop_header) {
const auto* merge = TargetBlock(ctx.program, term.merge_block); const auto* merge = TargetBlock(program, term.merge_block);
const auto* cont = TargetBlock(ctx.program, term.continue_block); const auto* cont = TargetBlock(program, term.continue_block);
if (merge != nullptr && cont != nullptr) { if (merge != nullptr && cont != nullptr) {
ctx.state.builder.AddFunction( ctx.state.builder.AddFunction(
{OpLoopMerge, ctx.Label(merge), ctx.Label(cont), LoopControlNone}); {OpLoopMerge, ctx.Label(merge), ctx.Label(cont), LoopControlNone});
} }
} else if (term.kind == CFG::TerminatorKind::ConditionalBranch && } else if (term.kind == CFG::TerminatorKind::ConditionalBranch &&
term.merge_block != UINT32_MAX) { term.merge_block != UINT32_MAX) {
if (const auto* merge = TargetBlock(ctx.program, term.merge_block); merge != nullptr) { if (const auto* merge = TargetBlock(program, term.merge_block); merge != nullptr) {
ctx.state.builder.AddFunction( ctx.state.builder.AddFunction(
{OpSelectionMerge, ctx.Label(merge), SelectionControlNone}); {OpSelectionMerge, ctx.Label(merge), SelectionControlNone});
} }
@@ -138,7 +139,7 @@ void EmitStructuredTerminator(ValueEmitContext& ctx, const IR::Block* block,
switch (term.kind) { switch (term.kind) {
case CFG::TerminatorKind::Branch: { case CFG::TerminatorKind::Branch: {
const auto* target = TargetBlock(ctx.program, term.true_block); const auto* target = TargetBlock(program, term.true_block);
if (target == nullptr) { if (target == nullptr) {
EmitReturn(ctx); EmitReturn(ctx);
return; return;
@@ -148,8 +149,8 @@ void EmitStructuredTerminator(ValueEmitContext& ctx, const IR::Block* block,
return; return;
} }
case CFG::TerminatorKind::ConditionalBranch: { case CFG::TerminatorKind::ConditionalBranch: {
const auto* true_block = TargetBlock(ctx.program, term.true_block); const auto* true_block = TargetBlock(program, term.true_block);
const auto* false_block = TargetBlock(ctx.program, term.false_block); const auto* false_block = TargetBlock(program, term.false_block);
if (true_block == nullptr || false_block == nullptr || info.condition.IsEmpty()) { if (true_block == nullptr || false_block == nullptr || info.condition.IsEmpty()) {
EmitReturn(ctx); EmitReturn(ctx);
return; return;
@@ -166,7 +167,7 @@ void EmitStructuredTerminator(ValueEmitContext& ctx, const IR::Block* block,
void EmitDispatcherTarget(ValueEmitContext& ctx, const DispatcherFunctionState& dispatcher, void EmitDispatcherTarget(ValueEmitContext& ctx, const DispatcherFunctionState& dispatcher,
const IR::Block* from, uint32_t target) { const IR::Block* from, uint32_t target) {
const auto* block = TargetBlock(ctx.program, target); const auto* block = TargetBlock(ctx.state.program, target);
if (block != nullptr) { if (block != nullptr) {
StoreDispatcherPhiEdge(ctx, dispatcher, from, block); StoreDispatcherPhiEdge(ctx, dispatcher, from, block);
if (ctx.other_half != nullptr) { if (ctx.other_half != nullptr) {
@@ -272,10 +273,7 @@ void EmitDispatcherInstruction(ValueEmitContext& ctx, const DispatcherFunctionSt
template <typename EmitInstruction> template <typename EmitInstruction>
void EmitBlock(ValueEmitContext& ctx, const IR::Block* block, EmitInstruction&& emit_instruction) { void EmitBlock(ValueEmitContext& ctx, const IR::Block* block, EmitInstruction&& emit_instruction) {
ctx.current_block = block; ctx.state.current_block = block;
if (ctx.other_half != nullptr) {
ctx.other_half->current_block = block;
}
EmitLabel(ctx.state, ctx.Label(block)); EmitLabel(ctx.state, ctx.Label(block));
bool emitted_non_phi = false; bool emitted_non_phi = false;
for (const auto& inst: *block) { for (const auto& inst: *block) {
@@ -288,7 +286,6 @@ void EmitBlock(ValueEmitContext& ctx, const IR::Block* block, EmitInstruction&&
} }
for (uint32_t half = 0; half < ctx.state.lane_count; half++) { for (uint32_t half = 0; half < ctx.state.lane_count; half++) {
auto& lane = half == 0 ? ctx : *ctx.other_half; auto& lane = half == 0 ? ctx : *ctx.other_half;
lane.current_block = block;
ctx.state.lane_half = half; ctx.state.lane_half = half;
if (half == 0 || (inst.GetOpcode() != IR::ValueOpcode::Barrier && if (half == 0 || (inst.GetOpcode() != IR::ValueOpcode::Barrier &&
inst.GetOpcode() != IR::ValueOpcode::MeshAllocate)) { inst.GetOpcode() != IR::ValueOpcode::MeshAllocate)) {
@@ -315,28 +312,29 @@ void PatchStructuredPhis(ValueEmitContext& ctx, StructuredFunctionState& structu
} }
void EmitStructuredFunction(ValueEmitContext& ctx) { void EmitStructuredFunction(ValueEmitContext& ctx) {
const auto& program = ctx.state.program;
StructuredFunctionState structured; StructuredFunctionState structured;
ctx.state.builder.AddFunction({OpBranch, ctx.Label(ctx.program.blocks.front())}); ctx.state.builder.AddFunction({OpBranch, ctx.Label(program.blocks.front())});
for (size_t index = 0; index < ctx.program.blocks.size(); index++) { for (size_t index = 0; index < program.blocks.size(); index++) {
const auto* block = ctx.program.blocks[index]; const auto* block = program.blocks[index];
EmitBlock(ctx, block, [&](ValueEmitContext& lane, const IR::Inst& inst) { EmitBlock(ctx, block, [&](ValueEmitContext& lane, const IR::Inst& inst) {
EmitStructuredInstruction(lane, structured, inst); EmitStructuredInstruction(lane, structured, inst);
}); });
structured.block_exit_labels.emplace(block, ctx.state.current_label); structured.block_exit_labels.emplace(block, ctx.state.current_label);
EmitStructuredTerminator(ctx, block, ctx.program.block_info[index]); EmitStructuredTerminator(ctx, block, program.block_info[index]);
} }
PatchStructuredPhis(ctx, structured); PatchStructuredPhis(ctx, structured);
} }
void EmitDispatcherFunction(ValueEmitContext& ctx, const DispatcherFunctionState& dispatcher) { void EmitDispatcherFunction(ValueEmitContext& ctx, const DispatcherFunctionState& dispatcher) {
auto& state = ctx.state; auto& state = ctx.state;
const auto* entry = ctx.program.blocks.front(); const auto* entry = state.program.blocks.front();
state.builder.AddFunction({OpBranch, ctx.Label(entry)}); state.builder.AddFunction({OpBranch, ctx.Label(entry)});
EmitBlock(ctx, entry, [&](ValueEmitContext& lane, const IR::Inst& inst) { EmitBlock(ctx, entry, [&](ValueEmitContext& lane, const IR::Inst& inst) {
EmitDispatcherInstruction(lane, dispatcher, inst); EmitDispatcherInstruction(lane, dispatcher, inst);
}); });
const auto initial_pc = const auto initial_pc =
EmitDispatcherNextPc(ctx, dispatcher, entry, ctx.program.block_info.front()); EmitDispatcherNextPc(ctx, dispatcher, entry, state.program.block_info.front());
const auto initial_parent = state.current_label; const auto initial_parent = state.current_label;
state.builder.AddFunction({OpBranch, dispatcher.header_label}); state.builder.AddFunction({OpBranch, dispatcher.header_label});
@@ -357,21 +355,21 @@ void EmitDispatcherFunction(ValueEmitContext& ctx, const DispatcherFunctionState
state.builder.AddFunction( state.builder.AddFunction(
{OpSelectionMerge, dispatcher.after_switch_label, SelectionControlNone}); {OpSelectionMerge, dispatcher.after_switch_label, SelectionControlNone});
std::vector<uint32_t> words {OpSwitch, pc, dispatcher.after_switch_label}; std::vector<uint32_t> words {OpSwitch, pc, dispatcher.after_switch_label};
for (size_t index = 1; index < ctx.program.blocks.size(); index++) { for (size_t index = 1; index < state.program.blocks.size(); index++) {
words.push_back(ctx.program.block_info[index].id); words.push_back(state.program.block_info[index].id);
words.push_back(ctx.Label(ctx.program.blocks[index])); words.push_back(ctx.Label(state.program.blocks[index]));
} }
state.builder.AddFunction(words); state.builder.AddFunction(words);
std::vector<uint32_t> next_pc_words {OpPhi, TypeU32(state), next_pc, std::vector<uint32_t> next_pc_words {OpPhi, TypeU32(state), next_pc,
ConstantU32(state, UINT32_MAX), dispatcher.select_label}; ConstantU32(state, UINT32_MAX), dispatcher.select_label};
for (size_t index = 1; index < ctx.program.blocks.size(); index++) { for (size_t index = 1; index < state.program.blocks.size(); index++) {
EmitBlock(ctx, ctx.program.blocks[index], EmitBlock(ctx, state.program.blocks[index],
[&](ValueEmitContext& lane, const IR::Inst& inst) { [&](ValueEmitContext& lane, const IR::Inst& inst) {
EmitDispatcherInstruction(lane, dispatcher, inst); EmitDispatcherInstruction(lane, dispatcher, inst);
}); });
const auto selected = EmitDispatcherNextPc(ctx, dispatcher, ctx.program.blocks[index], const auto selected = EmitDispatcherNextPc(ctx, dispatcher, state.program.blocks[index],
ctx.program.block_info[index]); state.program.block_info[index]);
next_pc_words.push_back(selected); next_pc_words.push_back(selected);
next_pc_words.push_back(state.current_label); next_pc_words.push_back(state.current_label);
state.builder.AddFunction({OpBranch, dispatcher.after_switch_label}); state.builder.AddFunction({OpBranch, dispatcher.after_switch_label});
@@ -423,8 +421,8 @@ uint32_t ValueEmitContext::Def(IR::Value value) {
if (inst == nullptr) { if (inst == nullptr) {
Fail("direct SPIR-V emitter received a non-value argument"); Fail("direct SPIR-V emitter received a non-value argument");
} }
if (dispatcher_spills != nullptr && current_block != nullptr && if (dispatcher_spills != nullptr && state.current_block != nullptr &&
inst->Parent() != current_block) { inst->Parent() != state.current_block) {
if (const auto found = dispatcher_spills->find(inst); found != dispatcher_spills->end()) { if (const auto found = dispatcher_spills->find(inst); found != dispatcher_spills->end()) {
if (const auto loaded = dispatcher_block_loads.find(inst); if (const auto loaded = dispatcher_block_loads.find(inst);
loaded != dispatcher_block_loads.end() && loaded != dispatcher_block_loads.end() &&
@@ -571,11 +569,11 @@ const IR::Inst* ValueEmitContext::ImageAddress(IR::Value value) {
} }
const IR::MemoryInfo& ValueEmitContext::Memory(const IR::Inst& inst) const { const IR::MemoryInfo& ValueEmitContext::Memory(const IR::Inst& inst) const {
return program.memory_info.at(inst.Flags<IR::MemoryFlags>().index); return state.program.memory_info.at(inst.Flags<IR::MemoryFlags>().index);
} }
const IR::ExportInfo& ValueEmitContext::Export(const IR::Inst& inst) const { const IR::ExportInfo& ValueEmitContext::Export(const IR::Inst& inst) const {
return program.export_info.at(inst.Flags<IR::ExportFlags>().index); return state.program.export_info.at(inst.Flags<IR::ExportFlags>().index);
} }
uint32_t ValueEmitContext::Label(const IR::Block* block) const { uint32_t ValueEmitContext::Label(const IR::Block* block) const {
@@ -584,20 +582,21 @@ uint32_t ValueEmitContext::Label(const IR::Block* block) const {
[[noreturn]] void ValueEmitContext::Fail(const char* reason) const { [[noreturn]] void ValueEmitContext::Fail(const char* reason) const {
EXIT("SPIR-V emission failed: hash=0x%016" PRIx64 " stage=%u reason=%s\n", EXIT("SPIR-V emission failed: hash=0x%016" PRIx64 " stage=%u reason=%s\n",
program.shader_hash, static_cast<unsigned>(program.stage), reason); state.program.shader_hash, static_cast<unsigned>(state.program.stage), reason);
std::abort(); std::abort();
} }
[[noreturn]] void ValueEmitContext::Fail(const IR::Inst& inst, const char* reason) const { [[noreturn]] void ValueEmitContext::Fail(const IR::Inst& inst, const char* reason) const {
EXIT("SPIR-V emission failed: hash=0x%016" PRIx64 " stage=%u opcode=%s reason=%s\n", EXIT("SPIR-V emission failed: hash=0x%016" PRIx64 " stage=%u opcode=%s reason=%s\n",
program.shader_hash, static_cast<unsigned>(program.stage), state.program.shader_hash, static_cast<unsigned>(state.program.stage),
IR::ValueOpcodeName(inst.GetOpcode()), reason); IR::ValueOpcodeName(inst.GetOpcode()), reason);
std::abort(); std::abort();
} }
void EmitProgram(EmitterState& state, const IR::Program& program) { void EmitProgram(EmitterState& state) {
ValueEmitContext ctx(state, program); const auto& program = state.program;
ValueEmitContext high(state, program); ValueEmitContext ctx(state);
ValueEmitContext high(state);
if (state.lane_count == 2) { if (state.lane_count == 2) {
ctx.other_half = &high; ctx.other_half = &high;
high.other_half = &ctx; high.other_half = &ctx;
-1
View File
@@ -593,7 +593,6 @@ static void ShaderGetStaticInputInfoPS(
} }
ps_info.ps_pos_x = (active_inputs & 0x00000100u) != 0; ps_info.ps_pos_x = (active_inputs & 0x00000100u) != 0;
ps_info.ps_pos_y = (active_inputs & 0x00000200u) != 0; ps_info.ps_pos_y = (active_inputs & 0x00000200u) != 0;
ps_info.ps_pos_xy = ps_info.ps_pos_x && ps_info.ps_pos_y;
ps_info.ps_pos_z = (active_inputs & 0x00000400u) != 0; ps_info.ps_pos_z = (active_inputs & 0x00000400u) != 0;
ps_info.ps_pos_w = (active_inputs & 0x00000800u) != 0; ps_info.ps_pos_w = (active_inputs & 0x00000800u) != 0;
ps_info.ps_front_face = (active_inputs & 0x00001000u) != 0; ps_info.ps_front_face = (active_inputs & 0x00001000u) != 0;
-2
View File
@@ -102,7 +102,6 @@ struct ShaderVertexInputInfo {
ShaderVertexInputBuffer buffers[RES_MAX]; ShaderVertexInputBuffer buffers[RES_MAX];
ShaderStageRuntime stage; ShaderStageRuntime stage;
int resources_num = 0; int resources_num = 0;
int fetch_shader_reg = 0;
int fetch_attrib_reg = 0; int fetch_attrib_reg = 0;
int fetch_buffer_reg = 0; int fetch_buffer_reg = 0;
int buffers_num = 0; int buffers_num = 0;
@@ -135,7 +134,6 @@ struct ShaderPixelInputInfo {
uint32_t scratch_size_dwords = 0; uint32_t scratch_size_dwords = 0;
bool ps_pos_x = false; bool ps_pos_x = false;
bool ps_pos_y = false; bool ps_pos_y = false;
bool ps_pos_xy = false;
bool ps_pos_z = false; bool ps_pos_z = false;
bool ps_pos_w = false; bool ps_pos_w = false;
bool ps_front_face = false; bool ps_front_face = false;