Skip to content

feat(agc): apply the color logic operation of CB_COLOR_CONTROL - #9348

Merged
oneandonlydean merged 3 commits into
boykopovar:mainfrom
klosixgaming-arch:feat/agc-color-logic-op
Oct 24, 2026
Merged

oneandonlydean merged 3 commits into
boykopovar:mainfrom
klosixgaming-arch:feat/agc-color-logic-op

Conversation

@klosixgaming-arch

@klosixgaming-arch klosixgaming-arch commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

What

CB_COLOR_CONTROL carries a ROP3 code in bits 16 to 23. The driver accepted only the copy code (0xcc) and threw for every other one, so a draw that asks for a color logic operation stopped the process. The code is now decoded into the draw state (State::colorRop), keyed in the pipeline cache key and in the pipeline journal, and applied through the Vulkan logic operation of the color blend state. The device enables the logicOp feature when it has it.

Cyberpunk 2077 (PPSA03974) stops with this about 31 minutes into a session, after character creation:
AGC graphics: only normal color rendering with copy ROP is supported (CB_COLOR_CONTROL 0x005a0010, mode normal)
ROP3 0x5a with mode normal.

Reading of the code: CB_COLOR_CONTROL.ROP3 takes 28 codes, in two forms: source and destination (pqrspqrs, 0xcc is copy) or brush and destination (pqpqrsrs, the brush is the shader color), as the R6xx 3D register reference describes the field and Mesa's ROP3 enum lists (both quoted by wachi35676 in this PR; I could not open them myself). In both forms bits 7:6 and 1:0 hold the same function, so LogicOpFromRop reads bits 0, 1, 6 and 7. That makes 0xcc copy, 0x66 and 0x5a XOR, 0x88 and 0xa0 AND, 0xee and 0xfa OR.

Throws rather than guessing:

  • a code that combines source and brush (outside the 28)
  • a logic operation together with blending on any color export
  • a device without the logicOp feature
  • a logic operation on a color target that is not an allowlisted normalized or integer format (sRGB, floating-point and packed-float targets throw)

The pipeline journal file format moves from 6 to 7 because the state it stores gains a field. #8365 and #8542 change the line that holds that constant, so whichever of them merges second needs a trivial rebase.

Tested

Windows 11 (10.0.26200), NVIDIA GeForce RTX 5090, driver 617.42, WinLibs GCC 15.2.0, Release, on main a6646f8. Vulkan validation layer 1.4.363 (VK_LAYER_KHRONOS_validation, inserted for the instance in the run), ANYPS5_REQUIRE_VULKAN=1, ANYPS5_NO_SHADER_CACHE=1.

  • New agc_driver_color_logic_op (tests/execution/ColorLogicOp.cpp): fills a 64x16 R8G8B8A8 target with a byte pattern, draws a covering triangle that exports (0.2, 0.4, 0.6, 0.8) (bytes 0x33, 0x66, 0x99, 0xcc) with ROP 0xcc, 0x5a, 0x88, 0xee and 0xcc again, and checks every byte against copy, XOR, AND, OR and copy. Passes. It skips on a device without logicOp.
  • agc_driver_graphics: new decode cases (0x5a0010 decodes to colorRop 0x5a and VK_LOGIC_OP_XOR, the copy code decodes as copy, fourteen ROP3 codes map to the expected operation, exactly 28 of the 256 codes are accepted, 0x5b is refused, a logic operation with blending throws). Passes. The existing check that CB_COLOR_CONTROL 0xcc0013 is refused with "copy ROP" still passes.
  • Neighbouring tests that build pipelines with the default state: agc_driver_color1555_target, agc_driver_packed_unorm_color_target, agc_driver_dual_source_blend, agc_driver_reversed_order_blend. All pass.
  • With the validation layer: agc_driver_graphics, agc_driver_color_logic_op, agc_driver_color1555_target and agc_driver_dual_source_blend produced 0 VUID-.
  • On main the new tests cannot be built because State::colorRop does not exist. What main does with the draw is the message above, taken from the game log.
  • Also agc_pipeline_journal, agc_pipeline_journal_long_paths and agc_pipeline_journal_extended_paths (journal format 7): pass.
  • python tools/check_conventions.py --base origin/main: passed.

I have not run the game on this build yet, so I do not claim it gets past the stop in the title or that the XOR output looks right there; the tests show the logic operation is applied to the target bytes as specified.

