mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-21 19:36:55 +02:00
shader: unify stage input metadata
This commit is contained in:
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user