shader: emit bounded SPIR-V operands without temporary vectors

This commit is contained in:
nmzik
2026-10-09 01:58:39 +02:00
parent 7c6121cba5
commit 8abf99c56e
3 changed files with 26 additions and 36 deletions
@@ -80,9 +80,7 @@ uint32_t EmitFMinMax3(EmitterState& state, uint32_t a, uint32_t b, uint32_t c, b
uint32_t EmitExt(EmitterState& state, uint32_t type, uint32_t opcode, uint32_t EmitExt(EmitterState& state, uint32_t type, uint32_t opcode,
std::initializer_list<uint32_t> args) { std::initializer_list<uint32_t> args) {
const auto result = state.builder.AllocateId(); const auto result = state.builder.AllocateId();
std::vector<uint32_t> words {spv::OpExtInst, type, result, GlslStd450(state), opcode}; state.builder.AddFunction(spv::OpExtInst, type, result, GlslStd450(state), opcode, args);
words.insert(words.end(), args.begin(), args.end());
state.builder.AddFunction(words);
return result; return result;
} }
@@ -752,14 +752,11 @@ void EmitImage(ValueEmitContext& ctx, const IR::Inst& inst) {
const auto EmitGather = [&](uint32_t mip) { const auto EmitGather = [&](uint32_t mip) {
const auto sampled = MakeSampledImage(state, mem.resource, sampler_id, mip); const auto sampled = MakeSampledImage(state, mem.resource, sampler_id, mip);
const auto sample = state.builder.AllocateId(); const auto sample = state.builder.AllocateId();
std::vector<uint32_t> words { const std::array operands {operand_mask, offset};
static_cast<uint32_t>(dref ? spv::OpImageDrefGather : spv::OpImageGather), result_type, state.builder.AddFunction(
sample, sampled, coord, component_or_dref}; dref ? spv::OpImageDrefGather : spv::OpImageGather, result_type,
if (operand_mask != 0u) { sample, sampled, coord, component_or_dref,
words.push_back(operand_mask); std::span(operands).first(operand_mask != 0u ? 2u : 0u));
words.push_back(offset);
}
state.builder.AddFunction(words);
return sample; return sample;
}; };
const auto sample = image.mip_mode == IR::ImageMipMode::Dynamic && image.mip_count > 1u const auto sample = image.mip_mode == IR::ImageMipMode::Dynamic && image.mip_count > 1u
@@ -791,24 +788,25 @@ void EmitImage(ValueEmitContext& ctx, const IR::Inst& inst) {
dref_value = AddressF32(ctx, mem, *address, layout.dref); dref_value = AddressF32(ctx, mem, *address, layout.dref);
} }
} }
uint32_t operand_mask = 0; std::array<uint32_t, 3> operands {};
std::vector<uint32_t> operands; size_t operand_count = 0;
if (HasFlag(mem, Decoder::ImageSampleFlagDerivative)) { if (HasFlag(mem, Decoder::ImageSampleFlagDerivative)) {
operand_mask |= spv::ImageOperandsGradMask; operands[0] = spv::ImageOperandsGradMask;
operands.push_back( operands[1] = CoordF32(ctx, mem, *address, layout.grad_x, dimension_info.spatial_components);
CoordF32(ctx, mem, *address, layout.grad_x, dimension_info.spatial_components)); operands[2] = CoordF32(ctx, mem, *address, layout.grad_y, dimension_info.spatial_components);
operands.push_back( operand_count = 3;
CoordF32(ctx, mem, *address, layout.grad_y, dimension_info.spatial_components));
} else if (explicit_lod) { } else if (explicit_lod) {
operand_mask |= spv::ImageOperandsLodMask;
auto lod = ZeroF32(state); auto lod = ZeroF32(state);
if (HasFlag(mem, Decoder::ImageSampleFlagLod) && layout.lod != NoImageComponent) { if (HasFlag(mem, Decoder::ImageSampleFlagLod) && layout.lod != NoImageComponent) {
lod = AddressF32(ctx, mem, *address, layout.lod); lod = AddressF32(ctx, mem, *address, layout.lod);
} }
operands.push_back(lod); operands[0] = spv::ImageOperandsLodMask;
operands[1] = lod;
operand_count = 2;
} else if (layout.bias != NoImageComponent) { } else if (layout.bias != NoImageComponent) {
operand_mask |= spv::ImageOperandsBiasMask; operands[0] = spv::ImageOperandsBiasMask;
operands.push_back(AddressF32(ctx, mem, *address, layout.bias)); operands[1] = AddressF32(ctx, mem, *address, layout.bias);
operand_count = 2;
} }
const auto sampler_id = LoadSamplerDescriptor(state, mem.sampler); const auto sampler_id = LoadSamplerDescriptor(state, mem.sampler);
const auto EmitSample = [&](uint32_t resource, uint32_t array_index = 0u) { const auto EmitSample = [&](uint32_t resource, uint32_t array_index = 0u) {
@@ -819,15 +817,9 @@ void EmitImage(ValueEmitContext& ctx, const IR::Inst& inst) {
candidate.cube); candidate.cube);
const auto sampled = MakeSampledImage(state, resource, sampler_id, 0u, array_index); const auto sampled = MakeSampledImage(state, resource, sampler_id, 0u, array_index);
const auto sample = state.builder.AllocateId(); const auto sample = state.builder.AllocateId();
std::vector<uint32_t> sample_operands {result_type, sample, sampled, coord}; state.builder.AddFunction(opcode, result_type, sample, sampled, coord,
if (dref) { std::span(&dref_value, dref ? 1u : 0u),
sample_operands.push_back(dref_value); std::span<const uint32_t>(operands).first(operand_count));
}
if (operand_mask != 0u) {
sample_operands.push_back(operand_mask);
sample_operands.insert(sample_operands.end(), operands.begin(), operands.end());
}
state.builder.AddFunction(opcode, sample_operands);
return sample; return sample;
}; };
if (image.indirect_root != mem.resource) { if (image.indirect_root != mem.resource) {
@@ -384,9 +384,9 @@ uint32_t ConstantU32CompositeZero(EmitterState& state, uint32_t components) {
EXIT_IF(components < 1u || components > 4u); EXIT_IF(components < 1u || components > 4u);
const auto zero = ConstantU32(state, 0); const auto zero = ConstantU32(state, 0);
if (components == 1u) return zero; if (components == 1u) return zero;
std::vector<uint32_t> values(components, zero); const std::array values {zero, zero, zero, zero};
return state.builder.Constant(spv::OpConstantComposite, TypeU32Composite(state, components), return state.builder.Constant(spv::OpConstantComposite, TypeU32Composite(state, components),
values); std::span(values).first(components));
} }
uint32_t GlslStd450(EmitterState& state) { uint32_t GlslStd450(EmitterState& state) {