Checklist

  • Based on current main; no other open PR implements the same functions (the overlap check lists file overlaps only)
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw; the assumption about the ROP3 reading is listed in the library's technical debt file
  • No notes, investigation .md files or images added to the repository
  • New third-party code is a submodule built from source (none added)
  • Generic behaviour, not specific to one title
  • Depends on: none
  • Fixes: none
  • Unblocks: PPSA03974 (not yet confirmed on the title)
  • GPUs tested: NVIDIA GeForce RTX 5090, driver 617.42, Windows 11 10.0.26200
  • AI-assisted: yes

AI-assisted: yes. Written with AI assistance and reviewed by me.

@github-actions github-actions Bot added the unblocks title Names a title ID on the Unblocks line label Oct 21, 2026
@github-actions

github-actions Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

Other open pull requests touch the same code. Merging one will break the other, or both implement the same thing. If this one builds on them, list them in Depends on.

Pull request Conflicting files (lines on main) Same exports Same new files
PR 6612 core/libs/prx/libSceAgcDriver/Graphics/src/PipelineJournal.cpp L50
PR 8365 core/libs/prx/libSceAgcDriver/Graphics/src/PipelineJournal.cpp L50
PR 8542 core/libs/prx/libSceAgcDriver/Graphics/src/PipelineJournal.cpp L50
PR 10249 core/libs/prx/libSceAgcDriver/Graphics/include/State.hpp L154-155
PR 10351 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp L424, L1777-1778, L3973
core/libs/prx/libSceAgcDriver/Graphics/include/Context.hpp L215

Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.

Pull request Shared files not compared
PR 1191 core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
PR 1368 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/include/State.hpp
PR 1395 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/State.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 1896 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 2434 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
docs/dev/debt/libSceAgcDriver.md
PR 4040 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 4072 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/Context.hpp
PR 4448 docs/dev/debt/libSceAgcDriver.md
PR 4472 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/Context.hpp
PR 5021 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 5058 docs/dev/debt/libSceAgcDriver.md
PR 5371 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 5372 docs/dev/debt/libSceAgcDriver.md
PR 5441 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 5609 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawRegisterKey.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Pipeline.cpp
PR 5925 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Pipeline.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/PipelineJournal.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6146 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/State.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6186 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/debt/libSceAgcDriver.md
PR 6187 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6188 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
PR 6192 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6194 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6202 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 6209 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6223 docs/dev/debt/libSceAgcDriver.md
PR 6235 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawRegisterKey.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/State.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 6273 docs/dev/debt/libSceAgcDriver.md
PR 6280 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6300 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/debt/libSceAgcDriver.md
PR 6412 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/debt/libSceAgcDriver.md
PR 6481 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/include/Context.hpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6539 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawRegisterKey.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Pipeline.cpp
PR 6548 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6549 docs/dev/debt/libSceAgcDriver.md
PR 6642 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 6804 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/Context.hpp
core/libs/prx/libSceAgcDriver/Graphics/include/State.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6808 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6867 docs/dev/debt/libSceAgcDriver.md
PR 6959 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/include/State.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Pipeline.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/PipelineJournal.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 6960 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 6977 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawRegisterKey.cpp
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/State.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
docs/dev/debt/libSceAgcDriver.md
PR 7048 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 7201 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/Pipeline.cpp
PR 7223 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 7256 core/libs/prx/libSceAgcDriver/Graphics/include/State.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 7275 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/Context.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Pipeline.cpp
PR 7369 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 7410 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 7449 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
docs/dev/debt/libSceAgcDriver.md
PR 7457 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 7484 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/Context.hpp
PR 7604 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/debt/libSceAgcDriver.md
PR 7642 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/Context.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Pipeline.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/PipelineJournal.cpp
docs/dev/debt/libSceAgcDriver.md
PR 7668 core/libs/prx/libSceAgcDriver/Graphics/include/State.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 7677 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 7910 docs/dev/debt/libSceAgcDriver.md
PR 8004 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 8014 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
docs/dev/debt/libSceAgcDriver.md
PR 8212 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/PipelineJournal.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 8223 docs/dev/debt/libSceAgcDriver.md
PR 8246 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 8319 docs/dev/debt/libSceAgcDriver.md
PR 8484 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 8592 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/debt/libSceAgcDriver.md
PR 9193 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 9335 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawRegisterKey.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/State.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/PipelineJournal.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9356 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/Context.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Pipeline.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9387 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/Context.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Pipeline.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9393 docs/dev/debt/libSceAgcDriver.md
PR 9400 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
PR 9401 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/src/Pipeline.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/PipelineJournal.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9431 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawRegisterKey.cpp
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/State.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9432 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawRegisterKey.cpp
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/State.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9489 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawRegisterKey.cpp
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/Context.hpp
core/libs/prx/libSceAgcDriver/Graphics/include/State.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Pipeline.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/PipelineJournal.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 9533 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/include/State.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9592 docs/dev/debt/libSceAgcDriver.md
PR 9672 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawRegisterKey.cpp
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/State.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9673 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawRegisterKey.cpp
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/State.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9674 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawRegisterKey.cpp
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/State.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9675 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawRegisterKey.cpp
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/State.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9676 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawRegisterKey.cpp
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/State.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9700 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/include/State.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9717 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/include/State.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9742 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Graphics/include/State.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9842 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawRegisterKey.cpp
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/State.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9852 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 9875 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 9891 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawRegisterKey.cpp
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/State.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9892 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawRegisterKey.cpp
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/State.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9893 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawRegisterKey.cpp
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/State.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9895 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawRegisterKey.cpp
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/State.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9897 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 9898 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
docs/dev/debt/libSceAgcDriver.md
PR 9904 docs/dev/debt/libSceAgcDriver.md
PR 9905 docs/dev/debt/libSceAgcDriver.md
PR 9906 docs/dev/debt/libSceAgcDriver.md
PR 9969 core/libs/prx/libSceAgcDriver/CMakeLists.txt
PR 10046 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/Context.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Pipeline.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 10049 core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 10193 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/Context.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Pipeline.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/PipelineJournal.cpp
docs/dev/debt/libSceAgcDriver.md
PR 10233 core/libs/prx/libSceAgcDriver/CMakeLists.txt
docs/dev/debt/libSceAgcDriver.md
PR 10348 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawRegisterKey.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/State.hpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
PR 10420 core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawRegisterKey.cpp
core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/Context.hpp
core/libs/prx/libSceAgcDriver/Graphics/include/State.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/Pipeline.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/PipelineJournal.cpp
core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 10472 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 10515 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawRegisterKey.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/State.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 10581 core/libs/prx/libSceAgcDriver/CMakeLists.txt
core/libs/prx/libSceAgcDriver/Execution/src/Driver/Draw/DrawRegisterKey.cpp
core/libs/prx/libSceAgcDriver/Graphics/include/State.hpp
core/libs/prx/libSceAgcDriver/Graphics/src/State.cpp
core/libs/prx/libSceAgcDriver/tests/Graphics.cpp
docs/dev/debt/libSceAgcDriver.md
PR 10678 core/libs/prx/libSceAgcDriver/Execution/src/VulkanDevice.cpp

