mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-28 13:56:59 +01:00
shader: drop null checks on the stage input info pointers
This commit is contained in:
@@ -209,20 +209,20 @@ int BufferTableAttribFromOffset(uint32_t raw_offset, int dword) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Frontend::EmbeddedFetchPlan DetectEmbeddedVertexFetch(
|
Frontend::EmbeddedFetchPlan DetectEmbeddedVertexFetch(
|
||||||
const Decoder::Program& decoded, const ShaderVertexInputInfo* input_info,
|
const Decoder::Program& decoded, const ShaderVertexInputInfo& input_info,
|
||||||
uint32_t user_data_base, uint32_t user_data_count, uint32_t wave_size) {
|
uint32_t user_data_base, uint32_t user_data_count, uint32_t wave_size) {
|
||||||
const uint32_t vertex_index_reg = input_info->logical_stage == ShaderType::Local ? 2u : 5u;
|
const uint32_t vertex_index_reg = input_info.logical_stage == ShaderType::Local ? 2u : 5u;
|
||||||
const uint32_t instance_index_reg = input_info->logical_stage == ShaderType::Local ? 5u : 8u;
|
const uint32_t instance_index_reg = input_info.logical_stage == ShaderType::Local ? 5u : 8u;
|
||||||
Frontend::EmbeddedFetchPlan data;
|
Frontend::EmbeddedFetchPlan data;
|
||||||
data.loads.reserve(input_info->resources_num);
|
data.loads.reserve(input_info.resources_num);
|
||||||
int32_t vertex_offset_candidate = -1;
|
int32_t vertex_offset_candidate = -1;
|
||||||
int32_t instance_offset_candidate = -1;
|
int32_t instance_offset_candidate = -1;
|
||||||
bool vertex_offset_conflict = false;
|
bool vertex_offset_conflict = false;
|
||||||
bool instance_offset_conflict = false;
|
bool instance_offset_conflict = false;
|
||||||
|
|
||||||
const int shift_regs = 8;
|
const int shift_regs = 8;
|
||||||
const int attrib_reg = input_info->fetch_attrib_reg + shift_regs;
|
const int attrib_reg = input_info.fetch_attrib_reg + shift_regs;
|
||||||
const int buffer_reg = input_info->fetch_buffer_reg + shift_regs;
|
const int buffer_reg = input_info.fetch_buffer_reg + shift_regs;
|
||||||
|
|
||||||
std::array<EmbeddedFetchSgprInfo, 108> sgprs {};
|
std::array<EmbeddedFetchSgprInfo, 108> sgprs {};
|
||||||
std::array<bool, 256> vgpr_is_index {};
|
std::array<bool, 256> vgpr_is_index {};
|
||||||
@@ -488,7 +488,6 @@ void PrepareCallTargets(ShaderSource& source, const CompileOptions& options) {
|
|||||||
if (source.decoded.instructions[i].opcode != Decoder::Opcode::S_SWAPPC_B64) continue;
|
if (source.decoded.instructions[i].opcode != Decoder::Opcode::S_SWAPPC_B64) continue;
|
||||||
source.calls.push_back({.instruction = i});
|
source.calls.push_back({.instruction = i});
|
||||||
}
|
}
|
||||||
EXIT_IF(options.input_info.compute == nullptr);
|
|
||||||
const auto graph = CFG::BuildGraph(source.decoded);
|
const auto graph = CFG::BuildGraph(source.decoded);
|
||||||
Program query;
|
Program query;
|
||||||
query.stage = options.stage;
|
query.stage = options.stage;
|
||||||
@@ -809,9 +808,9 @@ TranslateResult TranslateProgram(const Decoder::Program& decoded, const CompileO
|
|||||||
const auto& cfg = *selected_cfg;
|
const auto& cfg = *selected_cfg;
|
||||||
Frontend::EmbeddedFetchPlan embedded_fetch;
|
Frontend::EmbeddedFetchPlan embedded_fetch;
|
||||||
if ((options.stage == ShaderType::Vertex || options.stage == ShaderType::Local) &&
|
if ((options.stage == ShaderType::Vertex || options.stage == ShaderType::Local) &&
|
||||||
options.input_info.vertex != nullptr && options.input_info.vertex->fetch_embedded) {
|
options.input_info.vertex->fetch_embedded) {
|
||||||
embedded_fetch = DetectEmbeddedVertexFetch(
|
embedded_fetch = DetectEmbeddedVertexFetch(
|
||||||
decoded, options.input_info.vertex, options.user_data_base,
|
decoded, *options.input_info.vertex, options.user_data_base,
|
||||||
static_cast<uint32_t>(options.user_data.size()), options.wave_size);
|
static_cast<uint32_t>(options.user_data.size()), options.wave_size);
|
||||||
if (!embedded_fetch.loads.empty()) {
|
if (!embedded_fetch.loads.empty()) {
|
||||||
LOGF("%s embedded vertex fetch plan: detected=%" PRIu64 "\n", GetDumpLabel(options),
|
LOGF("%s embedded vertex fetch plan: detected=%" PRIu64 "\n", GetDumpLabel(options),
|
||||||
|
|||||||
@@ -233,8 +233,8 @@ std::vector<uint32_t> EmitProgram(IR::Program& program, ShaderStageInputInfo inp
|
|||||||
? 2u
|
? 2u
|
||||||
: 1u;
|
: 1u;
|
||||||
DefineModule(state);
|
DefineModule(state);
|
||||||
ValidateNativeProgram(program, program.stage == ShaderType::Compute &&
|
ValidateNativeProgram(program,
|
||||||
input_info.compute != nullptr && input_info.compute->lds_storage);
|
program.stage == ShaderType::Compute && input_info.compute->lds_storage);
|
||||||
EmitProgram(state);
|
EmitProgram(state);
|
||||||
state.builder.AddEntryPoint(ExecutionModelForStage(state.program.stage), state.main_func,
|
state.builder.AddEntryPoint(ExecutionModelForStage(state.program.stage), state.main_func,
|
||||||
"main", state.interface_variables);
|
"main", state.interface_variables);
|
||||||
|
|||||||
@@ -53,8 +53,7 @@ uint32_t EmitBuiltinU32(EmitterState& state, IR::StageInputKind kind, uint32_t c
|
|||||||
const auto bits = state.builder.AllocateId();
|
const auto bits = state.builder.AllocateId();
|
||||||
state.builder.AddFunction(spv::OpLoad, TypeBool(state), value, variable);
|
state.builder.AddFunction(spv::OpLoad, TypeBool(state), value, variable);
|
||||||
// SPI_BARYC_CNTL.FRONT_FACE_ALL_BITS selects uint masks or float +/-1.
|
// SPI_BARYC_CNTL.FRONT_FACE_ALL_BITS selects uint masks or float +/-1.
|
||||||
const bool all_bits =
|
const bool all_bits = state.input_info.pixel->ps_front_face_all_bits;
|
||||||
state.input_info.pixel != nullptr && state.input_info.pixel->ps_front_face_all_bits;
|
|
||||||
const auto front = ConstantU32(state, all_bits ? 0xffffffffu : 0x3f800000u);
|
const auto front = ConstantU32(state, all_bits ? 0xffffffffu : 0x3f800000u);
|
||||||
const auto back = ConstantU32(state, all_bits ? 0u : 0xbf800000u);
|
const auto back = ConstantU32(state, all_bits ? 0u : 0xbf800000u);
|
||||||
state.builder.AddFunction(spv::OpSelect, TypeU32(state), bits, value, front, back);
|
state.builder.AddFunction(spv::OpSelect, TypeU32(state), bits, value, front, back);
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ struct EmitterState {
|
|||||||
lds_storage_class = spv::StorageClassWorkgroup;
|
lds_storage_class = spv::StorageClassWorkgroup;
|
||||||
}
|
}
|
||||||
if (program.info.uses_lds && program.stage == ShaderType::Compute &&
|
if (program.info.uses_lds && program.stage == ShaderType::Compute &&
|
||||||
input_info.compute != nullptr && input_info.compute->lds_storage) {
|
input_info.compute->lds_storage) {
|
||||||
lds_storage_class = spv::StorageClassStorageBuffer;
|
lds_storage_class = spv::StorageClassStorageBuffer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -169,10 +169,10 @@ uint32_t LdsDwordCount(const EmitterState& state) {
|
|||||||
if (const auto* workgroup = ShaderWorkgroupInput(state.program.stage, state.input_info)) {
|
if (const auto* workgroup = ShaderWorkgroupInput(state.program.stage, state.input_info)) {
|
||||||
return workgroup->lds_size_dwords;
|
return workgroup->lds_size_dwords;
|
||||||
}
|
}
|
||||||
if (state.program.stage == ShaderType::Pixel && state.input_info.pixel != nullptr) {
|
if (state.program.stage == ShaderType::Pixel) {
|
||||||
return std::max(state.input_info.pixel->lds_size_dwords, 1u);
|
return std::max(state.input_info.pixel->lds_size_dwords, 1u);
|
||||||
}
|
}
|
||||||
if (state.program.stage == ShaderType::Vertex && state.input_info.vertex != nullptr) {
|
if (state.program.stage == ShaderType::Vertex) {
|
||||||
return std::max(state.input_info.vertex->lds_size_dwords, 1u);
|
return std::max(state.input_info.vertex->lds_size_dwords, 1u);
|
||||||
}
|
}
|
||||||
return FUNCTION_LDS_DWORDS;
|
return FUNCTION_LDS_DWORDS;
|
||||||
|
|||||||
@@ -987,30 +987,6 @@ void ValidateTranslateOptions(const TranslateOptions& options) {
|
|||||||
options.stage != ShaderType::Local) {
|
options.stage != ShaderType::Local) {
|
||||||
EXIT("embedded fetch requires a vertex or local shader");
|
EXIT("embedded fetch requires a vertex or local shader");
|
||||||
}
|
}
|
||||||
switch (options.stage) {
|
|
||||||
case ShaderType::Vertex:
|
|
||||||
case ShaderType::Local:
|
|
||||||
case ShaderType::TessellationControl:
|
|
||||||
case ShaderType::TessellationEvaluation:
|
|
||||||
case ShaderType::Mesh:
|
|
||||||
if (options.input_info.vertex == nullptr) {
|
|
||||||
EXIT("vertex shader translation has no vertex input metadata");
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
case ShaderType::Pixel:
|
|
||||||
if (options.input_info.pixel == nullptr) {
|
|
||||||
EXIT("pixel shader translation has no pixel input metadata");
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
case ShaderType::Compute:
|
|
||||||
if (options.input_info.compute == nullptr) {
|
|
||||||
EXIT("compute shader translation has no compute input metadata");
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
default:
|
|
||||||
EXIT("shader translation has unsupported stage %u",
|
|
||||||
static_cast<uint32_t>(options.stage));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
@@ -1044,7 +1020,9 @@ IR::Program TranslateProgram(const Decoder::Program& decoded, const CFG::Graph&
|
|||||||
case ShaderType::Compute:
|
case ShaderType::Compute:
|
||||||
result.scratch_dwords = options.input_info.compute->scratch_size_dwords;
|
result.scratch_dwords = options.input_info.compute->scratch_size_dwords;
|
||||||
break;
|
break;
|
||||||
default: break; // ValidateTranslateOptions rejects unsupported stages.
|
default:
|
||||||
|
EXIT("shader translation has unsupported stage %u",
|
||||||
|
static_cast<uint32_t>(options.stage));
|
||||||
}
|
}
|
||||||
result.dispatcher_fallback = cfg.irreducible || cfg.unsupported;
|
result.dispatcher_fallback = cfg.irreducible || cfg.unsupported;
|
||||||
result.cfg_failure_kind = cfg.failure_kind;
|
result.cfg_failure_kind = cfg.failure_kind;
|
||||||
|
|||||||
@@ -362,8 +362,7 @@ class Tracker {
|
|||||||
public:
|
public:
|
||||||
Tracker(Program& program, const Decoder::Program& decoded, const CFG::Graph& native_cfg,
|
Tracker(Program& program, const Decoder::Program& decoded, const CFG::Graph& native_cfg,
|
||||||
ShaderStageInputInfo input)
|
ShaderStageInputInfo input)
|
||||||
: m_program(program), m_decoded(decoded), m_native_cfg(native_cfg),
|
: m_program(program), m_decoded(decoded), m_native_cfg(native_cfg), m_input(input),
|
||||||
m_workgroup(program.stage == ShaderType::Compute ? input.compute : nullptr),
|
|
||||||
m_scalar_writes(std::move(program.scalar_writes)), m_info(program.info) {
|
m_scalar_writes(std::move(program.scalar_writes)), m_info(program.info) {
|
||||||
std::ranges::sort(m_scalar_writes, {}, &Program::ScalarWrite::pc);
|
std::ranges::sort(m_scalar_writes, {}, &Program::ScalarWrite::pc);
|
||||||
m_info.buffers.clear();
|
m_info.buffers.clear();
|
||||||
@@ -1853,7 +1852,7 @@ private:
|
|||||||
if (inst->GetOpcode() == ValueOpcode::GetBuiltin &&
|
if (inst->GetOpcode() == ValueOpcode::GetBuiltin &&
|
||||||
inst->Arg(0) == Value(static_cast<uint32_t>(StageInputKind::LocalInvocationId)) &&
|
inst->Arg(0) == Value(static_cast<uint32_t>(StageInputKind::LocalInvocationId)) &&
|
||||||
ImmediateU32(inst->Arg(1), axis) && axis < 3u &&
|
ImmediateU32(inst->Arg(1), axis) && axis < 3u &&
|
||||||
m_workgroup->threads_num[axis] <= (uint64_t {1} << bits)) return axis + 1u;
|
m_input.compute->threads_num[axis] <= (uint64_t {1} << bits)) return axis + 1u;
|
||||||
if (!allow_induction || inst->GetOpcode() != ValueOpcode::Phi ||
|
if (!allow_induction || inst->GetOpcode() != ValueOpcode::Phi ||
|
||||||
(!induction.IsEmpty() && induction != at)) return {};
|
(!induction.IsEmpty() && induction != at)) return {};
|
||||||
induction = at;
|
induction = at;
|
||||||
@@ -1864,20 +1863,20 @@ private:
|
|||||||
bool LinearLocalIndex(const std::array<uint64_t, 5>& index) const {
|
bool LinearLocalIndex(const std::array<uint64_t, 5>& index) const {
|
||||||
uint64_t stride = 1u;
|
uint64_t stride = 1u;
|
||||||
for (uint32_t axis = 0; axis < 3u; ++axis) {
|
for (uint32_t axis = 0; axis < 3u; ++axis) {
|
||||||
if (m_workgroup->threads_num[axis] != 1u && index[axis + 1u] != stride) return false;
|
if (m_input.compute->threads_num[axis] != 1u && index[axis + 1u] != stride) return false;
|
||||||
stride *= m_workgroup->threads_num[axis];
|
stride *= m_input.compute->threads_num[axis];
|
||||||
}
|
}
|
||||||
return index[0] == 0u;
|
return index[0] == 0u;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ForwardPrivateLds() {
|
void ForwardPrivateLds() {
|
||||||
if (m_workgroup == nullptr) return;
|
if (m_program.stage != ShaderType::Compute) return;
|
||||||
uint64_t bytes = 4u;
|
uint64_t bytes = 4u;
|
||||||
for (const auto size: m_workgroup->threads_num) {
|
for (const auto size: m_input.compute->threads_num) {
|
||||||
if (size == 0u || size > 1024u) return;
|
if (size == 0u || size > 1024u) return;
|
||||||
bytes *= size;
|
bytes *= size;
|
||||||
}
|
}
|
||||||
if (bytes > uint64_t {m_workgroup->lds_size_dwords} * 4u) return;
|
if (bytes > uint64_t {m_input.compute->lds_size_dwords} * 4u) return;
|
||||||
struct Access { Inst* inst; uint32_t offset; };
|
struct Access { Inst* inst; uint32_t offset; };
|
||||||
std::vector<Access> reads, writes;
|
std::vector<Access> reads, writes;
|
||||||
Value address;
|
Value address;
|
||||||
@@ -1893,7 +1892,7 @@ private:
|
|||||||
if ((op != ValueOpcode::LoadSharedU32 && op != ValueOpcode::WriteSharedU32) ||
|
if ((op != ValueOpcode::LoadSharedU32 && op != ValueOpcode::WriteSharedU32) ||
|
||||||
memory.data_bits != 32u || memory.secondary_offset != 0u ||
|
memory.data_bits != 32u || memory.secondary_offset != 0u ||
|
||||||
(memory.offset & 3u) != 0u ||
|
(memory.offset & 3u) != 0u ||
|
||||||
uint64_t {memory.offset} + bytes > uint64_t {m_workgroup->lds_size_dwords} * 4u)
|
uint64_t {memory.offset} + bytes > uint64_t {m_input.compute->lds_size_dwords} * 4u)
|
||||||
return;
|
return;
|
||||||
if (address.IsEmpty()) address = inst.Arg(0).Resolve();
|
if (address.IsEmpty()) address = inst.Arg(0).Resolve();
|
||||||
else if (!EquivalentValue(m_program, address, inst.Arg(0))) return;
|
else if (!EquivalentValue(m_program, address, inst.Arg(0))) return;
|
||||||
@@ -2039,16 +2038,16 @@ private:
|
|||||||
Value SharedLoadBound(Value value, Value active) {
|
Value SharedLoadBound(Value value, Value active) {
|
||||||
const auto* read = ActiveValue(value, active).TryInstruction();
|
const auto* read = ActiveValue(value, active).TryInstruction();
|
||||||
if (read == nullptr || read->GetOpcode() != ValueOpcode::LoadSharedU32 ||
|
if (read == nullptr || read->GetOpcode() != ValueOpcode::LoadSharedU32 ||
|
||||||
m_workgroup == nullptr || m_program.stage != ShaderType::Compute ||
|
m_program.stage != ShaderType::Compute ||
|
||||||
read->Arg(1).Resolve() != Value(true)) return {};
|
read->Arg(1).Resolve() != Value(true)) return {};
|
||||||
uint64_t group_size = 1u;
|
uint64_t group_size = 1u;
|
||||||
for (const auto dimension: m_workgroup->threads_num) {
|
for (const auto dimension: m_input.compute->threads_num) {
|
||||||
if (dimension == 0u || dimension > m_workgroup->wave_size) return {};
|
if (dimension == 0u || dimension > m_input.compute->wave_size) return {};
|
||||||
group_size *= dimension;
|
group_size *= dimension;
|
||||||
}
|
}
|
||||||
// Indexed LDS operations within one native wave execute in order. Multiwave
|
// Indexed LDS operations within one native wave execute in order. Multiwave
|
||||||
// append lists require a separate workgroup synchronization proof.
|
// append lists require a separate workgroup synchronization proof.
|
||||||
if (group_size != m_workgroup->wave_size || group_size != m_program.wave_size ||
|
if (group_size != m_input.compute->wave_size || group_size != m_program.wave_size ||
|
||||||
(group_size != 32u && group_size != 64u)) return {};
|
(group_size != 32u && group_size != 64u)) return {};
|
||||||
const auto memory = [&](const Inst& inst) -> const MemoryInfo* {
|
const auto memory = [&](const Inst& inst) -> const MemoryInfo* {
|
||||||
const auto index = inst.Flags<MemoryFlags>().index;
|
const auto index = inst.Flags<MemoryFlags>().index;
|
||||||
@@ -2101,7 +2100,7 @@ private:
|
|||||||
if (op != ValueOpcode::SharedAtomicIAdd32 ||
|
if (op != ValueOpcode::SharedAtomicIAdd32 ||
|
||||||
ActiveValue(inst.Arg(1), guard) != Value(1u) ||
|
ActiveValue(inst.Arg(1), guard) != Value(1u) ||
|
||||||
!constant_address(inst, address) ||
|
!constant_address(inst, address) ||
|
||||||
uint64_t {address} + 4u > uint64_t {m_workgroup->lds_size_dwords} * 4u ||
|
uint64_t {address} + 4u > uint64_t {m_input.compute->lds_size_dwords} * 4u ||
|
||||||
address >= 0x10000u ||
|
address >= 0x10000u ||
|
||||||
std::ranges::any_of(appends, [&](const Append& at) { return at.counter == address; })) return {};
|
std::ranges::any_of(appends, [&](const Append& at) { return at.counter == address; })) return {};
|
||||||
appends.push_back({.atomic = &inst, .counter = address});
|
appends.push_back({.atomic = &inst, .counter = address});
|
||||||
@@ -4059,7 +4058,7 @@ private:
|
|||||||
Program& m_program;
|
Program& m_program;
|
||||||
const Decoder::Program& m_decoded;
|
const Decoder::Program& m_decoded;
|
||||||
const CFG::Graph& m_native_cfg;
|
const CFG::Graph& m_native_cfg;
|
||||||
const ShaderWorkgroupInputInfo* m_workgroup;
|
ShaderStageInputInfo m_input;
|
||||||
std::vector<Program::ScalarWrite> m_scalar_writes;
|
std::vector<Program::ScalarWrite> m_scalar_writes;
|
||||||
std::vector<ResolvedHandle> m_resolved_handles;
|
std::vector<ResolvedHandle> m_resolved_handles;
|
||||||
std::vector<const Inst*> m_srt_visiting;
|
std::vector<const Inst*> m_srt_visiting;
|
||||||
@@ -4092,8 +4091,8 @@ UniformFillPlan RecognizePatternFill(Program& program, const Decoder::Program& d
|
|||||||
// Dispatch thread dimensions, valid in both wave sizes.
|
// Dispatch thread dimensions, valid in both wave sizes.
|
||||||
Pattern {.code_words = 38, .hash = 0xacbda1a1ccdd4198ull, .wave_size_mask = 32 | 64, .bounded = false},
|
Pattern {.code_words = 38, .hash = 0xacbda1a1ccdd4198ull, .wave_size_mask = 32 | 64, .bounded = false},
|
||||||
};
|
};
|
||||||
if (program.stage != ShaderType::Compute || input.compute == nullptr ||
|
if (program.stage != ShaderType::Compute || decoded.instructions.empty() ||
|
||||||
decoded.instructions.empty() || program.user_data_base != 0 || program.user_data_count < 10 ||
|
program.user_data_base != 0 || program.user_data_count < 10 ||
|
||||||
program.info.buffers.size() != 1 || !program.info.images.empty()) return {};
|
program.info.buffers.size() != 1 || !program.info.images.empty()) return {};
|
||||||
const auto& cs = *input.compute;
|
const auto& cs = *input.compute;
|
||||||
const bool matching_inputs = cs.workgroup_register == 10 && cs.thread_ids_num == 1 &&
|
const bool matching_inputs = cs.workgroup_register == 10 && cs.thread_ids_num == 1 &&
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ namespace Libs::Graphics::ShaderRecompiler::IR {
|
|||||||
|
|
||||||
// Resolves native descriptor sources, plans their scalar reads, and assigns dense resource bindings.
|
// Resolves native descriptor sources, plans their scalar reads, and assigns dense resource bindings.
|
||||||
void TrackResources(Program& program, const Decoder::Program& decoded, const CFG::Graph& native_cfg,
|
void TrackResources(Program& program, const Decoder::Program& decoded, const CFG::Graph& native_cfg,
|
||||||
ShaderStageInputInfo input = {});
|
ShaderStageInputInfo input);
|
||||||
|
|
||||||
} // namespace Libs::Graphics::ShaderRecompiler::IR
|
} // namespace Libs::Graphics::ShaderRecompiler::IR
|
||||||
|
|
||||||
|
|||||||
@@ -47,26 +47,17 @@ void ValidateOptions(const Program& program, ShaderStageInputInfo input_info) {
|
|||||||
case ShaderType::TessellationControl:
|
case ShaderType::TessellationControl:
|
||||||
case ShaderType::TessellationEvaluation:
|
case ShaderType::TessellationEvaluation:
|
||||||
case ShaderType::Mesh:
|
case ShaderType::Mesh:
|
||||||
if (input_info.vertex == nullptr) {
|
|
||||||
return Fail("vertex shader has no input metadata");
|
|
||||||
}
|
|
||||||
if (input_info.vertex->resources_num < 0 ||
|
if (input_info.vertex->resources_num < 0 ||
|
||||||
input_info.vertex->resources_num > ShaderVertexInputInfo::RES_MAX) {
|
input_info.vertex->resources_num > ShaderVertexInputInfo::RES_MAX) {
|
||||||
return Fail("vertex resource count is out of range");
|
return Fail("vertex resource count is out of range");
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case ShaderType::Pixel:
|
case ShaderType::Pixel:
|
||||||
if (input_info.pixel == nullptr) {
|
|
||||||
return Fail("pixel shader has no input metadata");
|
|
||||||
}
|
|
||||||
if (input_info.pixel->input_num > std::size(input_info.pixel->interpolator_settings)) {
|
if (input_info.pixel->input_num > std::size(input_info.pixel->interpolator_settings)) {
|
||||||
return Fail("pixel input count is out of range");
|
return Fail("pixel input count is out of range");
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case ShaderType::Compute:
|
case ShaderType::Compute:
|
||||||
if (input_info.compute == nullptr) {
|
|
||||||
return Fail("compute shader has no input metadata");
|
|
||||||
}
|
|
||||||
if (input_info.compute->thread_ids_num < 0 || input_info.compute->thread_ids_num > 3) {
|
if (input_info.compute->thread_ids_num < 0 || input_info.compute->thread_ids_num > 3) {
|
||||||
return Fail("compute thread ID count is out of range");
|
return Fail("compute thread ID count is out of range");
|
||||||
}
|
}
|
||||||
@@ -191,7 +182,7 @@ void AddBuiltinInput(ShaderInfo& info, StageInputKind kind) {
|
|||||||
|
|
||||||
void CollectOutput(const Program& program, ShaderStageInputInfo input_info,
|
void CollectOutput(const Program& program, ShaderStageInputInfo input_info,
|
||||||
ShaderInfo& info, const Inst& inst) {
|
ShaderInfo& info, const Inst& inst) {
|
||||||
const bool alpha_remap = program.stage == ShaderType::Pixel && input_info.pixel != nullptr &&
|
const bool alpha_remap = program.stage == ShaderType::Pixel &&
|
||||||
input_info.pixel->alpha_blend_source != ShaderAlphaBlendSource::None;
|
input_info.pixel->alpha_blend_source != ShaderAlphaBlendSource::None;
|
||||||
const auto& export_info = program.export_info[inst.Flags<ExportFlags>().index];
|
const auto& export_info = program.export_info[inst.Flags<ExportFlags>().index];
|
||||||
if (export_info.kind == ExportTargetKind::MrtZ) {
|
if (export_info.kind == ExportTargetKind::MrtZ) {
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ void CheckFatal(F &&function, std::string_view expected, const char *message) {
|
|||||||
struct Fixture {
|
struct Fixture {
|
||||||
Program program;
|
Program program;
|
||||||
Block *block = nullptr;
|
Block *block = nullptr;
|
||||||
|
ShaderComputeInputInfo compute_info{};
|
||||||
|
|
||||||
explicit Fixture(ShaderType stage = ShaderType::Compute) {
|
explicit Fixture(ShaderType stage = ShaderType::Compute) {
|
||||||
program.stage = stage;
|
program.stage = stage;
|
||||||
@@ -131,7 +132,9 @@ struct Fixture {
|
|||||||
Value(0u), Value(0u), Value(0u)});
|
Value(0u), Value(0u), Value(0u)});
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlanAndTrack(Libs::Graphics::ShaderStageInputInfo input = {}) {
|
void PlanAndTrack() { PlanAndTrack({.compute = &compute_info}); }
|
||||||
|
|
||||||
|
void PlanAndTrack(Libs::Graphics::ShaderStageInputInfo input) {
|
||||||
for (size_t index = 0; index < program.blocks.size(); ++index) {
|
for (size_t index = 0; index < program.blocks.size(); ++index) {
|
||||||
const auto condition = program.blocks[index]->condition;
|
const auto condition = program.blocks[index]->condition;
|
||||||
if (!condition.IsEmpty())
|
if (!condition.IsEmpty())
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
using namespace Libs::Graphics::ShaderRecompiler::IR;
|
using namespace Libs::Graphics::ShaderRecompiler::IR;
|
||||||
|
using Libs::Graphics::ShaderComputeInputInfo;
|
||||||
using Libs::Graphics::ShaderType;
|
using Libs::Graphics::ShaderType;
|
||||||
|
|
||||||
void Check(bool condition, const char *message) {
|
void Check(bool condition, const char *message) {
|
||||||
@@ -37,6 +38,7 @@ void CheckFatal(F &&function, std::string_view expected, const char *message) {
|
|||||||
|
|
||||||
struct Fixture {
|
struct Fixture {
|
||||||
Program program;
|
Program program;
|
||||||
|
ShaderComputeInputInfo compute{};
|
||||||
|
|
||||||
explicit Fixture(uint32_t block_count = 1) {
|
explicit Fixture(uint32_t block_count = 1) {
|
||||||
program.stage = ShaderType::Compute;
|
program.stage = ShaderType::Compute;
|
||||||
@@ -73,7 +75,7 @@ struct Fixture {
|
|||||||
return static_cast<uint32_t>(program.memory_info.size() - 1u);
|
return static_cast<uint32_t>(program.memory_info.size() - 1u);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Plan() { TrackResources(program, {}, {}); }
|
void Plan() { TrackResources(program, {}, {}, {.compute = &compute}); }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TestMemory {
|
struct TestMemory {
|
||||||
@@ -158,7 +160,7 @@ void TestScalarMemoryDomainMismatchFails() {
|
|||||||
Fixture raw;
|
Fixture raw;
|
||||||
const auto raw_memory = raw.AddMemory(ResourceKind::ScalarBuffer);
|
const auto raw_memory = raw.AddMemory(ResourceKind::ScalarBuffer);
|
||||||
RawRead(raw, Address(raw, Value(0x1000u), Value(0u)), Value(0u), raw_memory);
|
RawRead(raw, Address(raw, Value(0x1000u), Value(0u)), Value(0u), raw_memory);
|
||||||
CheckFatal([&] { TrackResources(raw.program, {}, {}); },
|
CheckFatal([&] { raw.Plan(); },
|
||||||
"incompatible scalar memory metadata",
|
"incompatible scalar memory metadata",
|
||||||
"raw scalar load accepted descriptor-buffer metadata");
|
"raw scalar load accepted descriptor-buffer metadata");
|
||||||
|
|
||||||
@@ -169,7 +171,7 @@ void TestScalarMemoryDomainMismatchFails() {
|
|||||||
{Value(0x1000u), Value(0u), Value(16u), Value(0u)});
|
{Value(0x1000u), Value(0u), Value(16u), Value(0u)});
|
||||||
buffer.EmitMemory(ValueOpcode::ReadConstBuffer, {resource, Value(0u)},
|
buffer.EmitMemory(ValueOpcode::ReadConstBuffer, {resource, Value(0u)},
|
||||||
buffer_memory);
|
buffer_memory);
|
||||||
CheckFatal([&] { TrackResources(buffer.program, {}, {}); },
|
CheckFatal([&] { buffer.Plan(); },
|
||||||
"incompatible scalar memory metadata",
|
"incompatible scalar memory metadata",
|
||||||
"descriptor scalar load accepted raw-address metadata");
|
"descriptor scalar load accepted raw-address metadata");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14343,7 +14343,7 @@ void BuildTypedPlan(const uint32_t *code, uint32_t words,
|
|||||||
ShaderRecompiler::IR::RemoveIdentities(ir);
|
ShaderRecompiler::IR::RemoveIdentities(ir);
|
||||||
ShaderRecompiler::IR::EliminateDeadCode(ir.blocks);
|
ShaderRecompiler::IR::EliminateDeadCode(ir.blocks);
|
||||||
}
|
}
|
||||||
ShaderRecompiler::IR::TrackResources(ir, decoded, cfg);
|
ShaderRecompiler::IR::TrackResources(ir, decoded, cfg, options.input_info);
|
||||||
ShaderRecompiler::IR::EliminateDeadCode(ir.blocks);
|
ShaderRecompiler::IR::EliminateDeadCode(ir.blocks);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -16182,10 +16182,6 @@ void TestCompilerStageInputOwnership() {
|
|||||||
CheckSpirvBinaryValidates(compiled.spirv);
|
CheckSpirvBinaryValidates(compiled.spirv);
|
||||||
|
|
||||||
#if KYTY_PLATFORM != KYTY_PLATFORM_WINDOWS
|
#if KYTY_PLATFORM != KYTY_PLATFORM_WINDOWS
|
||||||
options.stage = ShaderType::Vertex;
|
|
||||||
options.input_info.vertex = nullptr;
|
|
||||||
ExpectFatal([&] { (void)TranslateProgram(shader, options); },
|
|
||||||
"missing stage metadata bypassed translation validation");
|
|
||||||
const uint32_t auxiliary_position[] = {
|
const uint32_t auxiliary_position[] = {
|
||||||
EncodeExp0(0x0d, 0x1), EncodeExp1(0, 0, 0, 0), EncodeSopp(0x01)};
|
EncodeExp0(0x0d, 0x1), EncodeExp1(0, 0, 0, 0), EncodeSopp(0x01)};
|
||||||
for (const auto stage : {ShaderType::Pixel, ShaderType::Compute}) {
|
for (const auto stage : {ShaderType::Pixel, ShaderType::Compute}) {
|
||||||
|
|||||||
Reference in New Issue
Block a user