mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-27 00:28:14 +00:00
Merge pull request #7175 from pushkarreddyy/feat/agc-driver-primitive-polygon
feat(libSceAgcDriver): support polygon primitive type 21
This commit is contained in:
4 files changed
+35
-9
No files matched your search
@@ -47,7 +47,7 @@ std::optional<DrawVerdict> Driver::precheckDraw(const QueueState& queue, const S
|
||||
const auto primitive = queue.userConfig.find(0x242);
|
||||
const std::uint32_t allOnes = drawParameters.indexSize == 2 ? 0xffffu : 0xffffffffu;
|
||||
const auto type = primitive == queue.userConfig.end() ? 0u : primitive->second & 0x3fu;
|
||||
const bool strip = type == 3 || type == 5 || type == 6;
|
||||
const bool strip = type == 3 || type == 5 || type == 6 || type == 21;
|
||||
const bool list = type == 1 || type == 2 || type == 4;
|
||||
const auto restartDevice = device.Load();
|
||||
if (!strip && !(list && restartDevice != nullptr && restartDevice->PrimitiveListRestart())) {
|
||||
|
||||
@@ -92,7 +92,7 @@ VkConservativeRasterizationModeEXT decodeConservativeRasterization(const QueueSt
|
||||
requireConservativeTriangles((domain == 1u || domain == 2u) && (topology == 2u || topology == 3u), topology == 0u ? "points" : topology == 1u || domain == 0u ? "lines" : "other primitive types", "VGT_TF_PARAM", parameters);
|
||||
} else {
|
||||
const auto primitive = read(queue.userConfig, 0x242, RegisterBank::UserConfig);
|
||||
requireConservativeTriangles(primitive == 4u || primitive == 5u || primitive == 6u, primitive == 1u ? "points" : primitive == 2u || primitive == 3u ? "lines" : primitive == 7u || primitive == 17u ? "rectangles" : "other primitive types", "VGT_PRIMITIVE_TYPE", primitive);
|
||||
requireConservativeTriangles(primitive == 4u || primitive == 5u || primitive == 6u || primitive == 21u, primitive == 1u ? "points" : primitive == 2u || primitive == 3u ? "lines" : primitive == 7u || primitive == 17u ? "rectangles" : "other primitive types", "VGT_PRIMITIVE_TYPE", primitive);
|
||||
}
|
||||
Require((read(cx, 0x1b3) & 0x44u) == 0, "conservative rasterization with centroid interpolation is unsupported");
|
||||
return VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT;
|
||||
@@ -118,6 +118,7 @@ std::uint32_t inactiveVertexPointSize(const QueueState& queue) {
|
||||
case 6:
|
||||
case 7:
|
||||
case 17:
|
||||
case 21:
|
||||
return 1u << 16u;
|
||||
default:
|
||||
return 0;
|
||||
@@ -401,7 +402,7 @@ std::string nonTriangleRejection(const QueueState& queue, const char* message, b
|
||||
const auto topology = (*parameters >> 5u) & 7u;
|
||||
if ((domain != 1u && domain != 2u) || (topology != 2u && topology != 3u)) return zeroMessage(0x2db, *parameters, message);
|
||||
}
|
||||
} else if (const auto primitive = word(queue.userConfig, 0x242, RegisterBank::UserConfig); primitive && *primitive != 4u && *primitive != 5u && *primitive != 6u && !(rectangles && (*primitive == 7u || *primitive == 17u))) {
|
||||
} else if (const auto primitive = word(queue.userConfig, 0x242, RegisterBank::UserConfig); primitive && *primitive != 4u && *primitive != 5u && *primitive != 6u && *primitive != 21u && !(rectangles && (*primitive == 7u || *primitive == 17u))) {
|
||||
return zeroMessage(0x242, *primitive, message);
|
||||
}
|
||||
return {};
|
||||
@@ -1039,7 +1040,10 @@ State DecodeState(const QueueState& queue, bool vertexWorkgroup) {
|
||||
break;
|
||||
case 9: result.topology = VK_PRIMITIVE_TOPOLOGY_PATCH_LIST; break;
|
||||
case 4: result.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; break;
|
||||
case 5: result.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN; break;
|
||||
case 5:
|
||||
case 21:
|
||||
result.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN;
|
||||
break;
|
||||
case 6: result.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; break;
|
||||
default: throw std::runtime_error("AGC graphics: unsupported primitive type " + std::to_string(primitive));
|
||||
}
|
||||
@@ -1733,7 +1737,7 @@ std::string DrawRejection(const QueueState& queue, bool indexed) {
|
||||
if (indexed && value(queue.userConfig, 0x24b, word) && word != 0) {
|
||||
std::uint32_t primitive = 0;
|
||||
std::uint32_t resetIndex = 0;
|
||||
if (value(queue.userConfig, 0x242, primitive) && (primitive & 0x3fu) != 1 && (primitive & 0x3fu) != 2 && (primitive & 0x3fu) != 3 && (primitive & 0x3fu) != 4 && (primitive & 0x3fu) != 5 && (primitive & 0x3fu) != 6) return "AGC graphics: primitive restart is only supported for point, line and triangle topologies";
|
||||
if (value(queue.userConfig, 0x242, primitive) && (primitive & 0x3fu) != 1 && (primitive & 0x3fu) != 2 && (primitive & 0x3fu) != 3 && (primitive & 0x3fu) != 4 && (primitive & 0x3fu) != 5 && (primitive & 0x3fu) != 6 && (primitive & 0x3fu) != 21) return "AGC graphics: primitive restart is only supported for point, line and triangle topologies";
|
||||
if (value(cx, 0x103, resetIndex) && (resetIndex & 0xffffu) != 0xffffu) return "AGC graphics: primitive restart index other than all ones is unsupported";
|
||||
}
|
||||
if (auto reason = nonzero(cx, 0x207, ~(LayerExports | ClipCullExports | inactiveVertexPointSize(queue)), "layer, viewport or auxiliary vertex exports"); !reason.empty()) return reason;
|
||||
|
||||
@@ -117,7 +117,7 @@ void inactiveVertexPointSizeTests() {
|
||||
queue.context[0x207] = 0x01210000;
|
||||
return queue;
|
||||
};
|
||||
for (const auto primitive : {2u, 4u, 5u, 6u, 7u, 17u}) {
|
||||
for (const auto primitive : {2u, 4u, 5u, 6u, 7u, 17u, 21u}) {
|
||||
auto queue = pointSizeState();
|
||||
queue.userConfig[0x242] = primitive;
|
||||
for (const auto raster : {0u, 0x240u, 0x248u}) {
|
||||
@@ -194,6 +194,23 @@ void inactiveVertexPointSizeTests() {
|
||||
rejected(queue);
|
||||
}
|
||||
|
||||
void PolygonPrimitiveTests() {
|
||||
auto queue = makeState();
|
||||
queue.userConfig[0x242] = 21;
|
||||
queue.context[0x1b3] = 2;
|
||||
queue.context[0x1b4] = 2;
|
||||
const auto state = AgcDriver::Graphics::DecodeState(queue);
|
||||
Require(state.topology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, "a polygon did not decode to a triangle fan");
|
||||
Require(!state.primitiveRestart, "polygon decoding enabled primitive restart by default");
|
||||
Require(AgcDriver::Graphics::RasterPrimitiveOf(state) == ShaderRecompiler::RasterPrimitive::Triangle, "a polygon was not classified as a triangle primitive");
|
||||
Require(AgcDriver::Graphics::DrawRejection(queue, false).empty(), "the precheck rejected a direct polygon draw");
|
||||
queue.userConfig[0x24b] = 1;
|
||||
queue.context[0x103] = 0xffffffffu;
|
||||
Require(AgcDriver::Graphics::DrawRejection(queue, true).empty(), "the precheck rejected an indexed polygon draw with restart");
|
||||
const auto indexedState = AgcDriver::Graphics::DecodeState(queue);
|
||||
Require(indexedState.topology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN && indexedState.primitiveRestart, "indexed polygon decoding did not keep primitive restart");
|
||||
}
|
||||
|
||||
void retainedPixelStageTests() {
|
||||
using namespace AgcDriver::Graphics;
|
||||
auto queue = makeState();
|
||||
@@ -315,6 +332,9 @@ void stateTests() {
|
||||
queue.context[0x103] = 0xffffffffu;
|
||||
Require(AgcDriver::Graphics::DrawRejection(queue, true).empty(), "primitive restart was rejected for an indexed strip");
|
||||
Require(AgcDriver::Graphics::DecodeState(queue).primitiveRestart, "primitive restart was not decoded for a strip");
|
||||
queue.userConfig[0x242] = 21;
|
||||
Require(AgcDriver::Graphics::DrawRejection(queue, true).empty(), "primitive restart was rejected for an indexed polygon");
|
||||
Require(AgcDriver::Graphics::DecodeState(queue).primitiveRestart, "primitive restart was not decoded for a polygon");
|
||||
queue.context[0x103] = 5;
|
||||
Require(AgcDriver::Graphics::DrawRejection(queue, true).find("all ones") != std::string::npos, "a restart index other than all ones was accepted");
|
||||
queue = makeState();
|
||||
@@ -726,10 +746,10 @@ void MsaaEnableSingleSampleTests() {
|
||||
queue = enabled();
|
||||
queue.userConfig[0x242] = 1;
|
||||
Require(DrawRejection(queue, false).find("primitives other than triangles") != std::string::npos, "the precheck accepted MSAA_ENABLE on a single-sample target for points");
|
||||
for (const auto primitive : {5u, 6u}) {
|
||||
for (const auto primitive : {5u, 6u, 21u}) {
|
||||
queue = enabled();
|
||||
queue.userConfig[0x242] = primitive;
|
||||
Require(DecodeState(queue).samples == 1 && DrawRejection(queue, false).empty(), "MSAA_ENABLE on a single-sample target was refused for a triangle fan or strip");
|
||||
Require(DecodeState(queue).samples == 1 && DrawRejection(queue, false).empty(), "MSAA_ENABLE on a single-sample target was refused for a triangle fan, strip or polygon");
|
||||
}
|
||||
queue = enabled();
|
||||
queue.context[0x292] = 7;
|
||||
@@ -7095,7 +7115,7 @@ void ConservativeRasterizationTests() {
|
||||
queue.context[0x1b4] = 2;
|
||||
Require(AgcDriver::Graphics::DecodeState(queue).conservativeRasterization == VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT, "PA_SC_CONSERVATIVE_RASTERIZATION_CNTL 0x6000 enabled conservative rasterization");
|
||||
queue.context[0x313] = 0x6001;
|
||||
for (const auto primitive : {4u, 5u, 6u}) {
|
||||
for (const auto primitive : {4u, 5u, 6u, 21u}) {
|
||||
queue.userConfig[0x242] = primitive;
|
||||
Require(AgcDriver::Graphics::DecodeState(queue).conservativeRasterization == VK_CONSERVATIVE_RASTERIZATION_MODE_OVERESTIMATE_EXT, "OVER_RAST_ENABLE did not decode to overestimation for primitive type " + std::to_string(primitive));
|
||||
Require(AgcDriver::Graphics::DrawRejection(queue, false).empty(), "the precheck rejected OVER_RAST_ENABLE");
|
||||
@@ -8745,6 +8765,7 @@ int main(int argc, char** argv) {
|
||||
ShaderStageTests();
|
||||
NggVertexWorkgroupTests();
|
||||
inactiveVertexPointSizeTests();
|
||||
PolygonPrimitiveTests();
|
||||
TuningFieldTests();
|
||||
PixelInputLayoutTests();
|
||||
UnexportedPixelInputTests();
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
### Functional
|
||||
|
||||
- [Texture cache budgets](../../../core/libs/prx/libSceAgcDriver/Graphics/src/ShaderResources.cpp) (libSceAgcDriver) - the storage image cache's budget is what the reported heap budget leaves after the heap's use other than the cached storage images, the unused part of the sampled textures' 2 GiB floor and an eighth of the budget, capped at a quarter of the budget and at `TextureCacheBudget` (a quarter of the heap's size, at least 2 GiB), never below 512 MiB; the sampled cache's budget reserves `TextureCacheBudget` for the storage cache. So the sampled budget falls first while the sampled textures alive stay within their floor, and both fall together above it; each cache trims only at its next insert, a storage image is allocated before its insert reads the budget, and both budgets read the heap at most once a second, so a burst between two reads can still exceed the reported budget. The 2 GiB floor and the eighth are the sampled formula's values reused and the 512 MiB floor and the caps the earlier ones; none was measured beyond one title (PPSA11386) on one 10 GB GPU, and a title whose storage working set exceeds the shrunk budget re-creates storage images at each use.
|
||||
- [Polygon primitive type](../../../core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp) (AGC driver) - `VGT_PRIMITIVE_TYPE` 21 (`PrimitiveType::Polygon`) decodes to `VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN` and is treated as inactive for vertex point size, like triangle fans and strips. PPSA01317 (Gran Turismo 7) submits polygon draws; whether the console performs polygon-mode decomposition or custom vertex routing is unverified.
|
||||
- [Native multisampled DCC fast clears](../../../core/libs/prx/libSceAgcDriver/Graphics/src/MultisampleTarget.cpp) import uniform 0000/0001/1110/1111 keys into a single-layer, level-zero SW_64KB_R_X color image with 2, 4 or 8 fragments. Color and DCC/CMASK ranges must stay write-watched and unchanged; expanded or mixed initial DCC, register CMASK clears, compressed payloads, color transforms, lossy modes, metadata changes, guest publication and writes over a live owner throw. Driver-mediated reads of the color and metadata stay guarded. The metadata extent follows [AMD Addrlib](https://github.com/GPUOpen-Drivers/pal/blob/c5e800072a32f68b6ccc4422936d96167c6e0728/src/core/imported/addrlib/src/gfx10/gfx10addrlib.cpp#L347-L454) with the [PS5 Mesa model](https://github.com/mihawk-99/PS5_Mesa/blob/0b2d6d1a61d9bbf89cf8beb88a696144f67c61f8/src/amd/vulkan/winsys/ps5/radv_ps5_winsys.c): GFX10.1, 16 pipes, 256-byte interleave, two maximum compressed fragments. Console geometry, concurrent guest mutation and transitions outside this subset are unverified.
|
||||
|
||||
- [Initial stencil state](../../../core/libs/prx/libSceAgcDriver/Execution/include/QueueState.hpp) uses zero for `DB_STENCIL_CONTROL`, `DB_STENCILREFMASK` and `DB_STENCILREFMASK_BF` (context `0x10b`-`0x10d`), including after `CLEAR_STATE`. The public V0, V4, V5 and V7-V11 [register-default tables](../../../core/libs/prx/libSceAgc/Command/include/RegisterDefaultsData.hpp) supply these values. Linux's [GFX10 clear-state table](https://github.com/torvalds/linux/blob/master/drivers/gpu/drm/amd/amdgpu/clearstate_gfx10.h) agrees on the control register but uses `0x01000000` for the reference masks; the console reset values have not been measured. Planet Coaster (PPSA01736 v01.017) enables stencil tests without writing the control register.
|
||||
|
||||
Reference in new issue
Block a user