Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "prx/libSceAgcDriver/Execution/include/Driver/Driver.hpp"
#include "prx/libSceAgcDriver/Execution/include/Driver/Diagnostics.hpp"
#include "prx/libSceAgcDriver/Execution/include/Pm4.hpp"
#include "prx/libSceAgcDriver/Graphics/include/GuestBufferMemory.hpp"
#include <cstdlib>

namespace AgcDriver::DriverDetail {
Expand Down Expand Up @@ -51,6 +52,12 @@ std::optional<Graphics::IndirectDrawPath> Driver::ClassifyIndirectDraw(const Sha
if (!support.firstInstance && (indirect.instanceRule == Rule::InPlace || indirect.instanceConstant != 0)) fail(Path::FeatureGap);
if ((indirect.vertexRule == Rule::Constant || indirect.instanceRule == Rule::Constant) && indirect.count > 256) fail(Path::FeatureGap);

const auto rangeBytes = indirect.RangeBytes();
if (rangeBytes > 0) {
if (!Graphics::RegisteredReadableCovers(indirect.arguments, static_cast<std::size_t>(rangeBytes))) fail(Path::NotImported);
if (indirect.countIndirect && !Graphics::RegisteredReadableCovers(indirect.countAddress, 4)) fail(Path::NotImported);
}

static const std::uint64_t vertexCap = [] { const char* text = std::getenv("APS5_INDIRECT_VERTEX_MIB"); return (text ? std::strtoull(text, nullptr, 10) : 64ull) << 20u; }();
for (const auto& attribute : result.vertexAttributes) {
const auto stride = (attribute.resource.fields[1] >> 16u) & 0x3fffu;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,25 @@ std::string Run(Fixture& fixture) {
fixture.Draw(vertex, draw);
failures += fixture.Check(what + ", drawn on the GPU", bufferIndices, 0x51u, 0x62u, true);
}
{
const std::string what = "indexed indirect record whose arguments are outside registered guest memory";
const auto vertex = fixture.Vertex(PostAddCode, staleUserData);
AgcDriver::Pm4::DrawParameters draw{indexAddress, static_cast<std::uint32_t>(Indices.size()), 2, 0, 0, true, 0, 0};
auto unmapped = indexedIndirect;
unmapped.arguments = 0xdeadbeef0000ull;
draw.indirect = unmapped;
failures += Classified(fixture, what, vertex, staleUserData, draw, Path::NotImported, Rule::InPlace);
}
{
const std::string what = "indexed indirect record whose count buffer is outside registered guest memory";
const auto vertex = fixture.Vertex(PostAddCode, staleUserData);
AgcDriver::Pm4::DrawParameters draw{indexAddress, static_cast<std::uint32_t>(Indices.size()), 2, 0, 0, true, 0, 0};
auto unmapped = indexedIndirect;
unmapped.countIndirect = true;
unmapped.countAddress = 0xdeadbeef1000ull;
draw.indirect = unmapped;
failures += Classified(fixture, what, vertex, staleUserData, draw, Path::NotImported, Rule::InPlace);
}
}
return failures;
}
Expand Down
1 change: 1 addition & 0 deletions docs/dev/debt/libSceAgcDriver.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
- [Background link-time-optimized relink of library pipelines](../../../core/libs/prx/libSceAgcDriver/Execution/include/PipelineLinkOptimization.hpp) (libSceAgcDriver) is skipped on every GPU under NVIDIA's proprietary Vulkan driver (`VK_DRIVER_ID_NVIDIA_PROPRIETARY`), so those pipelines keep their fast-linked form. The optimized link loses the device when bound on an RTX 3080 (Ampere, #2866) and an RTX 4060 (Ada, #3434); an RTX 5060 and an RTX 5080 (Blackwell) on the same driver do not, so the scope is wider than the evidence. No standard Vulkan query tells the architecture apart, and the driver version that fixes it is unknown. `APS5_NO_PIPELINE_LTO` disables the relink on every driver.
- [8_SRGB and 8_8_SRGB textures](../../../core/libs/prx/libSceAgcDriver/Graphics/src/TextureFormat.cpp) (libSceAgcDriver) that the device samples as R8_SRGB or R8G8_SRGB use its own decode, which need not match gfx1035: NVIDIA's R8_SRGB is one bf16 step off in 29 of 256 codes.
- [WAIT_REG_MEM](../../../core/libs/prx/libSceAgcDriver/Execution/src/Driver/Synchronization/WaitMemory.cpp) reports a diagnostic after `APS5_GPU_WAIT_TIMEOUT_MS` without treating the timeout as completion. An unsatisfied wait keeps polling and checking driver failures; a missing producer can therefore leave its queue waiting indefinitely. Existing recorded-label shortcuts remain in use.
- [Indirect draw argument range validation](../../../core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/IndirectDraw.cpp) (libSceAgcDriver): an indirect draw whose argument or count buffer address is not covered by registered readable guest memory falls back to CPU-side execution (Path::NotImported); whether the console faults or drops draws on unmapped indirect argument buffers is not measured.
- [COND_EXEC](../../../core/libs/prx/libSceAgcDriver/Execution/src/Driver/Packets/PacketExecution.cpp) reads its condition after the earlier packets of its queue complete. Without PFP_SYNC_ME the console's graphics PFP reads it ahead of the ME, so a title that races the read sees a later value here.
- A [flip inside a COND_EXEC range](../../../core/libs/prx/libSceAgcDriver/Execution/src/Driver/Packets/CommandValidation.cpp) throws: the flip is reserved with the video output when the buffer is submitted, and how the console withdraws a skipped one is unknown.
- A [COND_EXEC range](../../../core/libs/prx/libSceAgcDriver/Execution/src/Driver/Queues/Submission.cpp) must hold whole packets and end inside its command buffer. A chained INDIRECT_BUFFER or a REWIND inside a range throws, as what the CP does with the skipped dwords then is unknown.
Expand Down
Loading