@wachi35676

Copy link
Copy Markdown
Contributor

AMD run and a source for the ROP3 reading. Head b142ad1f merged onto main a6dcea927 (clean merge, 9cf202581).

Host: Windows 11 (10.0.26300), Ryzen 5 9600X, WinLibs GCC 15.2.0, Release. GPUs: NVIDIA RTX 5070 Ti (617.42) and AMD Radeon RDNA2 iGPU 1002:13c0 (proprietary 32.0.21042.62, ANYPS5_GPU=AMD). ANYPS5_REQUIRE_VULKAN=1 ANYPS5_NO_SHADER_CACHE=1, no validation layer.

  • agc_driver_color_logic_op passes on both GPUs, with GPL and with APS5_NO_GPL=1. The AMD device exposes logicOp, so the test runs on AMD rather than skipping.
  • Negative control: with only blend.logicOpEnable = VK_TRUE changed to VK_FALSE in Pipeline.cpp, the test fails on both GPUs with ROP3 0x5a into an 8_8_8_8 unorm target: pixel (0, 0) channel 0 is 51, expected 56. 51 is the copied source byte 0x33.
  • 82-test related set (agc_driver_graphics*, the color-target, blend and pipeline-journal tests including agc_pipeline_journal* after the format 6→7 bump, mesh, indirect and others): the results match main on both GPUs. The only failures are main's existing local ones (image_array_window_past_layer_limit does not build under MinGW; agc_driver_tessellation fails on AMD).
  • tools/check_conventions.py --base a6dcea927 passes.

