mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 10:56:58 +02:00
refactor(shader): emit SPIR-V declarations on demand
This commit is contained in:
@@ -27,12 +27,12 @@ uint32_t EmitWqmLaneU32(EmitterState& state, uint32_t src) {
|
||||
const auto expanded = state.builder.AllocateId();
|
||||
const auto combined = state.builder.AllocateId();
|
||||
state.builder.AddFunction(
|
||||
{OpBitwiseAnd, state.uint_type, masked, src, ConstantU32(state, mask)});
|
||||
{OpBitwiseAnd, TypeU32(state), masked, src, ConstantU32(state, mask)});
|
||||
state.builder.AddFunction(
|
||||
{OpINotEqual, state.bool_type, non_zero, masked, ConstantU32(state, 0)});
|
||||
state.builder.AddFunction({OpSelect, state.uint_type, expanded, non_zero,
|
||||
{OpINotEqual, TypeBool(state), non_zero, masked, ConstantU32(state, 0)});
|
||||
state.builder.AddFunction({OpSelect, TypeU32(state), expanded, non_zero,
|
||||
ConstantU32(state, mask), ConstantU32(state, 0)});
|
||||
state.builder.AddFunction({OpBitwiseOr, state.uint_type, combined, ret, expanded});
|
||||
state.builder.AddFunction({OpBitwiseOr, TypeU32(state), combined, ret, expanded});
|
||||
ret = combined;
|
||||
}
|
||||
return ret;
|
||||
@@ -40,7 +40,7 @@ uint32_t EmitWqmLaneU32(EmitterState& state, uint32_t src) {
|
||||
|
||||
uint32_t BoolAsU32(ValueEmitContext& ctx, uint32_t value) {
|
||||
const auto result = ctx.state.builder.AllocateId();
|
||||
ctx.state.builder.AddFunction({OpSelect, ctx.state.uint_type, result, value,
|
||||
ctx.state.builder.AddFunction({OpSelect, TypeU32(ctx.state), result, value,
|
||||
ConstantU32(ctx.state, 1), ConstantU32(ctx.state, 0)});
|
||||
return result;
|
||||
}
|
||||
@@ -57,26 +57,27 @@ uint32_t EmitBuiltinU32(ValueEmitContext& ctx, IR::StageInputKind kind, uint32_t
|
||||
if (kind == IR::StageInputKind::FrontFacing) {
|
||||
const auto value = state.builder.AllocateId();
|
||||
const auto bits = state.builder.AllocateId();
|
||||
state.builder.AddFunction({OpLoad, state.bool_type, value, variable});
|
||||
state.builder.AddFunction({OpLoad, TypeBool(state), value, variable});
|
||||
state.builder.AddFunction(
|
||||
{OpSelect, state.uint_type, bits, value, ConstantU32(state, 1), ConstantU32(state, 0)});
|
||||
{OpSelect, TypeU32(state), bits, value, ConstantU32(state, 1), ConstantU32(state, 0)});
|
||||
return bits;
|
||||
}
|
||||
if (kind == IR::StageInputKind::VertexIndex || kind == IR::StageInputKind::InstanceIndex) {
|
||||
const auto value = state.builder.AllocateId();
|
||||
const auto bits = state.builder.AllocateId();
|
||||
state.builder.AddFunction({OpLoad, state.int_type, value, variable});
|
||||
state.builder.AddFunction({OpBitcast, state.uint_type, bits, value});
|
||||
state.builder.AddFunction({OpLoad, TypeI32(state), value, variable});
|
||||
state.builder.AddFunction({OpBitcast, TypeU32(state), bits, value});
|
||||
return bits;
|
||||
}
|
||||
if (kind == IR::StageInputKind::FragCoord) {
|
||||
const auto pointer = state.builder.AllocateId();
|
||||
const auto value = state.builder.AllocateId();
|
||||
const auto bits = state.builder.AllocateId();
|
||||
state.builder.AddFunction({OpAccessChain, state.ptr_input_float, pointer, variable,
|
||||
ConstantU32(state, component)});
|
||||
state.builder.AddFunction({OpLoad, state.float_type, value, pointer});
|
||||
state.builder.AddFunction({OpBitcast, state.uint_type, bits, value});
|
||||
state.builder.AddFunction({OpAccessChain,
|
||||
TypePointer(state, StorageClassInput, TypeF32(state)), pointer,
|
||||
variable, ConstantU32(state, component)});
|
||||
state.builder.AddFunction({OpLoad, TypeF32(state), value, pointer});
|
||||
state.builder.AddFunction({OpBitcast, TypeU32(state), bits, value});
|
||||
return bits;
|
||||
}
|
||||
return EmitInputComponentU32(state, kind, component);
|
||||
@@ -85,12 +86,12 @@ uint32_t EmitBuiltinU32(ValueEmitContext& ctx, IR::StageInputKind kind, uint32_t
|
||||
uint32_t EmitWqm(ValueEmitContext& ctx, uint32_t active) {
|
||||
auto& state = ctx.state;
|
||||
const auto ballot = state.builder.AllocateId();
|
||||
state.builder.AddFunction({OpGroupNonUniformBallot, state.vec4_uint_type, ballot,
|
||||
state.builder.AddFunction({OpGroupNonUniformBallot, TypeU32Vector(state, 4), ballot,
|
||||
ConstantU32(state, ScopeSubgroup), active});
|
||||
const auto low = state.builder.AllocateId();
|
||||
const auto high = state.builder.AllocateId();
|
||||
state.builder.AddFunction({OpCompositeExtract, state.uint_type, low, ballot, 0});
|
||||
state.builder.AddFunction({OpCompositeExtract, state.uint_type, high, ballot, 1});
|
||||
state.builder.AddFunction({OpCompositeExtract, TypeU32(state), low, ballot, 0});
|
||||
state.builder.AddFunction({OpCompositeExtract, TypeU32(state), high, ballot, 1});
|
||||
const auto wqm_low = EmitWqmLaneU32(state, low);
|
||||
const auto wqm_high = EmitWqmLaneU32(state, high);
|
||||
const auto lane = EmitSubgroupLocalInvocationId(state);
|
||||
@@ -101,14 +102,14 @@ uint32_t EmitWqm(ValueEmitContext& ctx, uint32_t active) {
|
||||
const auto hit = state.builder.AllocateId();
|
||||
const auto result = state.builder.AllocateId();
|
||||
state.builder.AddFunction(
|
||||
{OpUGreaterThanEqual, state.bool_type, upper, lane, ConstantU32(state, 32)});
|
||||
state.builder.AddFunction({OpSelect, state.uint_type, mask, upper, wqm_high, wqm_low});
|
||||
{OpUGreaterThanEqual, TypeBool(state), upper, lane, ConstantU32(state, 32)});
|
||||
state.builder.AddFunction({OpSelect, TypeU32(state), mask, upper, wqm_high, wqm_low});
|
||||
state.builder.AddFunction(
|
||||
{OpBitwiseAnd, state.uint_type, bit_lane, lane, ConstantU32(state, 31)});
|
||||
{OpBitwiseAnd, TypeU32(state), bit_lane, lane, ConstantU32(state, 31)});
|
||||
state.builder.AddFunction(
|
||||
{OpShiftLeftLogical, state.uint_type, bit, ConstantU32(state, 1), bit_lane});
|
||||
state.builder.AddFunction({OpBitwiseAnd, state.uint_type, hit, mask, bit});
|
||||
state.builder.AddFunction({OpINotEqual, state.bool_type, result, hit, ConstantU32(state, 0)});
|
||||
{OpShiftLeftLogical, TypeU32(state), bit, ConstantU32(state, 1), bit_lane});
|
||||
state.builder.AddFunction({OpBitwiseAnd, TypeU32(state), hit, mask, bit});
|
||||
state.builder.AddFunction({OpINotEqual, TypeBool(state), result, hit, ConstantU32(state, 0)});
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -128,35 +129,35 @@ uint32_t EmitDppWriteCondition(ValueEmitContext& ctx, const IR::DppMoveFlags& fl
|
||||
const auto row_ok = state.builder.AllocateId();
|
||||
const auto masks_ok = state.builder.AllocateId();
|
||||
state.builder.AddFunction(
|
||||
{OpShiftRightLogical, state.uint_type, bank_shift, lane, ConstantU32(state, 2)});
|
||||
{OpShiftRightLogical, TypeU32(state), bank_shift, lane, ConstantU32(state, 2)});
|
||||
state.builder.AddFunction(
|
||||
{OpShiftRightLogical, state.uint_type, row_shift, lane, ConstantU32(state, 4)});
|
||||
{OpShiftRightLogical, TypeU32(state), row_shift, lane, ConstantU32(state, 4)});
|
||||
state.builder.AddFunction(
|
||||
{OpBitwiseAnd, state.uint_type, bank, bank_shift, ConstantU32(state, 3)});
|
||||
{OpBitwiseAnd, TypeU32(state), bank, bank_shift, ConstantU32(state, 3)});
|
||||
state.builder.AddFunction(
|
||||
{OpBitwiseAnd, state.uint_type, row, row_shift, ConstantU32(state, 3)});
|
||||
{OpBitwiseAnd, TypeU32(state), row, row_shift, ConstantU32(state, 3)});
|
||||
state.builder.AddFunction(
|
||||
{OpShiftLeftLogical, state.uint_type, bank_bit, ConstantU32(state, 1), bank});
|
||||
{OpShiftLeftLogical, TypeU32(state), bank_bit, ConstantU32(state, 1), bank});
|
||||
state.builder.AddFunction(
|
||||
{OpShiftLeftLogical, state.uint_type, row_bit, ConstantU32(state, 1), row});
|
||||
{OpShiftLeftLogical, TypeU32(state), row_bit, ConstantU32(state, 1), row});
|
||||
state.builder.AddFunction(
|
||||
{OpBitwiseAnd, state.uint_type, bank_hit, ConstantU32(state, flags.bank_mask), bank_bit});
|
||||
{OpBitwiseAnd, TypeU32(state), bank_hit, ConstantU32(state, flags.bank_mask), bank_bit});
|
||||
state.builder.AddFunction(
|
||||
{OpBitwiseAnd, state.uint_type, row_hit, ConstantU32(state, flags.row_mask), row_bit});
|
||||
{OpBitwiseAnd, TypeU32(state), row_hit, ConstantU32(state, flags.row_mask), row_bit});
|
||||
state.builder.AddFunction(
|
||||
{OpINotEqual, state.bool_type, bank_ok, bank_hit, ConstantU32(state, 0)});
|
||||
{OpINotEqual, TypeBool(state), bank_ok, bank_hit, ConstantU32(state, 0)});
|
||||
state.builder.AddFunction(
|
||||
{OpINotEqual, state.bool_type, row_ok, row_hit, ConstantU32(state, 0)});
|
||||
state.builder.AddFunction({OpLogicalAnd, state.bool_type, masks_ok, bank_ok, row_ok});
|
||||
{OpINotEqual, TypeBool(state), row_ok, row_hit, ConstantU32(state, 0)});
|
||||
state.builder.AddFunction({OpLogicalAnd, TypeBool(state), masks_ok, bank_ok, row_ok});
|
||||
uint32_t writable = masks_ok;
|
||||
if (!flags.bound_control) {
|
||||
const auto target = EmitDppTargetLane(state, flags.control);
|
||||
const auto bounded = state.builder.AllocateId();
|
||||
state.builder.AddFunction({OpLogicalAnd, state.bool_type, bounded, writable, target.valid});
|
||||
state.builder.AddFunction({OpLogicalAnd, TypeBool(state), bounded, writable, target.valid});
|
||||
writable = bounded;
|
||||
}
|
||||
const auto result = state.builder.AllocateId();
|
||||
state.builder.AddFunction({OpLogicalAnd, state.bool_type, result, exec, writable});
|
||||
state.builder.AddFunction({OpLogicalAnd, TypeBool(state), result, exec, writable});
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -172,9 +173,9 @@ uint32_t EmitAttribute(ValueEmitContext& ctx, uint32_t attr, uint32_t chan) {
|
||||
const auto vector = state.builder.AllocateId();
|
||||
const auto component = state.builder.AllocateId();
|
||||
const auto bits = state.builder.AllocateId();
|
||||
state.builder.AddFunction({OpLoad, state.vec4_float_type, vector, input->variable_id});
|
||||
state.builder.AddFunction({OpCompositeExtract, state.float_type, component, vector, chan & 3u});
|
||||
state.builder.AddFunction({OpBitcast, state.uint_type, bits, component});
|
||||
state.builder.AddFunction({OpLoad, TypeF32Vector(state, 4), vector, input->variable_id});
|
||||
state.builder.AddFunction({OpCompositeExtract, TypeF32(state), component, vector, chan & 3u});
|
||||
state.builder.AddFunction({OpBitcast, TypeU32(state), bits, component});
|
||||
return bits;
|
||||
}
|
||||
|
||||
@@ -187,7 +188,7 @@ bool MrtUsesUint(const EmitterState& state, const IR::ExportInfo& exp) {
|
||||
uint32_t ExportRawComponent(ValueEmitContext& ctx, uint32_t vector, uint32_t component) {
|
||||
const auto value = ctx.state.builder.AllocateId();
|
||||
ctx.state.builder.AddFunction(
|
||||
{OpCompositeExtract, ctx.state.uint_type, value, vector, component});
|
||||
{OpCompositeExtract, TypeU32(ctx.state), value, vector, component});
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -203,21 +204,21 @@ uint32_t ExportVector(ValueEmitContext& ctx, uint32_t data, const IR::ExportInfo
|
||||
}
|
||||
const auto packed = state.builder.AllocateId();
|
||||
const auto unpacked = state.builder.AllocateId();
|
||||
state.builder.AddFunction({OpCompositeExtract, state.uint_type, packed, data, pair});
|
||||
state.builder.AddFunction({OpExtInst, state.vec2_float_type, unpacked,
|
||||
state.glsl_std450, GlslUnpackHalf2x16, packed});
|
||||
state.builder.AddFunction({OpCompositeExtract, TypeU32(state), packed, data, pair});
|
||||
state.builder.AddFunction({OpExtInst, TypeF32Vector(state, 2), unpacked,
|
||||
GlslStd450(state), GlslUnpackHalf2x16, packed});
|
||||
for (uint32_t lane = 0; lane < 2u; lane++) {
|
||||
const auto component = pair * 2u + lane;
|
||||
if (((exp.en >> component) & 1u) != 0u) {
|
||||
f32[component] = state.builder.AllocateId();
|
||||
state.builder.AddFunction(
|
||||
{OpCompositeExtract, state.float_type, f32[component], unpacked, lane});
|
||||
{OpCompositeExtract, TypeF32(state), f32[component], unpacked, lane});
|
||||
}
|
||||
}
|
||||
}
|
||||
const auto vector = state.builder.AllocateId();
|
||||
state.builder.AddFunction(
|
||||
{OpCompositeConstruct, state.vec4_float_type, vector, f32[0], f32[1], f32[2], f32[3]});
|
||||
state.builder.AddFunction({OpCompositeConstruct, TypeF32Vector(state, 4), vector, f32[0],
|
||||
f32[1], f32[2], f32[3]});
|
||||
return vector;
|
||||
}
|
||||
uint32_t raw[4] = {
|
||||
@@ -238,7 +239,7 @@ uint32_t ExportVector(ValueEmitContext& ctx, uint32_t data, const IR::ExportInfo
|
||||
continue;
|
||||
}
|
||||
raw[component] = state.builder.AllocateId();
|
||||
state.builder.AddFunction({OpBitFieldUExtract, state.uint_type, raw[component],
|
||||
state.builder.AddFunction({OpBitFieldUExtract, TypeU32(state), raw[component],
|
||||
packed, ConstantU32(state, lane * 16u),
|
||||
ConstantU32(state, 16)});
|
||||
}
|
||||
@@ -252,18 +253,18 @@ uint32_t ExportVector(ValueEmitContext& ctx, uint32_t data, const IR::ExportInfo
|
||||
}
|
||||
if (uint_output) {
|
||||
const auto vector = state.builder.AllocateId();
|
||||
state.builder.AddFunction(
|
||||
{OpCompositeConstruct, state.vec4_uint_type, vector, raw[0], raw[1], raw[2], raw[3]});
|
||||
state.builder.AddFunction({OpCompositeConstruct, TypeU32Vector(state, 4), vector, raw[0],
|
||||
raw[1], raw[2], raw[3]});
|
||||
return vector;
|
||||
}
|
||||
uint32_t f32[4] {};
|
||||
for (uint32_t component = 0; component < 4u; component++) {
|
||||
f32[component] = state.builder.AllocateId();
|
||||
state.builder.AddFunction({OpBitcast, state.float_type, f32[component], raw[component]});
|
||||
state.builder.AddFunction({OpBitcast, TypeF32(state), f32[component], raw[component]});
|
||||
}
|
||||
const auto vector = state.builder.AllocateId();
|
||||
state.builder.AddFunction(
|
||||
{OpCompositeConstruct, state.vec4_float_type, vector, f32[0], f32[1], f32[2], f32[3]});
|
||||
{OpCompositeConstruct, TypeF32Vector(state, 4), vector, f32[0], f32[1], f32[2], f32[3]});
|
||||
return vector;
|
||||
}
|
||||
|
||||
@@ -271,11 +272,11 @@ void EmitExport(ValueEmitContext& ctx, const IR::Inst& inst) {
|
||||
auto& state = ctx.state;
|
||||
const auto& exp = ctx.Export(inst);
|
||||
const auto exec = ctx.Arg(inst, 1);
|
||||
if (state.stage == ShaderType::Pixel && exp.vm && state.needs_pixel_valid_mask &&
|
||||
if (state.stage == ShaderType::Pixel && exp.vm && state.requirements.pixel_valid_mask &&
|
||||
state.pixel_valid_mask_variable != 0) {
|
||||
const auto value = state.builder.AllocateId();
|
||||
state.builder.AddFunction(
|
||||
{OpSelect, state.uint_type, value, exec, ConstantU32(state, 1), ConstantU32(state, 0)});
|
||||
{OpSelect, TypeU32(state), value, exec, ConstantU32(state, 1), ConstantU32(state, 0)});
|
||||
state.builder.AddFunction({OpStore, state.pixel_valid_mask_variable, value});
|
||||
}
|
||||
if (exp.kind == IR::ExportTargetKind::Null || exp.kind == IR::ExportTargetKind::Primitive ||
|
||||
@@ -288,16 +289,17 @@ void EmitExport(ValueEmitContext& ctx, const IR::Inst& inst) {
|
||||
if ((exp.en & 1u) != 0u && state.depth_variable != 0) {
|
||||
const auto raw = ExportRawComponent(ctx, data, 0);
|
||||
const auto f32 = state.builder.AllocateId();
|
||||
state.builder.AddFunction({OpBitcast, state.float_type, f32, raw});
|
||||
state.builder.AddFunction({OpBitcast, TypeF32(state), f32, raw});
|
||||
state.builder.AddFunction({OpStore, state.depth_variable, f32});
|
||||
}
|
||||
if ((exp.en & 4u) != 0u && state.sample_mask_variable != 0) {
|
||||
const auto raw = ExportRawComponent(ctx, data, 2);
|
||||
const auto value = state.builder.AllocateId();
|
||||
const auto pointer = state.builder.AllocateId();
|
||||
state.builder.AddFunction({OpBitcast, state.int_type, value, raw});
|
||||
state.builder.AddFunction({OpAccessChain, state.ptr_output_int, pointer,
|
||||
state.sample_mask_variable, ConstantU32(state, 0)});
|
||||
state.builder.AddFunction({OpBitcast, TypeI32(state), value, raw});
|
||||
state.builder.AddFunction(
|
||||
{OpAccessChain, TypePointer(state, StorageClassOutput, TypeI32(state)), pointer,
|
||||
state.sample_mask_variable, ConstantU32(state, 0)});
|
||||
state.builder.AddFunction({OpStore, pointer, value});
|
||||
}
|
||||
return;
|
||||
@@ -307,7 +309,7 @@ void EmitExport(ValueEmitContext& ctx, const IR::Inst& inst) {
|
||||
return;
|
||||
}
|
||||
const bool uint_output = MrtUsesUint(state, exp);
|
||||
const auto vector_type = uint_output ? state.vec4_uint_type : state.vec4_float_type;
|
||||
const auto vector_type = uint_output ? TypeU32Vector(state, 4) : TypeF32Vector(state, 4);
|
||||
auto value = ExportVector(ctx, data, exp, uint_output);
|
||||
if (state.stage == ShaderType::Pixel && exp.kind == IR::ExportTargetKind::Mrt &&
|
||||
exp.index < state.input_info.pixel->target_export_mapping.size()) {
|
||||
@@ -322,8 +324,9 @@ void EmitExport(ValueEmitContext& ctx, const IR::Inst& inst) {
|
||||
}
|
||||
if (exp.kind == IR::ExportTargetKind::Position) {
|
||||
const auto pointer = state.builder.AllocateId();
|
||||
state.builder.AddFunction({OpAccessChain, state.ptr_output_vec4_float, pointer,
|
||||
variable, ConstantU32(state, 0)});
|
||||
state.builder.AddFunction(
|
||||
{OpAccessChain, TypePointer(state, StorageClassOutput, TypeF32Vector(state, 4)),
|
||||
pointer, variable, ConstantU32(state, 0)});
|
||||
state.builder.AddFunction({OpStore, pointer, value});
|
||||
} else {
|
||||
state.builder.AddFunction({OpStore, variable, value});
|
||||
@@ -378,7 +381,7 @@ bool EmitValueFlow(ValueEmitContext& ctx, const IR::Inst& inst) {
|
||||
const auto flags = inst.Flags<IR::DppMoveFlags>();
|
||||
const auto target = EmitDppTargetLane(state, flags.control);
|
||||
const auto shuffled = state.builder.AllocateId();
|
||||
state.builder.AddFunction({OpGroupNonUniformShuffle, state.uint_type, shuffled,
|
||||
state.builder.AddFunction({OpGroupNonUniformShuffle, TypeU32(state), shuffled,
|
||||
ConstantU32(state, ScopeSubgroup), ctx.Arg(inst, 0),
|
||||
target.lane});
|
||||
if (flags.fetch_inactive) {
|
||||
@@ -386,12 +389,12 @@ bool EmitValueFlow(ValueEmitContext& ctx, const IR::Inst& inst) {
|
||||
return true;
|
||||
}
|
||||
const auto ballot = state.builder.AllocateId();
|
||||
state.builder.AddFunction({OpGroupNonUniformBallot, state.vec4_uint_type, ballot,
|
||||
state.builder.AddFunction({OpGroupNonUniformBallot, TypeU32Vector(state, 4), ballot,
|
||||
ConstantU32(state, ScopeSubgroup), ctx.Arg(inst, 1)});
|
||||
const auto source_active = EmitBallotLaneActiveBool(state, ballot, target.lane);
|
||||
const auto can_fetch = state.builder.AllocateId();
|
||||
state.builder.AddFunction(
|
||||
{OpLogicalAnd, state.bool_type, can_fetch, target.valid, source_active});
|
||||
{OpLogicalAnd, TypeBool(state), can_fetch, target.valid, source_active});
|
||||
ctx.Emit(inst, OpSelect, IR::Type::U32, {can_fetch, shuffled, ConstantU32(state, 0)});
|
||||
return true;
|
||||
}
|
||||
@@ -410,7 +413,7 @@ bool EmitValueFlow(ValueEmitContext& ctx, const IR::Inst& inst) {
|
||||
case IR::ValueOpcode::Ballot:
|
||||
if (state.per_invocation_masks) {
|
||||
const auto result = state.builder.AllocateId();
|
||||
state.builder.AddFunction({OpCompositeConstruct, state.vec4_uint_type, result,
|
||||
state.builder.AddFunction({OpCompositeConstruct, TypeU32Vector(state, 4), result,
|
||||
BoolAsU32(ctx, ctx.Arg(inst, 0)), ConstantU32(state, 0),
|
||||
ConstantU32(state, 0), ConstantU32(state, 0)});
|
||||
ctx.Define(inst, result);
|
||||
@@ -422,9 +425,9 @@ bool EmitValueFlow(ValueEmitContext& ctx, const IR::Inst& inst) {
|
||||
case IR::ValueOpcode::ReadFirstLane: {
|
||||
const auto ballot = state.builder.AllocateId();
|
||||
const auto lane = state.builder.AllocateId();
|
||||
state.builder.AddFunction({OpGroupNonUniformBallot, state.vec4_uint_type, ballot,
|
||||
state.builder.AddFunction({OpGroupNonUniformBallot, TypeU32Vector(state, 4), ballot,
|
||||
ConstantU32(state, ScopeSubgroup), ctx.Arg(inst, 1)});
|
||||
state.builder.AddFunction({OpGroupNonUniformBallotFindLSB, state.uint_type, lane,
|
||||
state.builder.AddFunction({OpGroupNonUniformBallotFindLSB, TypeU32(state), lane,
|
||||
ConstantU32(state, ScopeSubgroup), ballot});
|
||||
ctx.Emit(inst, OpGroupNonUniformShuffle, IR::Type::U32,
|
||||
{ConstantU32(state, ScopeSubgroup), ctx.Arg(inst, 0), lane});
|
||||
@@ -436,7 +439,7 @@ bool EmitValueFlow(ValueEmitContext& ctx, const IR::Inst& inst) {
|
||||
return true;
|
||||
case IR::ValueOpcode::WriteLane: {
|
||||
const auto hit = state.builder.AllocateId();
|
||||
state.builder.AddFunction({OpIEqual, state.bool_type, hit,
|
||||
state.builder.AddFunction({OpIEqual, TypeBool(state), hit,
|
||||
EmitSubgroupLocalInvocationId(state), ctx.Arg(inst, 2)});
|
||||
ctx.Emit(inst, OpSelect, IR::Type::U32, {hit, ctx.Arg(inst, 1), ctx.Arg(inst, 0)});
|
||||
return true;
|
||||
@@ -455,40 +458,40 @@ bool EmitValueFlow(ValueEmitContext& ctx, const IR::Inst& inst) {
|
||||
const auto index = state.builder.AllocateId();
|
||||
const auto target = state.builder.AllocateId();
|
||||
state.builder.AddFunction(
|
||||
{OpBitwiseAnd, state.uint_type, row, subid, ConstantU32(state, 0xfffffff0u)});
|
||||
{OpBitwiseAnd, TypeU32(state), row, subid, ConstantU32(state, 0xfffffff0u)});
|
||||
if (flags.x16) {
|
||||
state.builder.AddFunction(
|
||||
{OpBitwiseXor, state.uint_type, row_value, row, ConstantU32(state, 16)});
|
||||
{OpBitwiseXor, TypeU32(state), row_value, row, ConstantU32(state, 16)});
|
||||
} else {
|
||||
state.builder.AddFunction({OpCopyObject, state.uint_type, row_value, row});
|
||||
state.builder.AddFunction({OpCopyObject, TypeU32(state), row_value, row});
|
||||
}
|
||||
state.builder.AddFunction(
|
||||
{OpBitwiseAnd, state.uint_type, lane, subid, ConstantU32(state, 15)});
|
||||
{OpBitwiseAnd, TypeU32(state), lane, subid, ConstantU32(state, 15)});
|
||||
state.builder.AddFunction(
|
||||
{OpBitwiseAnd, state.uint_type, lane8, lane, ConstantU32(state, 7)});
|
||||
{OpBitwiseAnd, TypeU32(state), lane8, lane, ConstantU32(state, 7)});
|
||||
state.builder.AddFunction(
|
||||
{OpShiftLeftLogical, state.uint_type, shift, lane8, ConstantU32(state, 2)});
|
||||
{OpShiftLeftLogical, TypeU32(state), shift, lane8, ConstantU32(state, 2)});
|
||||
state.builder.AddFunction(
|
||||
{OpUGreaterThanEqual, state.bool_type, upper, lane, ConstantU32(state, 8)});
|
||||
{OpUGreaterThanEqual, TypeBool(state), upper, lane, ConstantU32(state, 8)});
|
||||
state.builder.AddFunction(
|
||||
{OpSelect, state.uint_type, selected, upper, ctx.Arg(inst, 2), ctx.Arg(inst, 1)});
|
||||
{OpSelect, TypeU32(state), selected, upper, ctx.Arg(inst, 2), ctx.Arg(inst, 1)});
|
||||
state.builder.AddFunction(
|
||||
{OpShiftRightLogical, state.uint_type, shifted, selected, shift});
|
||||
{OpShiftRightLogical, TypeU32(state), shifted, selected, shift});
|
||||
state.builder.AddFunction(
|
||||
{OpBitwiseAnd, state.uint_type, index, shifted, ConstantU32(state, 15)});
|
||||
state.builder.AddFunction({OpBitwiseOr, state.uint_type, target, row_value, index});
|
||||
{OpBitwiseAnd, TypeU32(state), index, shifted, ConstantU32(state, 15)});
|
||||
state.builder.AddFunction({OpBitwiseOr, TypeU32(state), target, row_value, index});
|
||||
const auto shuffled = state.builder.AllocateId();
|
||||
state.builder.AddFunction({OpGroupNonUniformShuffle, state.uint_type, shuffled,
|
||||
state.builder.AddFunction({OpGroupNonUniformShuffle, TypeU32(state), shuffled,
|
||||
ConstantU32(state, ScopeSubgroup), ctx.Arg(inst, 0),
|
||||
target});
|
||||
uint32_t result = shuffled;
|
||||
if (!flags.fetch_inactive) {
|
||||
const auto source_exec = state.builder.AllocateId();
|
||||
state.builder.AddFunction({OpGroupNonUniformShuffle, state.bool_type, source_exec,
|
||||
state.builder.AddFunction({OpGroupNonUniformShuffle, TypeBool(state), source_exec,
|
||||
ConstantU32(state, ScopeSubgroup), ctx.Arg(inst, 3),
|
||||
target});
|
||||
result = state.builder.AllocateId();
|
||||
state.builder.AddFunction({OpSelect, state.uint_type, result, source_exec, shuffled,
|
||||
state.builder.AddFunction({OpSelect, TypeU32(state), result, source_exec, shuffled,
|
||||
ConstantU32(state, 0)});
|
||||
}
|
||||
ctx.Define(inst, result);
|
||||
|
||||
Reference in New Issue
Block a user