Merge pull request #2293 from MichonGoddijn231849/fix/agc-prim-state-patch-hs

fix(agc): skip prim state preparation for a patch/hull mismatch
This commit is contained in:
Dean 2026-10-10 17:46:48 +13:00 committed by GitHub
commit a7aa802c3e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 21 additions and 5 deletions

View File

@ -78,7 +78,7 @@ enum class PrimitiveType : std::uint32_t {
};
constexpr std::uint32_t VGT_SHADER_STAGES_GS_BIT = 0x20u;
constexpr std::uint32_t VGT_SHADER_STAGES_NGG_BIT = 0x04u;
constexpr std::uint32_t VGT_SHADER_STAGES_HS_BIT = 0x04u;
enum class AgcDirectResourceType : std::uint32_t {
GdsCounterRange = 0,

View File

@ -46,14 +46,17 @@ int APS5_VABI sceAgcCreatePrimState(ShaderRegister* cx_regs, ShaderRegister* uc_
}
std::array<ShaderRegister, 3> primitiveValues{gs->specials->ge_cntl, hs != nullptr ? hs->specials->ge_user_vgpr_en : gs->specials->ge_user_vgpr_en, ShaderRegister{ShaderRegs::VGT_PRIMITIVE_TYPE, prim_type}};
const std::array<const Shader*, 2> stages{hs, gs};
AgcDriverResolveGraphicsStagesAbi_nid_postfix(std::span(stages).subspan(hs == nullptr ? 1u : 0u), contextValues, primitiveValues);
const bool patch = prim_type == static_cast<std::uint32_t>(ShaderRegs::PrimitiveType::Patch);
if (patch == ((contextValues[0].value & ShaderRegs::VGT_SHADER_STAGES_HS_BIT) != 0)) {
AgcDriverResolveGraphicsStagesAbi_nid_postfix(std::span(stages).subspan(hs == nullptr ? 1u : 0u), contextValues, primitiveValues);
}
if (cx_regs != nullptr) std::copy(contextValues.begin(), contextValues.end(), cx_regs);
if (uc_regs != nullptr) std::copy(primitiveValues.begin(), primitiveValues.end(), uc_regs);
return 0;
}
int APS5_VABI sceAgcUpdatePrimState(ShaderRegister* cx_regs, ShaderRegister* uc_regs, std::uint32_t prim_type) {
if (cx_regs != nullptr && (cx_regs[0].value & (ShaderRegs::VGT_SHADER_STAGES_GS_BIT | ShaderRegs::VGT_SHADER_STAGES_NGG_BIT)) == 0) {
if (cx_regs != nullptr && (cx_regs[0].value & (ShaderRegs::VGT_SHADER_STAGES_GS_BIT | ShaderRegs::VGT_SHADER_STAGES_HS_BIT)) == 0) {
cx_regs[1].value &= ~0x7u;
cx_regs[1].value |= GraphicsPrimTypeToGsOut(prim_type);
}

View File

@ -110,6 +110,19 @@ int main() {
}
}
}
preparations = 0;
std::array<ShaderRegister, 2> patchContext{};
std::array<ShaderRegister, 3> patchPrimitive{};
Require(sceAgcCreatePrimState(patchContext.data(), patchPrimitive.data(), nullptr, &vertex, 9) == 0);
Require(preparations == 0 && patchContext[0].offset == VGT_SHADER_STAGES_EN && patchContext[0].value == 0 && patchPrimitive[2].offset == VGT_PRIMITIVE_TYPE && patchPrimitive[2].value == 9);
ShaderSpecialRegs hullSpecial = special;
hullSpecial.vgt_shader_stages_en.value = VGT_SHADER_STAGES_HS_BIT;
hull.specials = &hullSpecial;
Require(sceAgcCreatePrimState(patchContext.data(), patchPrimitive.data(), &hull, &vertex, 4) == 0);
Require(preparations == 0 && patchContext[0].value == VGT_SHADER_STAGES_HS_BIT && patchPrimitive[2].value == 4);
Require(sceAgcCreatePrimState(patchContext.data(), patchPrimitive.data(), &hull, &vertex, 9) == 0);
Require(preparations == 1 && stageCount == 2 && preparedContext[0].value == VGT_SHADER_STAGES_HS_BIT && preparedPrimitive[2].value == 9 && patchPrimitive[2].value == 9);
hull.specials = &special;
std::array<ShaderRegister, 34> linkedContext{};
std::array<ShaderRegister, 3> linkedPrimitive{};
for (auto& value : linkedContext) value.value = 0xdeadbeef;

View File

@ -50,7 +50,7 @@ int main() {
}
Require(hasRenderTarget && hasRasterizer);
ShaderSpecialRegs special{};
special.vgt_shader_stages_en = {VGT_SHADER_STAGES_EN, VGT_SHADER_STAGES_NGG_BIT};
special.vgt_shader_stages_en = {VGT_SHADER_STAGES_EN, 0x2000u};
special.vgt_gs_out_prim_type = {VGT_GS_OUT_PRIM_TYPE, 0};
special.ge_cntl = {GE_CNTL, 0x123};
special.ge_user_vgpr_en = {GE_USER_VGPR_EN, 7};
@ -64,7 +64,7 @@ int main() {
context.back() = {0xdeadbeef, 0xcafebabe};
primitive.back() = context.back();
Require(sceAgcLinkShaders(context.data(), primitive.data(), nullptr, &vertex, &pixel, 4) == 0);
Require(context[0].offset == VGT_SHADER_STAGES_EN && context[0].value == VGT_SHADER_STAGES_NGG_BIT);
Require(context[0].offset == VGT_SHADER_STAGES_EN && context[0].value == 0x2000u);
Require(context[1].offset == VGT_GS_OUT_PRIM_TYPE && context[1].value == 2);
for (unsigned i = 0; i < 32; ++i)
Require(context[i + 2].offset == SPI_PS_INPUT_CNTL_0 + i && context[i + 2].value == i);