shader: unify stage input metadata

This commit is contained in:
nmzik
2026-08-18 03:53:44 +02:00
parent 5ea92d95a7
commit 0f3540b1ff
16 changed files with 278 additions and 407 deletions
@@ -336,9 +336,6 @@ EmbeddedFetchData DetectEmbeddedVertexFetch(const Decoder::Program& decoded
uint32_t user_data_base, uint32_t user_data_count,
uint32_t wave_size) {
EmbeddedFetchData data;
if (input_info == nullptr || !input_info->fetch_embedded) {
return data;
}
data.loads.reserve(input_info->resources_num);
int32_t offset_candidate = -1;
bool offset_conflict = false;
@@ -587,9 +584,6 @@ bool IsIrFetchPrologLoad(const IR::Instruction& inst) {
int ResolveEmbeddedFetchResource(const ShaderVertexInputInfo* input_info,
const EmbeddedFetchLoad& load) {
if (input_info == nullptr) {
return -1;
}
if (load.attrib_id >= 0 && load.attrib_id < input_info->resources_num &&
input_info->resources_dst[load.attrib_id].attr_id == load.attrib_id) {
return load.attrib_id;
@@ -611,7 +605,7 @@ int ResolveEmbeddedFetchResource(const ShaderVertexInputInfo* input_info,
uint32_t RewriteEmbeddedVertexFetches(IR::Program& ir, const ShaderVertexInputInfo* input_info,
const std::vector<EmbeddedFetchLoad>& loads) {
if (input_info == nullptr || loads.empty()) {
if (loads.empty()) {
return 0;
}
@@ -840,14 +834,20 @@ bool TryRecompile(std::span<const uint32_t> code, const CompileOptions& options,
" elapsed_ms=%" PRIu64 "\n",
GetDumpLabel(options), StageName(options.stage), options.shader_hash,
static_cast<uint64_t>(ir.blocks.size()), phase_ms());
const ShaderVertexInputInfo* vertex = nullptr;
const ShaderPixelInputInfo* pixel = nullptr;
const ShaderComputeInputInfo* compute = nullptr;
switch (options.stage) {
case ShaderType::Vertex: vertex = options.input_info.vertex; break;
case ShaderType::Pixel: pixel = options.input_info.pixel; break;
case ShaderType::Compute: compute = options.input_info.compute; break;
default: break;
}
EmbeddedFetchData embedded_fetch;
if (options.stage == ShaderType::Vertex && options.vertex_input_info != nullptr &&
options.vertex_input_info->fetch_embedded) {
embedded_fetch =
DetectEmbeddedVertexFetch(decoded, options.vertex_input_info, ir.user_data_base,
ir.user_data_count, options.wave_size);
auto rewritten =
RewriteEmbeddedVertexFetches(ir, options.vertex_input_info, embedded_fetch.loads);
if (options.stage == ShaderType::Vertex && vertex->fetch_embedded) {
embedded_fetch = DetectEmbeddedVertexFetch(decoded, vertex, ir.user_data_base,
ir.user_data_count, options.wave_size);
auto rewritten = RewriteEmbeddedVertexFetches(ir, vertex, embedded_fetch.loads);
if (rewritten > 0 || !embedded_fetch.loads.empty()) {
LOGF("%s embedded vertex fetch rewrite: detected=%" PRIu64 " rewritten=%" PRIu32 "\n",
GetDumpLabel(options), static_cast<uint64_t>(embedded_fetch.loads.size()),
@@ -859,15 +859,6 @@ bool TryRecompile(std::span<const uint32_t> code, const CompileOptions& options,
ir.fallback_reason = dispatcher_reason;
}
ShaderVertexInputInfo default_vertex {};
ShaderPixelInputInfo default_pixel {};
ShaderComputeInputInfo default_compute {};
const auto* vertex =
options.vertex_input_info != nullptr ? options.vertex_input_info : &default_vertex;
const auto* pixel =
options.pixel_input_info != nullptr ? options.pixel_input_info : &default_pixel;
const auto* compute =
options.compute_input_info != nullptr ? options.compute_input_info : &default_compute;
ir.values = std::make_shared<IR::ValueProgram>();
if (!Frontend::TranslateProgram(ir, *ir.values, vertex, pixel, compute, error)) {
return false;
@@ -962,8 +953,8 @@ bool TryRecompile(std::span<const uint32_t> code, const CompileOptions& options,
std::string emit_error;
LOGF("%s phase begin: stage=%s hash=0x%016" PRIx64 " SPIR-V EmitProgram\n",
GetDumpLabel(options), StageName(options.stage), options.shader_hash);
if (!Spirv::EmitProgram(ir, resources, options.vertex_input_info, options.pixel_input_info,
options.compute_input_info, spirv, &emit_error, options.dump_ir)) {
if (!Spirv::EmitProgram(ir, resources, options.input_info, spirv, &emit_error,
options.dump_ir)) {
LOGF("%s typed SPIR-V emit failed: %s\n", GetDumpLabel(options), emit_error.c_str());
if (dispatcher_fallback && error != nullptr) {
*error = fmt::format("dispatcher fallback failed after {}: {}",
@@ -13,27 +13,25 @@
namespace Libs::Graphics::ShaderRecompiler {
struct CompileOptions {
ShaderType stage = ShaderType::Compute;
ShaderLaneMaskMode lane_mask_mode = ShaderLaneMaskMode::NativeWave;
uint32_t wave_size = 64;
uint32_t user_data_base = 0;
uint32_t user_data_count = 64;
uint64_t shader_hash = 0;
uint64_t shader_base = 0;
std::optional<uint64_t> flat_memory_base;
uint32_t descriptor_set = 0;
uint32_t push_constant_offset = 0;
bool dump_ir = true;
bool early_dump = false;
const char* dump_label = nullptr;
const uint32_t* user_data = nullptr;
IR::SrtMemoryReader read_memory = nullptr;
IR::SrtMemoryReader read_specialization_memory = nullptr;
void* read_memory_data = nullptr;
const IR::ResourceSnapshot* resource_snapshot = nullptr;
const ShaderVertexInputInfo* vertex_input_info = nullptr;
const ShaderPixelInputInfo* pixel_input_info = nullptr;
const ShaderComputeInputInfo* compute_input_info = nullptr;
ShaderType stage = ShaderType::Compute;
ShaderLaneMaskMode lane_mask_mode = ShaderLaneMaskMode::NativeWave;
uint32_t wave_size = 64;
uint32_t user_data_base = 0;
uint32_t user_data_count = 64;
uint64_t shader_hash = 0;
uint64_t shader_base = 0;
std::optional<uint64_t> flat_memory_base;
uint32_t descriptor_set = 0;
uint32_t push_constant_offset = 0;
bool dump_ir = true;
bool early_dump = false;
const char* dump_label = nullptr;
const uint32_t* user_data = nullptr;
IR::SrtMemoryReader read_memory = nullptr;
IR::SrtMemoryReader read_specialization_memory = nullptr;
void* read_memory_data = nullptr;
const IR::ResourceSnapshot* resource_snapshot = nullptr;
ShaderStageInputInfo input_info;
};
struct CompileResult {
@@ -316,10 +316,8 @@ bool ProgramRequiresExactSubgroupSize(const IR::Program& program) {
}
bool EmitProgram(const IR::Program& program, const IR::ResourceSnapshot& resources,
const ShaderVertexInputInfo* vertex_input_info,
const ShaderPixelInputInfo* pixel_input_info,
const ShaderComputeInputInfo* compute_input_info, std::vector<uint32_t>& spirv,
std::string* error, bool preserve_debug_values) {
ShaderStageInputInfo input_info, std::vector<uint32_t>& spirv, std::string* error,
bool preserve_debug_values) {
using namespace Emitter;
if (program.stage != ShaderType::Compute && program.stage != ShaderType::Vertex &&
@@ -345,21 +343,12 @@ bool EmitProgram(const IR::Program& program, const IR::ResourceSnapshot& resourc
SetError(error, "SPIR-V emitter requires planned typed SSA");
return false;
}
ShaderVertexInputInfo default_vertex {};
ShaderPixelInputInfo default_pixel {};
ShaderComputeInputInfo default_compute {};
const auto* vertex = vertex_input_info != nullptr ? vertex_input_info : &default_vertex;
const auto* pixel = pixel_input_info != nullptr ? pixel_input_info : &default_pixel;
const auto* compute = compute_input_info != nullptr ? compute_input_info : &default_compute;
(void)preserve_debug_values;
const auto& value_program = *program.values;
if (!IR::ValidateValueProgram(value_program, true, error)) {
return false;
}
EmitterState state(program, resources);
state.vertex_input_info = vertex;
state.pixel_input_info = pixel;
state.compute_input_info = compute;
EmitterState state(program, resources, input_info);
state.stage = program.stage;
state.wave_size = program.wave_size;
state.per_invocation_masks = program.lane_mask_mode == ShaderLaneMaskMode::PerInvocation;
@@ -12,10 +12,8 @@ namespace Libs::Graphics::ShaderRecompiler::Spirv {
bool ProgramRequiresExactSubgroupSize(const IR::Program& program);
bool EmitProgram(const IR::Program& program, const IR::ResourceSnapshot& resources,
const ShaderVertexInputInfo* vertex_input_info,
const ShaderPixelInputInfo* pixel_input_info,
const ShaderComputeInputInfo* compute_input_info, std::vector<uint32_t>& spirv,
std::string* error, bool preserve_debug_values = false);
ShaderStageInputInfo input_info, std::vector<uint32_t>& spirv, std::string* error,
bool preserve_debug_values = false);
} // namespace Libs::Graphics::ShaderRecompiler::Spirv
@@ -7,11 +7,10 @@
namespace Libs::Graphics::ShaderRecompiler::Spirv::Emitter {
uint32_t PixelParameterMappedLocation(const EmitterState& state, uint32_t attr) {
const auto* ps = state.pixel_input_info;
if (state.stage != ShaderType::Pixel || ps == nullptr) {
if (state.stage != ShaderType::Pixel) {
return attr;
}
return ShaderPixelParameterMappedLocation(*ps, attr);
return ShaderPixelParameterMappedLocation(*state.input_info.pixel, attr);
}
uint32_t PixelParameterLocation(const EmitterState& state, uint32_t attr) {
@@ -22,16 +21,15 @@ uint32_t PixelParameterLocation(const EmitterState& state, uint32_t attr) {
active_inputs[active_count++] = input.location;
}
}
return state.stage == ShaderType::Pixel && state.pixel_input_info != nullptr
? ShaderPixelParameterLocation(*state.pixel_input_info,
return state.stage == ShaderType::Pixel
? ShaderPixelParameterLocation(*state.input_info.pixel,
{active_inputs.data(), active_count}, attr)
: attr;
}
bool PixelParameterIsFlat(const EmitterState& state, uint32_t attr) {
const auto* ps = state.pixel_input_info;
return state.stage == ShaderType::Pixel && ps != nullptr &&
ShaderPixelParameterIsFlat(*ps, attr);
return state.stage == ShaderType::Pixel &&
ShaderPixelParameterIsFlat(*state.input_info.pixel, attr);
}
void SetError(std::string* error, const char* message) {
@@ -95,20 +95,19 @@ uint32_t EmitExportVec4U32(EmitterState& state, const IR::Instruction& inst) {
}
static bool MrtUsesUintOutput(const EmitterState& state, const IR::Instruction& inst) {
return inst.export_info.kind == IR::ExportTargetKind::Mrt &&
state.pixel_input_info != nullptr &&
inst.export_info.index < std::size(state.pixel_input_info->target_output_mode) &&
state.pixel_input_info->target_output_mode[inst.export_info.index] == 7u;
return state.stage == ShaderType::Pixel && inst.export_info.kind == IR::ExportTargetKind::Mrt &&
inst.export_info.index < std::size(state.input_info.pixel->target_output_mode) &&
state.input_info.pixel->target_output_mode[inst.export_info.index] == 7u;
}
uint32_t ApplyMrtExportMapping(EmitterState& state, const IR::Instruction& inst, uint32_t value,
uint32_t vector_type) {
if (inst.export_info.kind != IR::ExportTargetKind::Mrt || state.pixel_input_info == nullptr ||
inst.export_info.index >= state.pixel_input_info->target_export_mapping.size()) {
if (state.stage != ShaderType::Pixel || inst.export_info.kind != IR::ExportTargetKind::Mrt ||
inst.export_info.index >= state.input_info.pixel->target_export_mapping.size()) {
return value;
}
const auto mapping = state.pixel_input_info->target_export_mapping[inst.export_info.index];
const auto mapping = state.input_info.pixel->target_export_mapping[inst.export_info.index];
if (mapping.IsIdentity()) {
return value;
}
@@ -317,17 +317,16 @@ struct StorageImageDescriptors {
};
struct EmitterState {
EmitterState(const IR::Program& program_, const IR::ResourceSnapshot& resources_)
: program(program_), resources(resources_) {}
EmitterState(const IR::Program& program_, const IR::ResourceSnapshot& resources_,
ShaderStageInputInfo input_info_)
: program(program_), resources(resources_), input_info(input_info_) {}
Builder builder;
const IR::Program& program;
const IR::ResourceSnapshot& resources;
const ShaderVertexInputInfo* vertex_input_info = nullptr;
const ShaderPixelInputInfo* pixel_input_info = nullptr;
const ShaderComputeInputInfo* compute_input_info = nullptr;
ShaderType stage = ShaderType::Unknown;
uint32_t wave_size = 64;
ShaderStageInputInfo input_info;
ShaderType stage = ShaderType::Unknown;
uint32_t wave_size = 64;
bool exact_subgroup_operations = false;
bool per_invocation_masks = false;
uint32_t void_type = 0;
@@ -496,7 +496,7 @@ uint32_t EmitLdsElementPointer(EmitterState& state, uint32_t index) {
}
uint32_t LdsDwordCount(const EmitterState& state) {
return state.needs_function_lds ? 8192u : state.compute_input_info->lds_size_dwords;
return state.stage == ShaderType::Compute ? state.input_info.compute->lds_size_dwords : 8192u;
}
uint32_t EmitLdsElementInBounds(EmitterState& state, uint32_t index) {
@@ -59,13 +59,12 @@ uint32_t ConstantF32Value(EmitterState& state, float value) {
}
VertexInputScalarKind VertexParameterScalarKind(const EmitterState& state, uint32_t location) {
if (state.stage != ShaderType::Vertex || state.vertex_input_info == nullptr ||
location >= ShaderVertexInputInfo::RES_MAX ||
location >= static_cast<uint32_t>(state.vertex_input_info->resources_num)) {
if (state.stage != ShaderType::Vertex || location >= ShaderVertexInputInfo::RES_MAX ||
location >= static_cast<uint32_t>(state.input_info.vertex->resources_num)) {
return VertexInputScalarKind::Float;
}
switch (state.vertex_input_info->resources[location].Format()) {
switch (state.input_info.vertex->resources[location].Format()) {
case Prospero::BufferFormat::k8UInt:
case Prospero::BufferFormat::k16UInt:
case Prospero::BufferFormat::k8_8UInt:
@@ -92,12 +91,11 @@ VertexInputScalarKind VertexParameterScalarKind(const EmitterState& state, uint3
uint32_t VertexParameterComponentCount(const EmitterState& state, const InputBinding& input) {
uint32_t count = input.component_count;
if (state.stage == ShaderType::Vertex && state.vertex_input_info != nullptr &&
input.location < ShaderVertexInputInfo::RES_MAX &&
input.location < static_cast<uint32_t>(state.vertex_input_info->resources_num) &&
state.vertex_input_info->resources_dst[input.location].registers_num > 0) {
if (state.stage == ShaderType::Vertex && input.location < ShaderVertexInputInfo::RES_MAX &&
input.location < static_cast<uint32_t>(state.input_info.vertex->resources_num) &&
state.input_info.vertex->resources_dst[input.location].registers_num > 0) {
count = static_cast<uint32_t>(
state.vertex_input_info->resources_dst[input.location].registers_num);
state.input_info.vertex->resources_dst[input.location].registers_num);
}
return std::clamp(count, 1u, 4u);
}
@@ -177,9 +175,9 @@ uint32_t VertexParameterInputPointerType(const EmitterState& state, VertexInputS
}
static bool MrtUsesUintOutput(const EmitterState& state, uint32_t index) {
return state.stage == ShaderType::Pixel && state.pixel_input_info != nullptr &&
index < std::size(state.pixel_input_info->target_output_mode) &&
state.pixel_input_info->target_output_mode[index] == 7u;
return state.stage == ShaderType::Pixel &&
index < std::size(state.input_info.pixel->target_output_mode) &&
state.input_info.pixel->target_output_mode[index] == 7u;
}
void AllocateInputVariables(EmitterState& state) {
@@ -260,8 +258,8 @@ void AddInputAnnotationsAndNames(EmitterState& state) {
if (flat) {
state.builder.AddAnnotation({OpDecorate, input.variable_id, DecorationFlat});
}
if (state.stage == ShaderType::Pixel && state.pixel_input_info != nullptr &&
state.pixel_input_info->ps_no_perspective && !flat) {
if (state.stage == ShaderType::Pixel && state.input_info.pixel->ps_no_perspective &&
!flat) {
state.builder.AddAnnotation(
{OpDecorate, input.variable_id, DecorationNoPerspective});
}
@@ -521,15 +519,13 @@ void EmitHeaderAndTypes(EmitterState& state) {
// contract prevents host compilers from treating synthesized IEEE values as finite.
state.builder.AddExecutionMode({state.main_func, ExecutionModeSignedZeroInfNanPreserve, 32u});
if (state.stage == ShaderType::Compute) {
uint32_t local_x = state.needs_compute_derivatives ? 2u : 1u;
uint32_t local_y = state.needs_compute_derivatives ? 2u : 1u;
uint32_t local_z = 1u;
if (state.compute_input_info != nullptr) {
const auto* cs = state.compute_input_info;
local_x = cs->threads_num[0] != 0u ? cs->threads_num[0] : local_x;
local_y = cs->threads_num[1] != 0u ? cs->threads_num[1] : local_y;
local_z = cs->threads_num[2] != 0u ? cs->threads_num[2] : local_z;
}
uint32_t local_x = state.needs_compute_derivatives ? 2u : 1u;
uint32_t local_y = state.needs_compute_derivatives ? 2u : 1u;
uint32_t local_z = 1u;
const auto* cs = state.input_info.compute;
local_x = cs->threads_num[0] != 0u ? cs->threads_num[0] : local_x;
local_y = cs->threads_num[1] != 0u ? cs->threads_num[1] : local_y;
local_z = cs->threads_num[2] != 0u ? cs->threads_num[2] : local_z;
state.builder.AddExecutionMode(
{state.main_func, ExecutionModeLocalSize, local_x, local_y, local_z});
}
@@ -538,10 +534,9 @@ void EmitHeaderAndTypes(EmitterState& state) {
if (state.depth_variable != 0) {
state.builder.AddExecutionMode({state.main_func, ExecutionModeDepthReplacing});
}
if (state.pixel_input_info != nullptr && state.pixel_input_info->ps_early_z &&
!state.pixel_input_info->ps_pixel_kill_enable &&
!state.pixel_input_info->ps_depth_export_enable &&
!state.pixel_input_info->ps_sample_mask_export_enable) {
if (state.input_info.pixel->ps_early_z && !state.input_info.pixel->ps_pixel_kill_enable &&
!state.input_info.pixel->ps_depth_export_enable &&
!state.input_info.pixel->ps_sample_mask_export_enable) {
state.builder.AddExecutionMode({state.main_func, ExecutionModeEarlyFragmentTests});
}
}
@@ -159,9 +159,9 @@ uint32_t EmitAttribute(ValueEmitContext& ctx, uint32_t attr, uint32_t chan) {
}
bool MrtUsesUint(const EmitterState& state, const IR::ExportInfo& exp) {
return exp.kind == IR::ExportTargetKind::Mrt && state.pixel_input_info != nullptr &&
exp.index < std::size(state.pixel_input_info->target_output_mode) &&
state.pixel_input_info->target_output_mode[exp.index] == 7u;
return state.stage == ShaderType::Pixel && exp.kind == IR::ExportTargetKind::Mrt &&
exp.index < std::size(state.input_info.pixel->target_output_mode) &&
state.input_info.pixel->target_output_mode[exp.index] == 7u;
}
uint32_t ExportRawComponent(ValueEmitContext& ctx, uint32_t vector, uint32_t component) {
@@ -289,9 +289,9 @@ void EmitExport(ValueEmitContext& ctx, const IR::Inst& inst) {
const bool uint_output = MrtUsesUint(state, exp);
const auto vector_type = uint_output ? state.vec4_uint_type : state.vec4_float_type;
auto value = ExportVector(ctx, data, exp, uint_output);
if (exp.kind == IR::ExportTargetKind::Mrt && state.pixel_input_info != nullptr &&
exp.index < state.pixel_input_info->target_export_mapping.size()) {
const auto mapping = state.pixel_input_info->target_export_mapping[exp.index];
if (state.stage == ShaderType::Pixel && exp.kind == IR::ExportTargetKind::Mrt &&
exp.index < state.input_info.pixel->target_export_mapping.size()) {
const auto mapping = state.input_info.pixel->target_export_mapping[exp.index];
if (!mapping.IsIdentity()) {
const auto mapped = state.builder.AllocateId();
state.builder.AddFunction({OpVectorShuffle, vector_type, mapped, value, value,
@@ -863,7 +863,7 @@ bool TranslateProgram(const IR::Program& source, IR::ValueProgram& result,
prologue.SetVccLo(IR::U32(IR::Value(0u)));
prologue.SetVccHi(IR::U32(IR::Value(0u)));
prologue.SetM0(IR::U32(IR::Value(0u)));
if (source.stage == ShaderType::Compute && compute_input_info != nullptr) {
if (source.stage == ShaderType::Compute) {
const auto* cs = compute_input_info;
const auto thread_ids =
cs->thread_ids_num > 0 ? std::min<uint32_t>(cs->thread_ids_num, 3u) : 0u;
@@ -897,7 +897,7 @@ bool TranslateProgram(const IR::Program& source, IR::ValueProgram& result,
prologue.BitwiseOr(prologue.BitwiseOr(wave_bits, IR::U32(IR::Value(waves))),
first_bit));
}
} else if (source.stage == ShaderType::Pixel && pixel_input_info != nullptr) {
} else if (source.stage == ShaderType::Pixel) {
const auto* ps = pixel_input_info;
uint32_t reg = ps->ps_system_input_base;
if (ps->ps_pos_x) {
@@ -920,7 +920,7 @@ bool TranslateProgram(const IR::Program& source, IR::ValueProgram& result,
prologue.SetVectorReg(static_cast<IR::VectorReg>(reg),
builtin(IR::StageInputKind::FrontFacing));
}
} else if (source.stage == ShaderType::Vertex && vertex_input_info != nullptr) {
} else if (source.stage == ShaderType::Vertex) {
prologue.SetVectorReg(static_cast<IR::VectorReg>(5),
builtin(IR::StageInputKind::VertexIndex));
prologue.SetVectorReg(static_cast<IR::VectorReg>(8),
@@ -42,24 +42,15 @@ bool ValidateOptions(const Program& program, const ShaderInfoOptions& options, s
};
switch (program.stage) {
case ShaderType::Vertex:
if (options.vertex == nullptr) {
return Fail("vertex shader info requires vertex metadata");
}
if (options.vertex->resources_num < 0 ||
options.vertex->resources_num > ShaderVertexInputInfo::RES_MAX) {
return Fail("vertex resource count is out of range");
}
return true;
case ShaderType::Pixel:
if (options.pixel == nullptr) {
return Fail("pixel shader info requires pixel metadata");
}
return options.pixel->input_num <= std::size(options.pixel->interpolator_settings) ||
Fail("pixel input count is out of range");
case ShaderType::Compute:
if (options.compute == nullptr) {
return Fail("compute shader info requires compute metadata");
}
return (options.compute->thread_ids_num >= 0 && options.compute->thread_ids_num <= 3) ||
Fail("compute thread ID count is out of range");
default: return Fail("unsupported shader stage for info collection");
@@ -83,7 +74,7 @@ bool ValidateValueReferences(const Program& program, const ShaderInfoOptions& op
return Fail("typed attribute reference is not constant");
}
if (program.stage == ShaderType::Vertex &&
(inst.Arg(1).U32() >= 4u || options.vertex == nullptr ||
(inst.Arg(1).U32() >= 4u ||
inst.Arg(0).U32() >=
static_cast<uint32_t>(options.vertex->resources_num))) {
return Fail("vertex input reference is out of range");
@@ -139,9 +130,6 @@ void CollectVertexInputs(const Program& program, const ShaderVertexInputInfo* ve
ShaderInfo& info) {
AddInput(info, StageInputKind::VertexIndex, 0, 1, "gl_VertexIndex");
AddInput(info, StageInputKind::InstanceIndex, 0, 1, "gl_InstanceIndex");
if (vertex == nullptr) {
return;
}
uint32_t used_components[ShaderVertexInputInfo::RES_MAX] = {};
for (const auto* block: program.values->blocks) {
for (const auto& inst: *block) {
@@ -163,9 +151,6 @@ void CollectVertexInputs(const Program& program, const ShaderVertexInputInfo* ve
}
void CollectPixelInputs(const ShaderPixelInputInfo* pixel, ShaderInfo& info) {
if (pixel == nullptr) {
return;
}
if (pixel->HasPositionInput()) {
AddInput(info, StageInputKind::FragCoord, 0, 4, "gl_FragCoord");
}
@@ -178,19 +163,17 @@ void CollectPixelInputs(const ShaderPixelInputInfo* pixel, ShaderInfo& info) {
}
void CollectComputeInputs(const ShaderComputeInputInfo* compute, ShaderInfo& info) {
if (compute != nullptr) {
if (compute->group_id[0] || compute->group_id[1] || compute->group_id[2]) {
AddInput(info, StageInputKind::WorkgroupId, 0, 3, "gl_WorkGroupID");
}
if (compute->thread_ids_num > 0) {
AddInput(info, StageInputKind::LocalInvocationId, 0, 3, "gl_LocalInvocationID");
}
if (compute->thread_ids_num > 0 || compute->tg_size_en) {
AddInput(info, StageInputKind::LocalInvocationIndex, 0, 1, "gl_LocalInvocationIndex");
}
if (compute->dispatch_thread_dimensions) {
AddInput(info, StageInputKind::GlobalInvocationId, 0, 3, "gl_GlobalInvocationID");
}
if (compute->group_id[0] || compute->group_id[1] || compute->group_id[2]) {
AddInput(info, StageInputKind::WorkgroupId, 0, 3, "gl_WorkGroupID");
}
if (compute->thread_ids_num > 0) {
AddInput(info, StageInputKind::LocalInvocationId, 0, 3, "gl_LocalInvocationID");
}
if (compute->thread_ids_num > 0 || compute->tg_size_en) {
AddInput(info, StageInputKind::LocalInvocationIndex, 0, 1, "gl_LocalInvocationIndex");
}
if (compute->dispatch_thread_dimensions) {
AddInput(info, StageInputKind::GlobalInvocationId, 0, 3, "gl_GlobalInvocationID");
}
}
@@ -238,11 +221,11 @@ void CollectOutputs(const Program& program, const ShaderPixelInputInfo* pixel, S
}
const auto& export_info = program.values->export_info[inst.Flags<ExportFlags>().index];
if (export_info.kind == ExportTargetKind::MrtZ) {
if (pixel != nullptr && (export_info.en & 0x1u) != 0 &&
if (program.stage == ShaderType::Pixel && (export_info.en & 0x1u) != 0 &&
pixel->ps_depth_export_enable) {
AddOutput(info, StageOutputKind::Depth, 0, 0, "gl_FragDepth");
}
if (pixel != nullptr && (export_info.en & 0x4u) != 0 &&
if (program.stage == ShaderType::Pixel && (export_info.en & 0x4u) != 0 &&
pixel->ps_sample_mask_export_enable) {
AddOutput(info, StageOutputKind::SampleMask, 0, 0, "gl_SampleMask");
}
+3 -3
View File
@@ -1455,7 +1455,7 @@ bool ShaderCompileSpirvVS(const HW::VertexShaderInfo& regs, const HW::ShaderRegi
options.read_specialization_memory = ReadShaderGuestMemory;
options.descriptor_set = 0;
options.push_constant_offset = 0;
options.vertex_input_info = &input_info;
options.input_info.vertex = &input_info;
options.dump_ir = ShaderRecompilerTextDumpEnabled();
options.early_dump = options.dump_ir;
options.dump_label = "ShaderRecompiler VS";
@@ -1509,7 +1509,7 @@ bool ShaderCompileSpirvPS(const HW::PixelShaderInfo& regs, const HW::ShaderRegis
options.read_specialization_memory = ReadShaderGuestMemory;
options.descriptor_set = input_info.descriptor_set;
options.push_constant_offset = input_info.push_constant_offset;
options.pixel_input_info = &input_info;
options.input_info.pixel = &input_info;
options.dump_ir = ShaderRecompilerTextDumpEnabled();
options.early_dump = options.dump_ir;
options.dump_label = "ShaderRecompiler PS";
@@ -1559,7 +1559,7 @@ bool ShaderCompileSpirvCS(const HW::ComputeShaderInfo& regs, const HW::ShaderReg
options.read_specialization_memory = ReadShaderGuestMemory;
options.descriptor_set = 0;
options.push_constant_offset = 0;
options.compute_input_info = &input_info;
options.input_info.compute = &input_info;
options.wave_size = input_info.wave_size;
options.dump_ir = ShaderRecompilerTextDumpEnabled();
options.early_dump = options.dump_ir;
+6
View File
@@ -128,6 +128,12 @@ struct ShaderPixelInputInfo {
bool HasPositionInput() const { return ps_pos_x || ps_pos_y || ps_pos_z || ps_pos_w; }
};
union ShaderStageInputInfo {
const ShaderVertexInputInfo* vertex;
const ShaderPixelInputInfo* pixel;
const ShaderComputeInputInfo* compute = nullptr;
};
uint32_t ShaderPixelParameterMappedLocation(const ShaderPixelInputInfo& info, uint32_t input);
uint32_t ShaderPixelParameterLocation(const ShaderPixelInputInfo& info,
std::span<const uint32_t> active_inputs, uint32_t input);
+8 -9
View File
@@ -1065,7 +1065,7 @@ CompiledShader CompileCase(const TestCase &test) {
ShaderRecompiler::CompileOptions options;
options.stage = ShaderType::Compute;
options.dump_ir = true;
options.compute_input_info = &test.compute_info;
options.input_info.compute = &test.compute_info;
options.user_data = user_data.data();
options.read_memory = ReadTestMemory;
options.read_memory_data = const_cast<std::vector<u32> *>(&test.initial);
@@ -1157,8 +1157,7 @@ CompiledShader CompileCase(const TestCase &test) {
"offset-only shader data did not use its storage fallback");
std::vector<u32> storage_spirv;
if (!ShaderRecompiler::Spirv::EmitProgram(
result.program, result.resources, nullptr, nullptr,
options.compute_input_info, storage_spirv, &error)) {
result.program, result.resources, options.input_info, storage_spirv, &error)) {
Fail(test.name, "SPIR-V emit", error.c_str());
}
result.spirv = std::move(storage_spirv);
@@ -1231,7 +1230,7 @@ CompiledShader CompileFragmentCase(const GraphicsCase &test) {
ShaderRecompiler::CompileOptions options;
options.stage = ShaderType::Pixel;
options.dump_ir = false;
options.pixel_input_info = &pixel_info;
options.input_info.pixel = &pixel_info;
options.user_data = user_data.data();
ShaderRecompiler::CompileResult result;
@@ -17149,8 +17148,8 @@ void CheckIndirectImageKeySwitch() {
ShaderComputeInputInfo compute{};
std::vector<u32> spirv;
Require(name, "SPIR-V emit",
ShaderRecompiler::Spirv::EmitProgram(program, snapshot, nullptr,
nullptr, &compute, spirv, &error),
ShaderRecompiler::Spirv::EmitProgram(
program, snapshot, {.compute = &compute}, spirv, &error),
error.c_str());
ValidateSpirv(name, spirv);
spvtools::SpirvTools tools(SPV_ENV_VULKAN_1_2);
@@ -18035,7 +18034,7 @@ void CheckPs5GameExampleImageClearRuntimeShape() {
options.user_data_base = 0;
options.user_data_count = static_cast<u32>(user_data.size());
options.user_data = user_data.data();
options.compute_input_info = &compute;
options.input_info.compute = &compute;
options.dump_ir = false;
ShaderRecompiler::CompileResult result;
std::string error;
@@ -18136,7 +18135,7 @@ void CheckEmbeddedFetchVertexOffset() {
options.user_data_base = 8;
options.user_data_count = static_cast<u32>(user_data.size());
options.user_data = user_data.data();
options.vertex_input_info = &vertex;
options.input_info.vertex = &vertex;
ShaderRecompiler::CompileResult result;
std::string error;
@@ -20760,7 +20759,7 @@ void CheckEmbeddedFetchLaneSpill() {
options.user_data_base = 8;
options.user_data_count = static_cast<u32>(user_data.size());
options.user_data = user_data.data();
options.vertex_input_info = &vertex;
options.input_info.vertex = &vertex;
ShaderRecompiler::CompileResult result;
std::string error;
+157 -241
View File
File diff suppressed because it is too large Load Diff