Skip to content

Commit

Permalink
read tess constants V# and other stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
baggins183 committed Nov 6, 2024
1 parent 1e72ccc commit 94e16be
Show file tree
Hide file tree
Showing 19 changed files with 339 additions and 277 deletions.
8 changes: 6 additions & 2 deletions src/core/libraries/gnmdriver/gnmdriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -307,8 +307,7 @@ struct AscQueueInfo {
u32 ring_size_dw;
};
static Common::SlotVector<AscQueueInfo> asc_queues{};
// static constexpr VAddr tessellation_factors_ring_addr = Core::SYSTEM_RESERVED_MAX - 0xFFFFFFF;
static constexpr VAddr tessellation_factors_ring_addr = 0xabcdef000000;
static constexpr VAddr tessellation_factors_ring_addr = Core::SYSTEM_RESERVED_MAX - 0xFFFFFFF;

static void ResetSubmissionLock(Platform::InterruptId irq) {
std::unique_lock lock{m_submission};
Expand Down Expand Up @@ -1617,6 +1616,10 @@ s32 PS4_SYSV_ABI sceGnmSetHsShader(u32* cmdbuf, u32 size, const u32* hs_regs, u3
cmdbuf = PM4CmdSetData::SetShReg(cmdbuf, 0x108u, hs_regs[0], 0u); // SPI_SHADER_PGM_LO_HS
cmdbuf = PM4CmdSetData::SetShReg(cmdbuf, 0x10au, hs_regs[2],
hs_regs[3]); // SPI_SHADER_PGM_RSRC1_HS/SPI_SHADER_PGM_RSRC2_HS
// This is wrong but just stash them here for now
// Should read the tess constants buffer instead, which is bound as V#, into runtime_info.
// HsConstants member of HsProgram is used to derive TessellationDataConstantBuffer, its members
// dont correspond to real registers
cmdbuf = PM4CmdSetData::SetShReg(cmdbuf, 0x11cu, hs_regs[4], hs_regs[5], hs_regs[6], hs_regs[7],
hs_regs[8], hs_regs[9], hs_regs[10], hs_regs[11], hs_regs[12],
hs_regs[13]); // TODO comment
Expand All @@ -1625,6 +1628,7 @@ s32 PS4_SYSV_ABI sceGnmSetHsShader(u32* cmdbuf, u32 size, const u32* hs_regs, u3
cmdbuf = PM4CmdSetData::SetContextReg(cmdbuf, 0x2dbu, hs_regs[4]); // VGT_TF_PARAM
cmdbuf = PM4CmdSetData::SetContextReg(cmdbuf, 0x2d6u, param4); // VGT_LS_HS_CONFIG

// right padding?
WriteTrailingNop<11>(cmdbuf);
return ORBIS_OK;
}
Expand Down
2 changes: 1 addition & 1 deletion src/shader_recompiler/backend/spirv/emit_spirv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ void DefineEntryPoint(const Info& info, EmitContext& ctx, Id main) {
execution_model = spv::ExecutionModel::TessellationControl;
ctx.AddCapability(spv::Capability::Tessellation);
ctx.AddExecutionMode(main, spv::ExecutionMode::OutputVertices,
ctx.runtime_info.hs_info.num_output_cp);
ctx.runtime_info.hs_info.output_control_points);
break;
case LogicalStage::TessellationEval: {
execution_model = spv::ExecutionModel::TessellationEvaluation;
Expand Down
25 changes: 25 additions & 0 deletions src/shader_recompiler/frontend/hull_shader.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include "common/types.h"

namespace Shader {

struct TessellationDataConstantBuffer {
u32 m_lsStride;
u32 m_hsCpStride; // HullStateConstants::m_cpStride != 0 ? HullStateConstants::m_cpStride :
// ls_stride
u32 m_hsNumPatch; // num patches submitted in threadgroup
u32 m_hsOutputBase; // HullStateConstants::m_numInputCP::m_cpStride != 0 ?
// HullStateConstants::m_numInputCP * ls_stride * num_patches : 0
//
u32 m_patchConstSize; // 16 * num_patch_attrs
u32 m_patchConstBase; // hs_output_base + patch_output_size
u32 m_patchOutputSize;
f32 m_offChipTessellationFactorThreshold;
u32 m_firstEdgeTessFactorIndex;
};

} // namespace Shader
26 changes: 4 additions & 22 deletions src/shader_recompiler/frontend/translate/scalar_alu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,9 @@ void Translator::EmitScalarAlu(const GcnInst& inst) {
case Opcode::S_MUL_I32:
return S_MUL_I32(inst);
case Opcode::S_BFE_I32:
return S_BFE_I32(inst);
return S_BFE(inst, true);
case Opcode::S_BFE_U32:
return S_BFE_U32(inst);
return S_BFE(inst, false);
case Opcode::S_ABSDIFF_I32:
return S_ABSDIFF_I32(inst);

Expand Down Expand Up @@ -411,30 +411,12 @@ void Translator::S_MUL_I32(const GcnInst& inst) {
SetDst(inst.dst[0], ir.IMul(GetSrc(inst.src[0]), GetSrc(inst.src[1])));
}

void Translator::S_BFE_U32(const GcnInst& inst) {
void Translator::S_BFE(const GcnInst& inst, bool is_signed) {
const IR::U32 src0{GetSrc(inst.src[0])};
const IR::U32 src1{GetSrc(inst.src[1])};
const IR::U32 offset{ir.BitwiseAnd(src1, ir.Imm32(0x1F))};
const IR::U32 count{ir.BitFieldExtract(src1, ir.Imm32(16), ir.Imm32(7))};
const IR::U32 result{ir.BitFieldExtract(src0, offset, count)};
SetDst(inst.dst[0], result);
ir.SetScc(ir.INotEqual(result, ir.Imm32(0)));
}

void Translator::S_BFE_I32(const GcnInst& inst) {
const IR::U32 src0{GetSrc(inst.src[0])};
const IR::U32 src1{GetSrc(inst.src[1])};
IR::U32 result;

ASSERT_MSG(src1.IsImmediate(), "Unhandled S_BFE_I32 with non-immediate mask");
u32 mask = src1.U32();
ASSERT(mask != 0);
u32 offset = std::countr_zero(mask);
u32 count = std::popcount(mask);
mask = mask >> offset;
ASSERT_MSG((mask & (mask + 1)) == 0, "mask {} has non-adjacent bits set");

result = ir.BitFieldExtract(src0, ir.Imm32(offset), ir.Imm32(count), true);
const IR::U32 result{ir.BitFieldExtract(src0, offset, count, is_signed)};
SetDst(inst.dst[0], result);
ir.SetScc(ir.INotEqual(result, ir.Imm32(0)));
}
Expand Down
27 changes: 0 additions & 27 deletions src/shader_recompiler/frontend/translate/translate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,35 +54,8 @@ void Translator::EmitPrologue() {
}
break;
case LogicalStage::TessellationControl: {
// v_bfe_u32 v0, v1, 8, 5
// v_bfe_u32 v2, v1, 0, 8
// Hull shader seems expect 2 values packed in V1.
// V1[0:7] seems like patch_id, aka PrimitiveId
// V1[8:12] seems like the output control point id, aka InvocationId
// however, in "passthrough" hull shaders, with the same input/output patch topology, and no
// additional per-output-control-point attributes, it doesn't make much sense for V1[8:12]
// to be a control point ID.
// Thats because this value contributes to address calculations for per-patch output writes,
// e.g. to the tess factors, in these "passthrough" shaders.
// V[0:7] also contributes, which is expected
ir.SetVectorReg(IR::VectorReg::V1,
ir.GetAttributeU32(IR::Attribute::PackedHullInvocationInfo));

// Copy inputs to outputs by InvocationID, to
// handle the passthrough case
// TODO: skip this if unecessary
// TODO: probably do this later because we dont know what attributes are active
if (true) {
// TODO: ctreate if stmt control flow:
// if (invocationID < gl_PatchVerticesIn) {
// out_attr[invocationID][0] = in_attr[invocationID][0];
// out_attr[invocationID][1] = in_attr[invocationID][1];
// ...
// out_attr[invocationID][N] = in_attr[invocationID][N];
//}
// for (auto i = 0; i < info.)
ir.TcsOutputBarrier();
}
break;
}
case LogicalStage::TessellationEval:
Expand Down
2 changes: 1 addition & 1 deletion src/shader_recompiler/frontend/translate/translate.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ class Translator {
void S_ASHR_I32(const GcnInst& inst);
void S_BFM_B32(const GcnInst& inst);
void S_MUL_I32(const GcnInst& inst);
void S_BFE_U32(const GcnInst& inst);
void S_BFE(const GcnInst& inst, bool is_signed);
void S_BFE_I32(const GcnInst& inst);
void S_ABSDIFF_I32(const GcnInst& inst);

Expand Down
22 changes: 12 additions & 10 deletions src/shader_recompiler/info.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "common/types.h"
#include "shader_recompiler/backend/bindings.h"
#include "shader_recompiler/frontend/copy_shader.h"
#include "shader_recompiler/frontend/hull_shader.h"
#include "shader_recompiler/ir/attribute.h"
#include "shader_recompiler/ir/passes/srt.h"
#include "shader_recompiler/ir/reg.h"
Expand Down Expand Up @@ -183,6 +184,9 @@ struct Info {
PersistentSrtInfo srt_info;
std::vector<u32> flattened_ud_buf;

// TODO handle indirection
IR::ScalarReg tess_constants_ud_reg = IR::ScalarReg::Max;

std::span<const u32> user_data;
Stage stage;
LogicalStage l_stage;
Expand Down Expand Up @@ -269,16 +273,14 @@ struct Info {
}
}

// Hack
bool isPassthroughTcs() {
static boost::container::vector<u64> passthrough_hashes = {
0xbc234799 /* passthrough */, 0x8453cd1c /* passthrough */,
0xd67db0ef /* passthrough */, 0x34121ac6 /* passthrough*/,
0xa26750c1 /* passthrough, warp */, 0xbb88db5f /* passthrough */,
0x90c6fb05 /* passthrough */, 0x627ac5b9 /* ayyylmao*, passthrough */,
};

return std::ranges::contains(passthrough_hashes, pgm_hash);
void ReadTessConstantBuffer(TessellationDataConstantBuffer& tess_constants) {
ASSERT(tess_constants_ud_reg != IR::ScalarReg::Max);
auto buf = ReadUdReg<AmdGpu::Buffer>(static_cast<u32>(IR::ScalarReg::Max),
static_cast<u32>(tess_constants_ud_reg));
VAddr tess_constants_addr = buf.base_address;
memcpy(&tess_constants,
reinterpret_cast<TessellationDataConstantBuffer*>(tess_constants_addr),
sizeof(tess_constants));
}
};

Expand Down
24 changes: 19 additions & 5 deletions src/shader_recompiler/ir/attribute.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,18 +118,32 @@ std::string NameOf(Attribute attribute) {
return "LocalInvocationIndex";
case Attribute::InvocationId:
return "InvocationId";
case Attribute::PackedHullInvocationInfo:
return "PackedHullInvocationInfo";
case Attribute::PatchVertices:
return "PatchVertices";
case Attribute::TessellationEvaluationPointU:
return "TessellationEvaluationPointU";
case Attribute::TessellationEvaluationPointV:
return "TessellationEvaluationPointV";
case Attribute::PackedHullInvocationInfo:
return "PackedHullInvocationInfo";
case Attribute::TcsLsStride:
return "TcsLsStride";
case Attribute::TcsCpStride:
return "TcsCpStride";
case Attribute::TcsNumPatches:
return "TcsInputMulA";
case Attribute::TcsInputCpStride:
return "TcsInputMulB";
return "TcsNumPatches";
case Attribute::TcsOutputBase:
return "TcsOutputBase";
case Attribute::TcsPatchConstSize:
return "TcsPatchConstSize";
case Attribute::TcsPatchConstBase:
return "TcsPatchConstBase";
case Attribute::TcsPatchOutputSize:
return "TcsPatchOutputSize";
case Attribute::TcsOffChipTessellationFactorThreshold:
return "TcsOffChipTessellationFactorThreshold";
case Attribute::TcsFirstEdgeTessFactorIndex:
return "TcsFirstEdgeTessFactorIndex";
default:
break;
}
Expand Down
15 changes: 12 additions & 3 deletions src/shader_recompiler/ir/attribute.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,18 @@ enum class Attribute : u64 {
TessellationEvaluationPointU = 82,
TessellationEvaluationPointV = 83,
PackedHullInvocationInfo =
84, // PrimitiveId (patch id) and InvocationId (output control point id)
TcsNumPatches = 85, // Figure this out, just marking it for now for pattern matching
TcsInputCpStride = 86,
84, // PrimitiveId (patch id) and InvocationId (output control point id)
// Probably don't need all these.
// Most should be dead after hull shader transform
TcsLsStride = 85,
TcsCpStride = 86,
TcsNumPatches = 87,
TcsOutputBase = 88,
TcsPatchConstSize = 89,
TcsPatchConstBase = 90,
TcsPatchOutputSize = 91,
TcsOffChipTessellationFactorThreshold = 92,
TcsFirstEdgeTessFactorIndex = 93,
Max,
};

Expand Down
2 changes: 2 additions & 0 deletions src/shader_recompiler/ir/ir_emitter.h
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,7 @@ class IREmitter {
template <typename T = Value, typename... Args>
T Inst(Opcode op, Args... args) {
auto it{block->PrependNewInst(insertion_point, op, {Value{args}...})};
it->SetParent(block);
return T{Value{&*it}};
}

Expand All @@ -349,6 +350,7 @@ class IREmitter {
u32 raw_flags{};
std::memcpy(&raw_flags, &flags.proxy, sizeof(flags.proxy));
auto it{block->PrependNewInst(insertion_point, op, {Value{args}...}, raw_flags)};
it->SetParent(block);
return T{Value{&*it}};
}
};
Expand Down
Loading

0 comments on commit 94e16be

Please sign in to comment.