diff --git a/src/graphics/guest_gpu/command_processor/pm4Dispatch.cpp b/src/graphics/guest_gpu/command_processor/pm4Dispatch.cpp index c9d587ede..12096d862 100644 --- a/src/graphics/guest_gpu/command_processor/pm4Dispatch.cpp +++ b/src/graphics/guest_gpu/command_processor/pm4Dispatch.cpp @@ -35,7 +35,6 @@ constexpr auto MakeContextDispatchTable() { } g_hw_ctx_func[Pm4::CB_TARGET_MASK] = HwCtxSetRenderTargetMask; g_hw_ctx_func[Pm4::PA_SC_GENERIC_SCISSOR_TL] = HwCtxSetGenericScissor; - g_hw_ctx_func[Pm4::CB_BLEND_RED] = HwCtxSetBlendColor; g_hw_ctx_func[Pm4::CB_DCC_CONTROL] = HwCtxSetCbDccControl; g_hw_ctx_func[Pm4::DB_STENCIL_CONTROL] = HwCtxSetStencilControl; g_hw_ctx_func[Pm4::DB_STENCILREFMASK] = HwCtxSetStencilMask; diff --git a/src/graphics/guest_gpu/command_processor/pm4Dispatch.h b/src/graphics/guest_gpu/command_processor/pm4Dispatch.h index e172605c5..a3596ca34 100644 --- a/src/graphics/guest_gpu/command_processor/pm4Dispatch.h +++ b/src/graphics/guest_gpu/command_processor/pm4Dispatch.h @@ -56,7 +56,6 @@ uint32_t HwCtxSetWindowScissor(CommandProcessor&, uint32_t, uint32_t, const uint uint32_t HwCtxSetClipRect(CommandProcessor&, uint32_t, uint32_t, const uint32_t*, uint32_t); uint32_t HwCtxSetRenderTargetMask(CommandProcessor&, uint32_t, uint32_t, const uint32_t*, uint32_t); uint32_t HwCtxSetGenericScissor(CommandProcessor&, uint32_t, uint32_t, const uint32_t*, uint32_t); -uint32_t HwCtxSetBlendColor(CommandProcessor&, uint32_t, uint32_t, const uint32_t*, uint32_t); uint32_t HwCtxSetCbDccControl(CommandProcessor&, uint32_t, uint32_t, const uint32_t*, uint32_t); uint32_t HwCtxSetStencilControl(CommandProcessor&, uint32_t, uint32_t, const uint32_t*, uint32_t); uint32_t HwCtxSetStencilMask(CommandProcessor&, uint32_t, uint32_t, const uint32_t*, uint32_t); diff --git a/src/graphics/guest_gpu/command_processor/pm4Handlers.cpp b/src/graphics/guest_gpu/command_processor/pm4Handlers.cpp index 40e9d7a6e..58f1a0196 100644 --- a/src/graphics/guest_gpu/command_processor/pm4Handlers.cpp +++ b/src/graphics/guest_gpu/command_processor/pm4Handlers.cpp @@ -530,22 +530,6 @@ KYTY_HW_CTX_PARSER(HwCtxSetAaMask) { return num_values; } -KYTY_HW_CTX_PARSER(HwCtxSetBlendColor) { - EXIT_NOT_IMPLEMENTED(cmd_id != 0xc0046900); - EXIT_NOT_IMPLEMENTED(cmd_offset != Pm4::CB_BLEND_RED); - - HW::BlendColor r; - - r.red = *reinterpret_cast(&buffer[0]); - r.green = *reinterpret_cast(&buffer[1]); - r.blue = *reinterpret_cast(&buffer[2]); - r.alpha = *reinterpret_cast(&buffer[3]); - - cp.GetCtx().SetBlendColor(r); - - return 4; -} - KYTY_HW_CTX_PARSER(HwCtxSetBlendControl) { EXIT_NOT_IMPLEMENTED(cmd_id != 0xC0016900); diff --git a/src/graphics/guest_gpu/pm4.h b/src/graphics/guest_gpu/pm4.h index 076761f51..8a7bc250d 100644 --- a/src/graphics/guest_gpu/pm4.h +++ b/src/graphics/guest_gpu/pm4.h @@ -317,8 +317,8 @@ constexpr uint32_t FSR_RECURSIONS1 = 0xF2; constexpr uint32_t VGT_MULTI_PRIM_IB_RESET_INDX = 0x103; constexpr uint32_t CB_RMI_GL2_CACHE_CONTROL = 0x104; constexpr uint32_t CB_BLEND_RED = 0x105; -constexpr uint32_t CB_BLEND_GREEN = 0x106; -constexpr uint32_t CB_BLEND_BLUE = 0x107; +constexpr uint32_t CB_BLEND_BLUE = 0x106; +constexpr uint32_t CB_BLEND_GREEN = 0x107; constexpr uint32_t CB_BLEND_ALPHA = 0x108; constexpr uint32_t CB_DCC_CONTROL = 0x109; diff --git a/tests/ShaderRecompilerComputeTests.cpp b/tests/ShaderRecompilerComputeTests.cpp index cde162f3c..4e1695e30 100644 --- a/tests/ShaderRecompilerComputeTests.cpp +++ b/tests/ShaderRecompilerComputeTests.cpp @@ -22146,6 +22146,71 @@ void CheckPm4GuardBandRegisterRanges(RenderContext &renderer) { std::printf("[host] %-32s ok\n", "Pm4GuardBandRegisterRanges"); } +void CheckPm4BlendColorRegisterRanges(RenderContext &renderer) { + GraphicsInitJmpTables(); + CommandProcessor processor(renderer); + processor.GetCtx().SetBlendColor({1.0f, 2.0f, 3.0f, 4.0f}); + + constexpr std::array, 4> singleton_values{{ + {Pm4::CB_BLEND_RED, 5.0f}, + {Pm4::CB_BLEND_BLUE, 7.0f}, + {Pm4::CB_BLEND_GREEN, 6.0f}, + {Pm4::CB_BLEND_ALPHA, 8.0f}, + }}; + bool singletons_complete = true; + for (const auto &[offset, value] : singleton_values) { + std::array packet{ + KYTY_PM4(3, Pm4::IT_SET_CONTEXT_REG, Pm4::R_ZERO), + offset, + std::bit_cast(value), + }; + Pm4Execution execution; + singletons_complete &= + processor.Process(execution, packet.data(), packet.size()) == + Pm4ProcessResult::Complete; + } + const auto &singletons = processor.GetCtx().GetBlendColor(); + Require("Pm4BlendColorRegisterRanges", "single registers", + singletons_complete && singletons.red == 5.0f && + singletons.green == 6.0f && singletons.blue == 7.0f && + singletons.alpha == 8.0f, + "single blend-color writes did not follow native PS5 register order"); + + std::array partial{ + KYTY_PM4(4, Pm4::IT_SET_CONTEXT_REG, Pm4::R_ZERO), + Pm4::CB_BLEND_BLUE, + std::bit_cast(9.0f), + std::bit_cast(10.0f), + }; + Pm4Execution partial_execution; + const auto partial_result = + processor.Process(partial_execution, partial.data(), partial.size()); + const auto &partial_color = processor.GetCtx().GetBlendColor(); + Require("Pm4BlendColorRegisterRanges", "partial range", + partial_result == Pm4ProcessResult::Complete && + partial_color.red == 5.0f && partial_color.green == 10.0f && + partial_color.blue == 9.0f && partial_color.alpha == 8.0f, + "partial blend-color range changed the wrong channels"); + + std::array full{ + KYTY_PM4(6, Pm4::IT_SET_CONTEXT_REG, Pm4::R_ZERO), + Pm4::CB_BLEND_RED, + std::bit_cast(11.0f), + std::bit_cast(13.0f), + std::bit_cast(12.0f), + std::bit_cast(14.0f), + }; + Pm4Execution full_execution; + const auto full_result = processor.Process(full_execution, full.data(), full.size()); + const auto &full_color = processor.GetCtx().GetBlendColor(); + Require("Pm4BlendColorRegisterRanges", "full range", + full_result == Pm4ProcessResult::Complete && full_color.red == 11.0f && + full_color.green == 12.0f && full_color.blue == 13.0f && + full_color.alpha == 14.0f, + "full blend-color range did not preserve native PS5 register order"); + std::printf("[host] %-32s ok\n", "Pm4BlendColorRegisterRanges"); +} + void CheckPm4PolygonOffsetRegisters(RenderContext &renderer) { GraphicsInitJmpTables(); CommandProcessor processor(renderer); @@ -22709,6 +22774,7 @@ int main(int argc, char **argv) { } if (argc == 2 && std::strcmp(argv[1], "--context-state-only") == 0) { VulkanHarness vulkan; + CheckPm4BlendColorRegisterRanges(vulkan.RuntimeRenderer()); CheckPm4PolygonOffsetRegisters(vulkan.RuntimeRenderer()); CheckPm4ContextStateOperations(vulkan.RuntimeRenderer()); return 0; @@ -22881,6 +22947,7 @@ int main(int argc, char **argv) { CheckPm4StencilInfoValueLane(vulkan.RuntimeRenderer()); CheckPm4DirectShaderRegisterFallback(vulkan.RuntimeRenderer()); CheckPm4GuardBandRegisterRanges(vulkan.RuntimeRenderer()); + CheckPm4BlendColorRegisterRanges(vulkan.RuntimeRenderer()); CheckPm4PolygonOffsetRegisters(vulkan.RuntimeRenderer()); CheckAgcWaitPackets(vulkan.RuntimeRenderer()); CheckPm4ContextStateOperations(vulkan.RuntimeRenderer());