On the reading of the code ("no register documentation confirms the pattern operand is the source color"):

  • AMD's R6xx 3D register reference (x.org docs/AMD/old/R6xx_3D_Registers.pdf), CB_COLOR_CONTROL.ROP3 [23:16], says: "This field supports the 28 boolean ops that combine either source and dest or brush and dest, with brush provided by the shader in place of source. ROP3 codes that use both src and brush are emulated in software. Allowed ROP3 codes have either the form pqrspqrs (for source/dest ops) or pqpqrsrs (for brush/dest ops). The code 0xCC (11001100) copies the source to the destination". 0x5a (01011010) has the brush/dest form, so it is brush XOR dest, and the brush is the shader color.
  • Mesa's src/amd/registers/gfx10.json ROP3 enum has exactly those 28 values: 16 named source/dest codes (0x66 XOR, 0x88 AND, …) and 12 X_0X.. codes (0x05, 0x0a, 0x0f, 0x50, 0x5a, 0x5f, 0xa0, 0xa5, 0xaf, 0xf0, 0xf5, 0xfa), which are the brush/dest functions. radeonsi writes func | func << 4 (si_state.c) and RADV writes the V_028808_ROP3_* values.
  • For both allowed forms, bits 7:6 and 1:0 hold the same function, so LogicOpFromRop's index from bits 0, 1, 6 and 7 gives the same VkLogicOp whether the code is the source or the brush form. The table also matches Mesa's PIPE_LOGICOP order. The debt line could cite this instead of saying no documentation exists. A code that uses both src and brush (outside both forms) is "emulated in software" on the console. The PR maps such codes as if brush were source. Throwing on codes outside the two forms might be safer.

AI-assisted: yes (Claude Code); results above were run on this machine.

@klosixgaming-arch

Copy link
Copy Markdown
Contributor Author

@wachi35676 thank you for the AMD run, the negative control and the register reference. Both points are in ce5950d (rebased onto main a6646f8).

  • The debt line now cites the source/dest form pqrspqrs and the brush/dest form pqpqrsrs (the brush is the shader color) instead of saying nothing confirms the reading. I took the wording from your quote; I could not download the R6xx reference or Mesa's gfx10.json myself, so please say if I misread either.
  • A code that combines source and brush now throws. documentedRop accepts a code when its high nibble equals its low nibble (source form) or (rop >> 2) & 0x33 equals rop & 0x33 (brush form); exactly 28 of the 256 codes pass, and the test counts them. CB_COLOR_CONTROL with such a code is refused with "source or brush form" in the decode, and LogicOpFromRop throws for it (0x5b is the case in the test).

Rerun on main a6646f8 with this head (RTX 5090, validation layer 1.4.363 on the four tests marked V): agc_driver_graphics V, agc_driver_color_logic_op V, agc_driver_color1555_target V, agc_driver_dual_source_blend V, agc_driver_packed_unorm_color_target, agc_driver_reversed_order_blend, agc_pipeline_journal, agc_pipeline_journal_long_paths, agc_pipeline_journal_extended_paths all pass; 0 VUID-. check_conventions passes.

AI-assisted: yes. Written with AI assistance and reviewed by me.

@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 23, 2026
The driver refused every ROP3 code but copy, so a draw that asks for a
logic operation stopped the process. The code is decoded into the draw
state, keyed in the pipeline cache and the pipeline journal, and applied
through the Vulkan logic operation of the color blend state.

The field accepts the 28 codes of the source and destination form and of
the brush and destination form, where the brush is the shader color; both
keep their function in bits 0, 1, 6 and 7. A code that combines source and
brush, blending together with a logic operation, a device without the
logicOp feature, and a color target that is not a normalized or integer
format throw.

The pipeline journal format moves to 7.

AI-assisted: yes. Written with AI assistance and reviewed by me.

@MarcZX10 MarcZX10 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed exact head 191ddda. The ROP3 decoding is confined to the documented source/brush forms; pipeline state, cache key, register decode key, and journal codec all include the operation, and unsupported blend/format/device combinations fail explicitly. The added tests exercise the logic-op byte results, code mapping/refusal, and journal format; the PR reports zero Vulkan validation VUIDs on the listed Windows/NVIDIA runs. Local diff check, conventions, and test-registration checks pass. I could not run the AGC executable in this host: the available older AnyPS5 test binary aborts before startup because this CPU lacks required x86 extensions. The PR reports the new tests cannot be built on main because State::colorRop is absent there; hosted product jobs are skipped. The Cyberpunk title behavior remains unverified, as the PR states.

