Merge pull request #292 from shadps4-emu/games/00144

Missing graphics features for flOw & Flower
This commit is contained in:
georgemoralis 2024-07-14 23:07:46 +03:00 committed by GitHub
commit b4df90d8e4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
25 changed files with 174 additions and 26 deletions

View file

@ -131,6 +131,13 @@ Id EmitReadConstBufferU32(EmitContext& ctx, u32 handle, Id index) {
return ctx.OpBitcast(ctx.U32[1], EmitReadConstBuffer(ctx, handle, index));
}
Id EmitReadStepRate(EmitContext& ctx, int rate_idx) {
return ctx.OpLoad(
ctx.U32[1], ctx.OpAccessChain(ctx.TypePointer(spv::StorageClass::PushConstant, ctx.U32[1]),
ctx.instance_step_rates,
rate_idx == 0 ? ctx.u32_zero_value : ctx.u32_one_value));
}
Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, u32 comp) {
if (IR::IsParam(attr)) {
const u32 index{u32(attr) - u32(IR::Attribute::Param0)};
@ -149,11 +156,7 @@ Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, u32 comp) {
return ctx.OpLoad(param.component_type, param.id);
}
} else {
const auto rate_idx = param.id.value == 0 ? ctx.u32_zero_value : ctx.u32_one_value;
const auto step_rate = ctx.OpLoad(
ctx.U32[1],
ctx.OpAccessChain(ctx.TypePointer(spv::StorageClass::PushConstant, ctx.U32[1]),
ctx.instance_step_rates, rate_idx));
const auto step_rate = EmitReadStepRate(ctx, param.id.value);
const auto offset = ctx.OpIAdd(
ctx.U32[1],
ctx.OpIMul(
@ -182,6 +185,12 @@ Id EmitGetAttributeU32(EmitContext& ctx, IR::Attribute attr, u32 comp) {
switch (attr) {
case IR::Attribute::VertexId:
return ctx.OpLoad(ctx.U32[1], ctx.vertex_index);
case IR::Attribute::InstanceId:
return ctx.OpLoad(ctx.U32[1], ctx.instance_id);
case IR::Attribute::InstanceId0:
return EmitReadStepRate(ctx, 0);
case IR::Attribute::InstanceId1:
return EmitReadStepRate(ctx, 1);
case IR::Attribute::WorkgroupId:
return ctx.OpCompositeExtract(ctx.U32[1], ctx.OpLoad(ctx.U32[3], ctx.workgroup_id), comp);
case IR::Attribute::LocalInvocationId:

View file

@ -45,6 +45,7 @@ void EmitSetVccHi(EmitContext& ctx);
void EmitPrologue(EmitContext& ctx);
void EmitEpilogue(EmitContext& ctx);
void EmitDiscard(EmitContext& ctx);
void EmitDiscardCond(EmitContext& ctx, Id condition);
void EmitBarrier(EmitContext& ctx);
void EmitWorkgroupMemoryBarrier(EmitContext& ctx);
void EmitDeviceMemoryBarrier(EmitContext& ctx);

View file

@ -14,6 +14,17 @@ void EmitDiscard(EmitContext& ctx) {
ctx.OpDemoteToHelperInvocationEXT();
}
void EmitDiscardCond(EmitContext& ctx, Id condition) {
const Id kill_label{ctx.OpLabel()};
const Id merge_label{ctx.OpLabel()};
ctx.OpSelectionMerge(merge_label, spv::SelectionControlMask::MaskNone);
ctx.OpBranchConditional(condition, kill_label, merge_label);
ctx.AddLabel(kill_label);
ctx.OpDemoteToHelperInvocationEXT();
ctx.OpBranch(merge_label);
ctx.AddLabel(merge_label);
}
void EmitEmitVertex(EmitContext& ctx, const IR::Value& stream) {
throw NotImplementedException("Geometry streams");
}

View file

@ -121,7 +121,7 @@ void CFG::EmitBlocks() {
void CFG::LinkBlocks() {
const auto get_block = [this](u32 address) {
const auto it = blocks.find(address, Compare{});
auto it = blocks.find(address, Compare{});
ASSERT_MSG(it != blocks.end() && it->begin == address);
return &*it;
};
@ -131,7 +131,10 @@ void CFG::LinkBlocks() {
// If the block doesn't end with a branch we simply
// need to link with the next block.
if (!end_inst.IsTerminateInstruction()) {
block.branch_true = get_block(block.end);
auto* next_block = get_block(block.end);
++next_block->num_predecessors;
block.branch_true = next_block;
block.end_class = EndClass::Branch;
continue;
}
@ -141,11 +144,20 @@ void CFG::LinkBlocks() {
const u32 branch_pc = block.end - end_inst.length;
const u32 target_pc = end_inst.BranchTarget(branch_pc);
if (end_inst.IsUnconditionalBranch()) {
block.branch_true = get_block(target_pc);
auto* target_block = get_block(target_pc);
++target_block->num_predecessors;
block.branch_true = target_block;
block.end_class = EndClass::Branch;
} else if (end_inst.IsConditionalBranch()) {
block.branch_true = get_block(target_pc);
block.branch_false = get_block(block.end);
auto* target_block = get_block(target_pc);
++target_block->num_predecessors;
auto* end_block = get_block(block.end);
++end_block->num_predecessors;
block.branch_true = target_block;
block.branch_false = end_block;
block.end_class = EndClass::Branch;
} else if (end_inst.opcode == Opcode::S_ENDPGM) {
const auto& prev_inst = inst_list[block.end_index - 1];

View file

@ -36,6 +36,7 @@ struct Block : Hook {
u32 end;
u32 begin_index;
u32 end_index;
u32 num_predecessors{};
IR::Condition cond{};
GcnInst end_inst{};
EndClass end_class{};

View file

@ -631,6 +631,7 @@ private:
case StatementType::Code: {
ensure_block();
if (!stmt.block->is_dummy) {
current_block->has_multiple_predecessors = stmt.block->num_predecessors > 1;
const u32 start = stmt.block->begin_index;
const u32 size = stmt.block->end_index - start + 1;
Translate(current_block, stmt.block->begin, inst_list.subspan(start, size),

View file

@ -1,11 +1,17 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/logging/log.h"
#include "shader_recompiler/frontend/translate/translate.h"
namespace Shader::Gcn {
void Translator::EXP(const GcnInst& inst) {
if (ir.block->has_multiple_predecessors) {
LOG_WARNING(Render_Recompiler, "An ambiguous export appeared in translation");
ir.Discard(ir.LogicalNot(ir.GetExec()));
}
const auto& exp = inst.control.exp;
const IR::Attribute attrib{exp.target};
const std::array vsrc = {

View file

@ -35,10 +35,20 @@ void Translator::EmitPrologue() {
IR::VectorReg dst_vreg = IR::VectorReg::V0;
switch (info.stage) {
case Stage::Vertex:
// https://github.com/chaotic-cx/mesa-mirror/blob/72326e15/src/amd/vulkan/radv_shader_args.c#L146C1-L146C23
// v0: vertex ID, always present
ir.SetVectorReg(dst_vreg++, ir.GetAttributeU32(IR::Attribute::VertexId));
ir.SetVectorReg(dst_vreg++, ir.GetAttributeU32(IR::Attribute::InstanceId));
ir.SetVectorReg(dst_vreg++, ir.GetAttributeU32(IR::Attribute::PrimitiveId));
// v1: instance ID, step rate 0
if (info.num_input_vgprs > 0) {
ir.SetVectorReg(dst_vreg++, ir.GetAttributeU32(IR::Attribute::InstanceId0));
}
// v2: instance ID, step rate 1
if (info.num_input_vgprs > 1) {
ir.SetVectorReg(dst_vreg++, ir.GetAttributeU32(IR::Attribute::InstanceId1));
}
// v3: instance ID, plain
if (info.num_input_vgprs > 2) {
ir.SetVectorReg(dst_vreg++, ir.GetAttributeU32(IR::Attribute::InstanceId));
}
break;
case Stage::Fragment:
// https://github.com/chaotic-cx/mesa-mirror/blob/72326e15/src/amd/vulkan/radv_shader_args.c#L258

View file

@ -72,6 +72,8 @@ enum class Attribute : u64 {
LocalInvocationId = 75,
LocalInvocationIndex = 76,
FragCoord = 77,
InstanceId0 = 78, // step rate 0
InstanceId1 = 79, // step rate 1
Max,
};

View file

@ -149,6 +149,8 @@ public:
std::array<Value, NumScalarRegs> ssa_sreg_values;
std::array<Value, NumVectorRegs> ssa_vreg_values;
bool has_multiple_predecessors{false};
private:
/// Memory pool for instruction list
ObjectPool<Inst>* inst_pool;

View file

@ -115,6 +115,10 @@ void IREmitter::Discard() {
Inst(Opcode::Discard);
}
void IREmitter::Discard(const U1& cond) {
Inst(Opcode::DiscardCond, cond);
}
void IREmitter::Barrier() {
Inst(Opcode::Barrier);
}

View file

@ -42,6 +42,7 @@ public:
void Prologue();
void Epilogue();
void Discard();
void Discard(const U1& cond);
void Barrier();
void WorkgroupMemoryBarrier();

View file

@ -49,6 +49,7 @@ bool Inst::MayHaveSideEffects() const noexcept {
case Opcode::Prologue:
case Opcode::Epilogue:
case Opcode::Discard:
case Opcode::DiscardCond:
case Opcode::SetAttribute:
case Opcode::StoreBufferF32:
case Opcode::StoreBufferF32x2:

View file

@ -13,6 +13,7 @@ OPCODE(PhiMove, Void, Opaq
OPCODE(Prologue, Void, )
OPCODE(Epilogue, Void, )
OPCODE(Discard, Void, )
OPCODE(DiscardCond, Void, U1, )
// Constant memory operations
OPCODE(ReadConst, U32, U32x2, U32, )

View file

@ -37,6 +37,7 @@ void Visit(Info& info, IR::Inst& inst) {
info.uses_group_quad = true;
break;
case IR::Opcode::Discard:
case IR::Opcode::DiscardCond:
info.has_discard = true;
break;
case IR::Opcode::ImageGather:

View file

@ -163,6 +163,7 @@ struct Info {
std::array<u32, 3> workgroup_size{};
u32 num_user_data;
u32 num_input_vgprs;
std::span<const u32> user_data;
Stage stage;