mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-28 13:56:59 +01:00
gpu: compile RDNA2 tessellation through native LS HS and TES stages
This commit is contained in:
@@ -150,8 +150,20 @@ struct SampledResourcePair {
|
||||
bool operator==(const SampledResourcePair& other) const = default;
|
||||
};
|
||||
|
||||
enum class TessellationAttribute {
|
||||
LocalOutput,
|
||||
ControlInput,
|
||||
ControlOutput,
|
||||
EvaluationInput,
|
||||
PatchOutput,
|
||||
Factor
|
||||
};
|
||||
|
||||
enum class StageInputKind {
|
||||
VertexIndex,
|
||||
InvocationId,
|
||||
PrimitiveId,
|
||||
TessCoord,
|
||||
InstanceIndex,
|
||||
FragCoord,
|
||||
FrontFacing,
|
||||
@@ -287,8 +299,12 @@ static_assert(sizeof(PushData) == 128);
|
||||
constexpr uint32_t NativePushConstantSize = sizeof(PushData);
|
||||
|
||||
[[nodiscard]] constexpr uint32_t NativeBinding(ShaderType stage, DescriptorBindingKind kind) {
|
||||
const uint32_t group = stage == ShaderType::Pixel ? 1u
|
||||
: stage == ShaderType::TessellationControl ? 2u
|
||||
: stage == ShaderType::TessellationEvaluation ? 3u
|
||||
: 0u;
|
||||
return static_cast<uint32_t>(kind) +
|
||||
(stage == ShaderType::Pixel ? static_cast<uint32_t>(DescriptorBindingKind::Count) : 0u);
|
||||
group * static_cast<uint32_t>(DescriptorBindingKind::Count);
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr ImageResourceClass ImageBindingResourceClass(DescriptorBindingKind kind) {
|
||||
|
||||
@@ -90,6 +90,7 @@ bool HasSideEffects(ValueOpcode opcode) {
|
||||
case ValueOpcode::Reference:
|
||||
case ValueOpcode::ReferenceU32:
|
||||
case ValueOpcode::SetAttribute:
|
||||
case ValueOpcode::SetTessellationAttribute:
|
||||
case ValueOpcode::MeshAllocate:
|
||||
case ValueOpcode::Barrier: return true;
|
||||
default: return false;
|
||||
|
||||
@@ -10,6 +10,9 @@ VALUE_OPCODE(GetUserData, U32, ScalarReg)
|
||||
VALUE_OPCODE(GetShaderBase, U64)
|
||||
VALUE_OPCODE(MeshDrawParameter, U32, U32)
|
||||
VALUE_OPCODE(MeshAllocate, Void, U32)
|
||||
VALUE_OPCODE(TessellationBase, U32, U32)
|
||||
VALUE_OPCODE(GetTessellationAttribute, U32, U32, U32, U1)
|
||||
VALUE_OPCODE(SetTessellationAttribute, Void, U32, U32, U32, U1)
|
||||
VALUE_OPCODE(GetBuiltin, U32, U32, U32)
|
||||
VALUE_OPCODE(GetThreadBitScalarRegister, U1, ScalarReg)
|
||||
VALUE_OPCODE(SetThreadBitScalarRegister, Void, ScalarReg, U1)
|
||||
|
||||
@@ -228,6 +228,15 @@ void FoldInstruction(Block& block, Block::iterator instruction,
|
||||
const auto offset = Arg(inst, 1);
|
||||
const auto count = Arg(inst, 2);
|
||||
auto* source = value.TryInstruction();
|
||||
if (source != nullptr && source->GetOpcode() == ValueOpcode::ShiftLeftLogical32 &&
|
||||
IsImmediate(offset, Type::U32) && IsImmediate(count, Type::U32)) {
|
||||
const auto shift = Arg(*source, 1);
|
||||
if (IsImmediate(shift, Type::U32) && shift.U32() < 32u &&
|
||||
offset.U32() <= shift.U32() && count.U32() <= shift.U32() - offset.U32()) {
|
||||
Replace(inst, Value(0u));
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (source != nullptr && source->GetOpcode() == ValueOpcode::GetBuiltin &&
|
||||
source->Arg(0) == Value(static_cast<uint32_t>(StageInputKind::PackedAncillary)) &&
|
||||
IsImmediate(offset, Type::U32) && IsImmediate(count, Type::U32) && count.U32() != 0u) {
|
||||
|
||||
@@ -43,6 +43,9 @@ void AddOutput(ShaderInfo& info, StageOutputKind kind, uint32_t index, uint32_t
|
||||
void ValidateOptions(const Program& program, ShaderStageInputInfo input_info) {
|
||||
switch (program.stage) {
|
||||
case ShaderType::Vertex:
|
||||
case ShaderType::Local:
|
||||
case ShaderType::TessellationControl:
|
||||
case ShaderType::TessellationEvaluation:
|
||||
case ShaderType::Mesh:
|
||||
if (input_info.vertex == nullptr) {
|
||||
return Fail("vertex shader has no input metadata");
|
||||
@@ -81,7 +84,8 @@ void ValidateValueReferences(const Program& program, ShaderStageInputInfo input_
|
||||
!inst.Arg(1).IsImmediate() || inst.Arg(1).GetType() != Type::U32) {
|
||||
return Fail("typed attribute reference is not constant");
|
||||
}
|
||||
if (program.stage == ShaderType::Vertex &&
|
||||
if ((program.stage == ShaderType::Vertex ||
|
||||
program.stage == ShaderType::Local) &&
|
||||
(inst.Arg(1).U32() >= 4u ||
|
||||
inst.Arg(0).U32() >=
|
||||
static_cast<uint32_t>(input_info.vertex->resources_num))) {
|
||||
@@ -124,6 +128,8 @@ void ValidateValueReferences(const Program& program, ShaderStageInputInfo input_
|
||||
}
|
||||
break;
|
||||
case StageInputKind::VertexIndex:
|
||||
case StageInputKind::InvocationId:
|
||||
case StageInputKind::PrimitiveId:
|
||||
case StageInputKind::InstanceIndex:
|
||||
case StageInputKind::FrontFacing:
|
||||
case StageInputKind::LocalInvocationIndex:
|
||||
@@ -142,6 +148,7 @@ void ValidateValueReferences(const Program& program, ShaderStageInputInfo input_
|
||||
return Fail("typed barycentric component is out of range");
|
||||
}
|
||||
break;
|
||||
case StageInputKind::TessCoord:
|
||||
case StageInputKind::WorkgroupId:
|
||||
case StageInputKind::LocalInvocationId:
|
||||
case StageInputKind::GlobalInvocationId:
|
||||
@@ -161,8 +168,10 @@ void ValidateValueReferences(const Program& program, ShaderStageInputInfo input_
|
||||
}
|
||||
const auto& exp = program.export_info[index];
|
||||
if (exp.kind == ExportTargetKind::Position && exp.index != 0 && exp.en != 0 &&
|
||||
program.stage != ShaderType::Vertex && program.stage != ShaderType::Mesh) {
|
||||
return Fail("auxiliary position export requires the vertex or mesh stage");
|
||||
program.stage != ShaderType::Vertex && program.stage != ShaderType::Mesh &&
|
||||
program.stage != ShaderType::TessellationEvaluation) {
|
||||
return Fail("auxiliary position export requires a vertex, mesh, or "
|
||||
"tessellation evaluation shader");
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -249,6 +258,10 @@ void CollectComputeInputs(const ShaderComputeInputInfo* compute, ShaderInfo& inf
|
||||
void CollectBuiltinInputs(const Program& program, ShaderInfo& info) {
|
||||
for (const auto* block: program.blocks) {
|
||||
for (const auto& inst: *block) {
|
||||
if (program.stage == ShaderType::TessellationControl &&
|
||||
inst.GetOpcode() == ValueOpcode::LaneId) {
|
||||
AddInput(info, StageInputKind::InvocationId, 0, 1, "gl_InvocationID");
|
||||
}
|
||||
if (inst.GetOpcode() != ValueOpcode::GetBuiltin) {
|
||||
continue;
|
||||
}
|
||||
@@ -260,6 +273,13 @@ void CollectBuiltinInputs(const Program& program, ShaderInfo& info) {
|
||||
case StageInputKind::InstanceIndex:
|
||||
AddInput(info, kind, 0, 1, "gl_InstanceIndex");
|
||||
break;
|
||||
case StageInputKind::InvocationId:
|
||||
AddInput(info, kind, 0, 1, "gl_InvocationID");
|
||||
break;
|
||||
case StageInputKind::PrimitiveId:
|
||||
AddInput(info, kind, 0, 1, "gl_PrimitiveID");
|
||||
break;
|
||||
case StageInputKind::TessCoord: AddInput(info, kind, 0, 3, "gl_TessCoord"); break;
|
||||
case StageInputKind::FragCoord: AddInput(info, kind, 0, 4, "gl_FragCoord"); break;
|
||||
case StageInputKind::FrontFacing:
|
||||
AddInput(info, kind, 0, 1, "gl_FrontFacing");
|
||||
@@ -380,7 +400,10 @@ void CollectShaderInfo(Program& program, ShaderStageInputInfo input_info) {
|
||||
});
|
||||
});
|
||||
switch (program.stage) {
|
||||
case ShaderType::Vertex: CollectVertexInputs(program, input_info.vertex, next); break;
|
||||
case ShaderType::Vertex:
|
||||
case ShaderType::Local: CollectVertexInputs(program, input_info.vertex, next); break;
|
||||
case ShaderType::TessellationControl:
|
||||
case ShaderType::TessellationEvaluation:
|
||||
case ShaderType::Mesh: break;
|
||||
case ShaderType::Pixel: CollectPixelInputs(program, input_info.pixel, next); break;
|
||||
case ShaderType::Compute: CollectComputeInputs(input_info.compute, next); break;
|
||||
|
||||
Reference in New Issue
Block a user