Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
0e891be
feat(agc): declare a changed-only byte-output mode in the texture det…
MarcZX10 Oct 27, 2026
68bc648
feat(agc): store only the bytes that differ from the original in the …
MarcZX10 Oct 27, 2026
cacbf92
build(agc): generate the changed-only detile shader variant
MarcZX10 Oct 27, 2026
1e43767
fix(agc): size the detiler descriptor pool for three bindings per set
MarcZX10 Oct 27, 2026
65b6054
feat(agc): give the detiler a third binding and an original base
MarcZX10 Oct 27, 2026
07bebca
feat(agc): create a changed-only detile pipeline variant
MarcZX10 Oct 27, 2026
2d33adc
feat(agc): let the detiler dispatch compare against an original
MarcZX10 Oct 27, 2026
20d03fb
feat(agc): bind the original buffer and pass its base to a changed-on…
MarcZX10 Oct 27, 2026
5cd1b96
test(agc): cover the changed-only detile dispatch
MarcZX10 Oct 27, 2026
7c8f4af
refactor(agc): declare the linear draw snapshot calls on StorageTexture
MarcZX10 Oct 27, 2026
65fad46
feat(agc): snapshot a linear target when a recorded draw starts
MarcZX10 Oct 27, 2026
0029653
feat(agc): finish a linear draw's store and release its snapshot
MarcZX10 Oct 27, 2026
93fa51e
fix(agc): snapshot the linear targets of a recorded draw before its p…
MarcZX10 Oct 27, 2026
edd4ee4
fix(agc): snapshot the linear targets of a prepared recorded draw
MarcZX10 Oct 27, 2026
25822dc
fix(agc): store a resident linear target through FinishLinearDraw
MarcZX10 Oct 27, 2026
11a7992
fix(agc): keep the bytes the CPU wrote after a linear draw began
MarcZX10 Oct 27, 2026
6cb074c
fix(agc): publish the whole target after a snapshot-based write-back
MarcZX10 Oct 27, 2026
c4b85c4
fix(agc): reuse the draw snapshot as the linear buffer of a write-back
MarcZX10 Oct 27, 2026
01e833a
fix(agc): retile only the changed bytes of a linear target from its s…
MarcZX10 Oct 27, 2026
60b0444
fix(agc): compare the stored bytes with the ones before the write-back
MarcZX10 Oct 27, 2026
66505d7
fix(agc): leave the drawn-rectangle store to targets without a draw s…
MarcZX10 Oct 27, 2026
543a5ff
test(agc): include what the resident linear target test needs
MarcZX10 Oct 27, 2026
52d740a
test(agc): draw the left half of the resident linear target test's ta…
MarcZX10 Oct 27, 2026
29dcc2c
test(agc): let the resident test's draw choose its scissor, write mas…
MarcZX10 Oct 27, 2026
1e7de7e
test(agc): check queued, cached and changed-only linear target draws …
MarcZX10 Oct 27, 2026
420f045
test(agc): register the resident linear target recipe mode
MarcZX10 Oct 27, 2026
d26764a
test(agc): add a linear target concurrent bytes test
MarcZX10 Oct 27, 2026
20acd74
test(agc): add a linear target publication test
MarcZX10 Oct 27, 2026
5d752c2
test(agc): add a linear target preserved bytes test
MarcZX10 Oct 27, 2026
8868994
perf(agc): refresh a linear draw's baseline instead of re-uploading t…
MarcZX10 Oct 27, 2026
3ab861c
Merge remote-tracking branch 'upstream/main' into HEAD
MarcZX10 Nov 5, 2026
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
12 changes: 12 additions & 0 deletions core/libs/prx/libSceAgcDriver/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,17 @@ add_custom_command(
DEPENDS "${agcTextureDetileShaderSource}" glslang-standalone
VERBATIM
)
set(agcTextureDetileChangedShaderSpv ${agcTextureDetileGeneratedDir}/TextureDetileChanged.spv)
set(agcTextureDetileChangedShaderHeader ${agcTextureDetileGeneratedDir}/TextureDetileChanged_spv.h)
add_custom_command(
OUTPUT "${agcTextureDetileChangedShaderHeader}"
COMMAND ${CMAKE_COMMAND} -E make_directory "${agcTextureDetileGeneratedDir}"
COMMAND "$<TARGET_FILE:glslang-standalone>" -V --target-env vulkan1.1 -DBYTE_OUTPUT=1 -o "${agcTextureDetileChangedShaderSpv}" "${agcTextureDetileShaderSource}"
COMMAND ${CMAKE_COMMAND} -DINPUT=${agcTextureDetileChangedShaderSpv} -DOUTPUT=${agcTextureDetileChangedShaderHeader}
-DSYMBOL=TEXTURE_DETILE_CHANGED_SPV -P "${CMAKE_CURRENT_SOURCE_DIR}/embed_spirv.cmake"
DEPENDS "${agcTextureDetileShaderSource}" glslang-standalone
VERBATIM
)
set(agcTextureDetileImageShaderSpv ${agcTextureDetileGeneratedDir}/TextureDetileImage.spv)
set(agcTextureDetileImageShaderHeader ${agcTextureDetileGeneratedDir}/TextureDetileImage_spv.h)
add_custom_command(
Expand Down Expand Up @@ -466,6 +477,7 @@ set(agcDriverSources
${CMAKE_CURRENT_SOURCE_DIR}/Graphics/src/Sampler.cpp
${agcSampleOrderShaderHeaders}
${agcTextureDetileShaderHeader}
${agcTextureDetileChangedShaderHeader}
${agcReadbackHeaders}
${agcMultisampleUploadHeader}
${agcCmaskClearShaderHeader}
Expand Down
4 changes: 4 additions & 0 deletions core/libs/prx/libSceAgcDriver/Graphics/include/Texture.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
namespace AgcDriver::Graphics {

class Buffer;
class DeviceBuffer;
class ResidentColor;
class CommandBatch;
class StorageTexture;
Expand Down Expand Up @@ -290,6 +291,8 @@ class StorageTexture : public std::enable_shared_from_this<StorageTexture> {
VkImageView AttachmentProxyView();
void RecordAttachmentProxyLoad(VkCommandBuffer commands, VkImageLayout attachmentLayout) const;
void RecordAttachmentProxyStore(VkCommandBuffer commands, VkImageLayout attachmentLayout) const;
void PrepareLinearDraw();
void FinishLinearDraw();
void WriteBack();
// Deferred write-back (APS5_EAGER_WRITEBACK=1 stores at once instead).
void MarkDirty();
Expand Down Expand Up @@ -841,6 +844,7 @@ class StorageTexture : public std::enable_shared_from_this<StorageTexture> {
std::vector<bool> layerOriginal;
std::map<std::uint64_t, std::uint64_t> keptAtUnwatch;
std::shared_ptr<Buffer> savedBytes;
std::shared_ptr<DeviceBuffer> linearDrawOriginal;
std::vector<std::uint64_t> savedTicket;
std::uint64_t lastSaveTicket = 0;
// The storage cache let the image go (Flush): a lookup makes a new image of the surface, so
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ namespace AgcDriver::Graphics {
// into tiled `destination`; offsets always refer to the respective buffers, and `window`
// restricts the move to part of the mip (a partial upload or write-back, StorageTexture),
// leaving the other elements of both buffers alone.
void Dispatch(VkCommandBuffer commands, TextureTileMode tileMode, std::uint32_t elementBytes, VkBuffer source, std::uint64_t sourceOffset, VkBuffer destination, std::uint64_t destinationOffset, const TileMipLayout& layout, bool retile = false, std::uint32_t slice = 0, bool thick = false, const DetileWindow& window = {});
void Dispatch(VkCommandBuffer commands, TextureTileMode tileMode, std::uint32_t elementBytes, VkBuffer source, std::uint64_t sourceOffset, VkBuffer destination, std::uint64_t destinationOffset, const TileMipLayout& layout, bool retile = false, std::uint32_t slice = 0, bool thick = false, const DetileWindow& window = {}, std::uint64_t originalOffset = 0);
void DispatchImage(VkCommandBuffer commands, TextureTileMode tileMode, std::uint32_t elementBytes, VkBuffer tiled, std::uint64_t tiledOffset, VkImageView view, const TileMipLayout& layout, bool retile = false, std::uint32_t slice = 0, const DetileWindow& window = {});
void DispatchRepack(VkCommandBuffer commands, VkBuffer source, std::uint64_t sourceOffset, VkBuffer destination, std::uint64_t destinationOffset, std::uint64_t bytes);
static VkFormat ImageElementFormat(std::uint32_t elementBytes);
Expand All @@ -61,7 +61,7 @@ namespace AgcDriver::Graphics {
private:
VkPipeline multisampleReadbackPipeline(std::uint32_t elementBytes, bool depth);
VkPipeline multisampleUploadPipeline(std::uint32_t elementBytes);
VkPipeline pipeline(TextureTileMode tileMode, std::uint32_t elementBytes, bool retile, bool thick, bool image = false);
VkPipeline pipeline(TextureTileMode tileMode, std::uint32_t elementBytes, bool retile, bool thick, bool image = false, bool changedOnly = false);
void release() noexcept;
struct DescriptorRing {
std::vector<VkDescriptorPool> pools;
Expand All @@ -78,6 +78,7 @@ namespace AgcDriver::Graphics {
VkDescriptorSetLayout descriptorLayout = VK_NULL_HANDLE;
VkPipelineLayout pipelineLayout = VK_NULL_HANDLE;
VkShaderModule module = VK_NULL_HANDLE;
VkShaderModule changedModule = VK_NULL_HANDLE;
std::vector<std::pair<std::uint32_t, VkPipeline>> pipelines;
std::vector<std::pair<std::uint32_t, GcnTileGeometry>> gcnGeometries;
std::uint32_t layerBankXor(TextureTileMode tileMode, std::uint32_t elementBytes, const TileMipLayout& layout, std::uint32_t layer);
Expand Down
21 changes: 21 additions & 0 deletions core/libs/prx/libSceAgcDriver/Graphics/shaders/TextureDetile.comp
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
#version 450
#ifdef BYTE_OUTPUT
#extension GL_EXT_shader_8bit_storage : require
#endif
#ifdef LINEAR_IMAGE
#extension GL_EXT_shader_image_load_formatted : require
#endif
Expand Down Expand Up @@ -33,6 +36,7 @@ layout(constant_id = 22) const uint SPLIT0 = 0u;
layout(constant_id = 23) const uint SPLIT1 = 0u;
layout(constant_id = 24) const uint SPLIT2 = 0u;
layout(constant_id = 25) const uint SPLIT3 = 0u;
layout(constant_id = 26) const uint CHANGED_ONLY = 0u;

layout(local_size_x = 8, local_size_y = 8) in;

Expand All @@ -41,8 +45,13 @@ layout(set = 0, binding = 0, std430) buffer Tiled { uint data[]; } tiledBuffer;
layout(set = 0, binding = 1) uniform uimage2D linearImage;
#else
layout(set = 0, binding = 0, std430) readonly buffer Input { uint data[]; } inputBuffer;
#ifdef BYTE_OUTPUT
layout(set = 0, binding = 1, std430) writeonly buffer Output { uint8_t data[]; } outputBuffer;
#else
layout(set = 0, binding = 1, std430) buffer Output { uint data[]; } outputBuffer;
#endif
layout(set = 0, binding = 2, std430) readonly buffer Original { uint data[]; } originalBuffer;
#endif

layout(push_constant) uniform Push {
uint srcBase;
Expand All @@ -69,6 +78,7 @@ layout(push_constant) uniform Push {
uint rowBegin;
uint pipeBankXor;
uint splitStride;
uint originalBase;
} params;

uint equationBit(uint mask, uvec2 p) {
Expand Down Expand Up @@ -193,6 +203,16 @@ void loadElement(uvec2 p, uint dst) {
}
#else
void copyElement(uint src, uint dst) {
#ifdef BYTE_OUTPUT
const uint original = params.originalBase + src - params.srcBase;
for (uint offset = 0u; offset < ELEMENT_BYTES; ++offset) {
const uint currentAddress = src + offset;
const uint originalAddress = original + offset;
const uint current = (inputBuffer.data[currentAddress >> 2] >> ((currentAddress & 3u) * 8u)) & 0xffu;
const uint before = (originalBuffer.data[originalAddress >> 2] >> ((originalAddress & 3u) * 8u)) & 0xffu;
if (current != before) outputBuffer.data[dst + offset] = uint8_t(current);
}
#else
if (ELEMENT_BYTES >= 4u) {
for (uint i = 0u; i < ELEMENT_BYTES; i += 4u) {
outputBuffer.data[(dst + i) >> 2] = inputBuffer.data[(src + i) >> 2];
Expand All @@ -204,6 +224,7 @@ void copyElement(uint src, uint dst) {
atomicAnd(outputBuffer.data[dst >> 2], ~(mask << shift));
atomicOr(outputBuffer.data[dst >> 2], value << shift);
}
#endif
}
#endif

Expand Down
10 changes: 9 additions & 1 deletion core/libs/prx/libSceAgcDriver/Graphics/src/Draw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2403,7 +2403,7 @@ void keepRecordedDraw(Recorder& recorder, const std::shared_ptr<ShaderResources>
else residents[index]->MarkDirty();
}
for (std::size_t index = 0; index < residents.size(); ++index) {
if (storeNow[index]) StorageTexture::FlushPending(residents[index]->Descriptor().baseAddress, static_cast<std::size_t>(residents[index]->GuestBytes()), nullptr, "linear target");
if (storeNow[index]) residents[index]->FinishLinearDraw();
}
}

Expand Down Expand Up @@ -2706,6 +2706,9 @@ void recordDraw(const Context& context, const State& state, const Pm4::DrawParam
const bool fenced = state.depth.has_value() || !record.proxies.empty();
resources.RequireGuestBuffers();
if (UsesMeshWindow(shaders)) PrepareMeshWindow(context);
for (const auto& target : record.targets) {
if (target != nullptr) target->PrepareLinearDraw();
}
const auto start = recorder->StartDrawPass(passKey, capture || readsTarget || gpuIndirect || meshIndirect || captured || !record.staged.empty() || PixelFunctionLdsSubgroup(shaders) != 0u, fenced, passAccess);
if (record.spaceKeep != nullptr) *record.spaceKeep = reserveSpaceKeep(*recorder, resources);
for (const auto& target : record.multisampleTargets) KeepMultisampleTarget_nid_no_patch(target);
Expand Down Expand Up @@ -3687,6 +3690,11 @@ void recordPreparedDraw(const Context& context, const State& state, const Pm4::D
if (recorded && recorder->HasQueuedKeyStores() && (resources->HoldsLease() || recorder->AnyQueuedKeyStore(touches))) recorder->FlushKeyStores();
// A queued label store over such memory likewise (Recorder::RecordStore).
if (recorded && recorder->HasQueuedStores() && (resources->HoldsLease() || recorder->AnyQueuedStore(touches))) recorder->FlushStores();
if (recorded) {
for (const auto& binding : targets) {
if (binding.resident != nullptr) binding.resident->PrepareLinearDraw();
}
}
const auto commands = recorded ? recorder->Commands() : batch->Handle();
if (recorded) prepared.spaceKeep = reserveSpaceKeep(*recorder, *resources);
if (recorded) recorder->PrepareSampleSlot();
Expand Down
Loading
Loading