mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-08-18 22:42:23 +00:00
shader: unify stage input metadata
This commit is contained in:
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user