mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-21 03:16:54 +02:00
graphics: emit PS5 register object and primitive IDs to RT7
This commit is contained in:
@@ -676,17 +676,11 @@ uint32_t EmitLaneId(EmitterState& state) {
|
||||
|
||||
uint32_t EmitMeshDrawParameter(ValueEmitContext& ctx, const IR::Inst& inst) {
|
||||
auto& state = ctx.state;
|
||||
const auto result = state.builder.AllocateId();
|
||||
const auto index = inst.Arg(0).U32();
|
||||
if (state.program.stage != ShaderType::Mesh || index >= IR::PushData::MeshDrawDwordCount) {
|
||||
ctx.Fail(inst, "invalid mesh draw parameter");
|
||||
}
|
||||
const auto pointer = state.builder.AllocateId();
|
||||
state.builder.AddFunction(spv::OpAccessChain, TypePushConstantElementPointer(state), pointer,
|
||||
state.push_constant_variable, ConstantU32(state, 0),
|
||||
ConstantU32(state, index));
|
||||
state.builder.AddFunction(spv::OpLoad, TypeU32(state), result, pointer);
|
||||
return result;
|
||||
return EmitPushDataLoad(state, ConstantU32(state, index));
|
||||
}
|
||||
|
||||
uint32_t EmitGetUserData(EmitterState& state, IR::ScalarReg reg) {
|
||||
|
||||
@@ -152,6 +152,7 @@ struct EmitterState {
|
||||
uint32_t layer_variable = 0;
|
||||
uint32_t viewport_index_variable = 0;
|
||||
uint32_t depth_variable = 0;
|
||||
uint32_t object_primitive_id_variable = 0;
|
||||
uint32_t sample_mask_variable = 0;
|
||||
std::vector<InputBinding> inputs;
|
||||
std::vector<OutputBinding> outputs;
|
||||
@@ -403,6 +404,7 @@ inline constexpr auto EmitAddU32 = EmitNative<spv::OpIAdd, IR::Type::U32, uint32
|
||||
uint32_t EmitBinaryU32(EmitterState& state, spv::Op opcode, uint32_t lhs, uint32_t rhs);
|
||||
|
||||
uint32_t EmitShaderDataDwordLoad(EmitterState& state, uint32_t dword_index);
|
||||
uint32_t EmitPushDataLoad(EmitterState& state, uint32_t index);
|
||||
|
||||
uint32_t StorageBufferPackedStride(const EmitterState& state, const IR::MemoryInfo& mem);
|
||||
|
||||
|
||||
@@ -2,16 +2,17 @@
|
||||
|
||||
namespace Libs::Graphics::ShaderRecompiler::Spirv::Emitter {
|
||||
|
||||
uint32_t EmitPushDataLoad(EmitterState& state, uint32_t index) {
|
||||
const auto pointer = state.builder.AllocateId();
|
||||
const auto value = state.builder.AllocateId();
|
||||
state.builder.AddFunction(spv::OpAccessChain, TypePushConstantElementPointer(state),
|
||||
pointer, state.push_constant_variable, ConstantU32(state, 0), index);
|
||||
state.builder.AddFunction(spv::OpLoad, TypeU32(state), value, pointer);
|
||||
return value;
|
||||
}
|
||||
|
||||
static uint32_t EmitShaderDataDwordLoadAt(EmitterState& state, uint32_t dword_index) {
|
||||
if (state.program.bindings.UsesPushData()) {
|
||||
const auto pointer = state.builder.AllocateId();
|
||||
const auto value = state.builder.AllocateId();
|
||||
state.builder.AddFunction(spv::OpAccessChain, TypePushConstantElementPointer(state),
|
||||
pointer, state.push_constant_variable, ConstantU32(state, 0),
|
||||
dword_index);
|
||||
state.builder.AddFunction(spv::OpLoad, TypeU32(state), value, pointer);
|
||||
return value;
|
||||
}
|
||||
if (state.program.bindings.UsesPushData()) return EmitPushDataLoad(state, dword_index);
|
||||
if (state.shader_data_storage_variable != 0) {
|
||||
const auto pointer = state.builder.AllocateId();
|
||||
const auto value = state.builder.AllocateId();
|
||||
|
||||
@@ -243,7 +243,8 @@ void DefineDescriptors(EmitterState& state) {
|
||||
IR::PushData::StartFor(bindings.push_data_start_dword, bindings.ShaderDataDwords());
|
||||
counts[static_cast<size_t>(Kind::ShaderData)] =
|
||||
bindings.ShaderDataDwords() != 0 && !bindings.UsesPushData();
|
||||
if (state.program.bindings.UsesPushData() || state.program.stage == ShaderType::Mesh) {
|
||||
if (state.program.bindings.UsesPushData() || state.program.stage == ShaderType::Mesh ||
|
||||
state.object_primitive_id_variable != 0) {
|
||||
const auto type = PushConstantBlockType(state);
|
||||
state.push_constant_variable = state.builder.DefineGlobalVariable(
|
||||
TypePointer(state, spv::StorageClassPushConstant, type), spv::StorageClassPushConstant);
|
||||
@@ -546,6 +547,11 @@ void DefineInputs(EmitterState& state) {
|
||||
}
|
||||
input.variable_id =
|
||||
DefineInterfaceVariable(state, type, spv::StorageClassInput, input.debug_name.c_str());
|
||||
if (state.program.stage == ShaderType::Pixel && input.kind == IR::StageInputKind::PrimitiveId) {
|
||||
// Fragment PrimitiveId accepts Tessellation, which the device already enables.
|
||||
state.builder.RequireCapability(spv::CapabilityTessellation);
|
||||
state.builder.AddAnnotation(spv::OpDecorate, input.variable_id, spv::DecorationFlat);
|
||||
}
|
||||
if (input.kind == IR::StageInputKind::Layer || input.kind == IR::StageInputKind::SampleId) {
|
||||
state.builder.AddAnnotation(spv::OpDecorate, input.variable_id, spv::DecorationFlat);
|
||||
}
|
||||
@@ -657,6 +663,13 @@ void DefineOutputs(EmitterState& state) {
|
||||
BuiltIn(state.sample_mask_variable, SampleMaskArrayType(state), "gl_SampleMask",
|
||||
spv::BuiltInSampleMask);
|
||||
break;
|
||||
case IR::StageOutputKind::ObjectPrimitiveId:
|
||||
binding.variable_id = DefineInterfaceVariable(
|
||||
state, TypeU32(state), spv::StorageClassOutput, binding.debug_name.c_str());
|
||||
state.object_primitive_id_variable = binding.variable_id;
|
||||
state.builder.AddAnnotation(spv::OpDecorate, binding.variable_id,
|
||||
spv::DecorationLocation, binding.location);
|
||||
break;
|
||||
case IR::StageOutputKind::Parameter:
|
||||
case IR::StageOutputKind::Mrt: {
|
||||
const bool uint_output =
|
||||
|
||||
@@ -85,6 +85,14 @@ void StoreDispatcherPhiEdge(ValueEmitContext& ctx, const DispatcherFunctionState
|
||||
|
||||
void EmitReturn(ValueEmitContext& ctx) {
|
||||
EmitKillIfPixelValidMaskInactive(ctx.state);
|
||||
if (ctx.state.object_primitive_id_variable != 0) {
|
||||
auto& state = ctx.state;
|
||||
const auto primitive = EmitGetBuiltin(
|
||||
ctx, IR::Value {static_cast<uint32_t>(IR::StageInputKind::PrimitiveId)}, IR::Value {0u});
|
||||
const auto object = EmitPushDataLoad(state, ConstantU32(state, 0));
|
||||
state.builder.AddFunction(spv::OpStore, state.object_primitive_id_variable,
|
||||
EmitAddU32(state, object, primitive));
|
||||
}
|
||||
ctx.state.builder.AddFunction(spv::OpReturn);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user