diff --git a/core/libs/prx/libSceAgcDriver/Execution/src/Driver/Shaders/ShaderRegistry.cpp b/core/libs/prx/libSceAgcDriver/Execution/src/Driver/Shaders/ShaderRegistry.cpp index cde3655482..5660f29339 100644 --- a/core/libs/prx/libSceAgcDriver/Execution/src/Driver/Shaders/ShaderRegistry.cpp +++ b/core/libs/prx/libSceAgcDriver/Execution/src/Driver/Shaders/ShaderRegistry.cpp @@ -452,6 +452,10 @@ std::unique_ptr PlanRegistered(const ShaderSnapshot& snap if (userCount > 32) throw std::runtime_error("AGC driver: static user SGPR count exceeds the register bank"); if (stage == Stage::Compute) { compute = Graphics::DecodeComputeStageInfo(state.shader, snapshot.header); + if (header.specials == nullptr) { + if (deferred != nullptr) return defer("its header has no specials to give its wave size"); + return {}; + } const auto special = ReadHeaderArray(snapshot, header.specials, 1).front(); wave = (special.dispatch_modifier & 0x8000u) != 0 ? 32u : 64u; } else if (stage == Stage::Fragment) { diff --git a/core/libs/prx/libSceAgcDriver/tests/execution/PreparedShaders.cpp b/core/libs/prx/libSceAgcDriver/tests/execution/PreparedShaders.cpp index be8e13c1c0..0f01860fd6 100644 --- a/core/libs/prx/libSceAgcDriver/tests/execution/PreparedShaders.cpp +++ b/core/libs/prx/libSceAgcDriver/tests/execution/PreparedShaders.cpp @@ -334,6 +334,30 @@ void UnsupportedTypeRegistration() { AgcDriverRegisterShader_nid_postfix(&header.shader); } +void RegistrationWithoutSpecials() { + alignas(256) std::array code{0xbf810000u}; + struct Header { + Shader shader{}; + std::array registers{}; + } header; + const auto address = reinterpret_cast(code.data()); + header.shader.file_header = 0x34333231u; + header.shader.version = 0x18; + header.shader.header_size = sizeof(header); + header.shader.shader_size = sizeof(code); + header.shader.code = code.data(); + header.shader.sh_registers = header.registers.data(); + header.shader.num_sh_registers = header.registers.size(); + header.registers = {{{0x20c, static_cast(address >> 8u)}, {0x20d, static_cast(address >> 40u)}, {0x207, 1}, {0x208, 1}, {0x209, 1}, {0x212, 0}, {0x213, 0}}}; + AgcDriverRegisterShader_nid_postfix(&header.shader); + std::vector commands; + for (const auto reg : header.registers) commands.insert(commands.end(), {0xc0017600u, reg.offset, reg.value}); + for (const std::uint32_t initiator : {0x8041u, 0x41u}) commands.insert(commands.end(), {0xc0031500u, 1, 1, 1, initiator}); + Packet packet{commands.data(), static_cast(commands.size()), 0, {}}; + sceAgcDriverSubmitAcb(0x20, &packet); + AgcDriverWaitIdle_nid_postfix(); +} + void Registration(bool indirect) { UnsupportedTypeRegistration(); alignas(256) std::array code{0xbf810000u}; @@ -496,6 +520,7 @@ int main(int argc, char** argv) { Require(argc != 2 || std::string_view(argv[1]) != "--fail-before-registration", "injected failure before registration"); PrepareMultisampledStorage(*device); device.reset(); + RegistrationWithoutSpecials(); Registration(argc == 2); std::cout << "prepared shader and transactional registration tests passed\n"; return 0;