shader: emit dynamic sample offsets with the enabled maintenance8 feature

This commit is contained in:
Ali Almohaya
2026-10-12 19:11:00 +02:00
committed by nmzik
parent 652154aead
commit 460a196fca
11 changed files with 135 additions and 26 deletions
@@ -197,7 +197,7 @@ void ValidateNativeProgram(const IR::Program& program, bool lds_storage) {
} // namespace
std::vector<uint32_t> EmitProgram(IR::Program& program, ShaderStageInputInfo input_info,
uint32_t push_data_start_dword) {
uint32_t push_data_start_dword, bool maintenance8_enabled) {
using namespace Emitter;
if (program.stage != ShaderType::Compute && program.stage != ShaderType::Vertex &&
@@ -215,7 +215,7 @@ std::vector<uint32_t> EmitProgram(IR::Program& program, ShaderStageInputInfo inp
}
IR::ValidateProgram(program, true);
program.bindings = {.push_data_start_dword = push_data_start_dword};
EmitterState state(program, input_info);
EmitterState state(program, input_info, maintenance8_enabled);
const auto* workgroup = ShaderWorkgroupInput(program.stage, input_info);
state.lane_count =
workgroup != nullptr && program.wave_size == 64u && workgroup->host_subgroup_size == 32u
@@ -11,7 +11,8 @@ namespace Libs::Graphics::ShaderRecompiler::Spirv {
// Resets and writes backend IDs and descriptor indices; do not emit the same program concurrently.
std::vector<uint32_t> EmitProgram(IR::Program& program, ShaderStageInputInfo input_info,
uint32_t push_data_start_dword = 0);
uint32_t push_data_start_dword = 0,
bool maintenance8_enabled = false);
} // namespace Libs::Graphics::ShaderRecompiler::Spirv
@@ -333,6 +333,7 @@ uint32_t PackedOffset(ValueEmitContext& ctx, IR::Value value, ImageDimension dim
TypeI32Vector(ctx.state, components),
std::span(values).first(components));
}
ctx.state.builder.RequireCapability(spv::CapabilityImageGatherExtended);
mask |= spv::ImageOperandsOffsetMask;
const auto packed = Unary(ctx.state, spv::OpBitcast, TypeI32(ctx.state), ctx.Def(value));
for (uint32_t index = 0; index < components; index++) {
@@ -937,8 +938,8 @@ void EmitImage(ValueEmitContext& ctx, const IR::Inst& inst) {
operand_count = 2;
}
if (layout.offset != NoImageComponent &&
!offset_value.IsImmediate()) {
ctx.Fail(inst, "has a nonconstant sample texel offset");
!offset_value.IsImmediate() && !state.maintenance8_enabled) {
ctx.Fail(inst, "requires maintenance8 for a dynamic sample texel offset");
}
const auto samplers = EmitImageSamplers(ctx, inst);
const auto EmitSample = [&](uint32_t resource, uint32_t array_index) {
@@ -73,9 +73,9 @@ struct ImageDefinition {
};
struct EmitterState {
EmitterState(IR::Program& program_, ShaderStageInputInfo input_info_)
EmitterState(IR::Program& program_, ShaderStageInputInfo input_info_, bool maintenance8_enabled_)
: builder(program_.stage == ShaderType::Mesh ? 0x00010400u : 0x00010300u),
program(program_), input_info(input_info_) {
program(program_), input_info(input_info_), maintenance8_enabled(maintenance8_enabled_) {
if (ShaderWorkgroupInput(program.stage, input_info) != nullptr) {
lds_storage_class = spv::StorageClassWorkgroup;
}
@@ -88,6 +88,7 @@ struct EmitterState {
Builder builder;
IR::Program& program;
ShaderStageInputInfo input_info;
bool maintenance8_enabled;
uint32_t void_type = 0;
uint32_t bool_type = 0;
uint32_t u32_type = 0;