@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 23, 2026
@oneandonlydean oneandonlydean self-assigned this Oct 23, 2026
@github-actions github-actions Bot added the needs rebase Conflicts with main, rebase needed label Oct 23, 2026
encodeState and decodeState carry colorRop, which changes the recipe codec. Main's journal format is already 9, so the bump to 9 this branch made is a no-op; use 10.
@github-actions github-actions Bot removed the needs rebase Conflicts with main, rebase needed label Oct 24, 2026
@oneandonlydean
oneandonlydean merged commit 1009187 into boykopovar:main Oct 24, 2026
10 checks passed
milescoviello added a commit to milescoviello/AnyPS5 that referenced this pull request Oct 24, 2026
The pipeline journal guards State and ShaderStages, which this branch
extends. The recipe codec and canonical state now carry the hull wave
size, the geometry stage after tessellation, the merged hull flag
(TessellationConfiguration keeps its size, so its guard can't see it)
and rasterizer discard, and the journal format becomes 12 (main took 5
for the recipe codec change of boykopovar#5656, 6 for the polygon modes of boykopovar#7869,
7 for the truncated coverage of boykopovar#8115, 8 for the point lists of boykopovar#6801
9 for the 4_4_4_4 UNORM target merges of boykopovar#8564 and 10 for the colour
logic operation of boykopovar#9348; boykopovar#8365 uses 11, and the number is set to main+1
when this lands). A draw's tessellation capture validates against that draw's
capture buffers, which a replay doesn't have, so it isn't journaled.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
milescoviello added a commit to milescoviello/AnyPS5 that referenced this pull request Oct 24, 2026
The pipeline journal guards State and ShaderStages, which this branch
extends. The recipe codec and canonical state now carry the hull wave
size, the geometry stage after tessellation, the merged hull flag
(TessellationConfiguration keeps its size, so its guard can't see it)
and rasterizer discard, and the journal format becomes 12 (main took 5
for the recipe codec change of boykopovar#5656, 6 for the polygon modes of boykopovar#7869,
7 for the truncated coverage of boykopovar#8115, 8 for the point lists of boykopovar#6801
9 for the 4_4_4_4 UNORM target merges of boykopovar#8564 and 10 for the colour
logic operation of boykopovar#9348; boykopovar#8365 uses 11, and the number is set to main+1
when this lands). A draw's tessellation capture validates against that draw's
capture buffers, which a replay doesn't have, so it isn't journaled.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
milescoviello added a commit to milescoviello/AnyPS5 that referenced this pull request Oct 25, 2026
The pipeline journal guards State and ShaderStages, which this branch
extends. The recipe codec and canonical state now carry the hull wave
size, the geometry stage after tessellation, the merged hull flag
(TessellationConfiguration keeps its size, so its guard can't see it)
and rasterizer discard, and the journal format becomes 12 (main took 5
for the recipe codec change of boykopovar#5656, 6 for the polygon modes of boykopovar#7869,
7 for the truncated coverage of boykopovar#8115, 8 for the point lists of boykopovar#6801
9 for the 4_4_4_4 UNORM target merges of boykopovar#8564 and 10 for the colour
logic operation of boykopovar#9348; boykopovar#8365 uses 11, and the number is set to main+1
when this lands). A draw's tessellation capture validates against that draw's
capture buffers, which a replay doesn't have, so it isn't journaled.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
milescoviello added a commit to milescoviello/AnyPS5 that referenced this pull request Oct 27, 2026
Module records are SPIR-V and take almost all of a journal's bytes, so
APS5_PIPELINE_JOURNAL_MAX_MIB fills with modules and later pipelines
are not recorded (boykopovar#8309). A module record now keeps its identity, stage
and encoded size, followed by a zstd frame (level 1) of the encoded
result; EncodeModule writes it, and loading and replay expand it before
decoding. The journal format becomes 11: main is at 10 (8 for the point
lists of boykopovar#6801, 9 for the 4_4_4_4 UNORM targets of boykopovar#8564, 10 for the
colour logic operation of boykopovar#9348).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
milescoviello added a commit to milescoviello/AnyPS5 that referenced this pull request Nov 1, 2026
Module records are SPIR-V and take almost all of a journal's bytes, so
APS5_PIPELINE_JOURNAL_MAX_MIB fills with modules and later pipelines
are not recorded (boykopovar#8309). A module record now keeps its identity, stage
and encoded size, followed by a zstd frame (level 1) of the encoded
result; EncodeModule writes it, and loading and replay expand it before
decoding. The journal format becomes 11: main is at 10 (8 for the point
lists of boykopovar#6801, 9 for the 4_4_4_4 UNORM targets of boykopovar#8564, 10 for the
colour logic operation of boykopovar#9348).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agc libSceAgc* build docs unblocks title Names a title ID on the Unblocks line

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants