fix graphical bug (PPSA17221)

This commit is contained in:
nmzik
2026-07-28 02:32:10 +02:00
parent aeceaff028
commit ec11f31aa6
4 changed files with 31 additions and 9 deletions
@@ -65,10 +65,23 @@ constexpr uint32_t GcrKnownMask = GcrGl2MetadataInvalidate | GcrGl0V
GcrGl2Writeback | GcrOrder012 | GcrOrder210; GcrGl2Writeback | GcrOrder012 | GcrOrder210;
constexpr uint32_t RegisterSelectorMask = 0x70000000u; constexpr uint32_t RegisterSelectorMask = 0x70000000u;
uint32_t NormalizeRegisterOffset(uint32_t raw_offset) { constexpr uint32_t NormalizeRegisterOffset(uint32_t raw_offset) {
return (raw_offset & ~RegisterSelectorMask); return raw_offset & ~RegisterSelectorMask;
} }
// Indirect Cx descriptors retain their selector. Selector 1 offsets 0..31 address the
// SPI_PS_INPUT_CNTL register bank; ordinary context-register offsets remain unchanged.
constexpr uint32_t DecodeIndirectCxRegisterOffset(uint32_t raw_offset) {
const auto offset = NormalizeRegisterOffset(raw_offset);
return (raw_offset & RegisterSelectorMask) == Pm4::CX_PS_SHADER_USAGE_BASE && offset < 32u
? Pm4::SPI_PS_INPUT_CNTL_0 + offset
: offset;
}
static_assert(DecodeIndirectCxRegisterOffset(Pm4::CX_PS_SHADER_USAGE_BASE + 2u) ==
Pm4::SPI_PS_INPUT_CNTL_0 + 2u);
static_assert(DecodeIndirectCxRegisterOffset(Pm4::DB_Z_INFO) == Pm4::DB_Z_INFO);
bool ReleaseMemGcrNeedsBarrier(uint32_t eop_event_type, uint32_t gcr_cntl) { bool ReleaseMemGcrNeedsBarrier(uint32_t eop_event_type, uint32_t gcr_cntl) {
return eop_event_type != 0x28u || return eop_event_type != 0x28u ||
(gcr_cntl & (GcrGl2MetadataInvalidate | GcrGl0VectorInvalidate | GcrGl1Invalidate | (gcr_cntl & (GcrGl2MetadataInvalidate | GcrGl0VectorInvalidate | GcrGl1Invalidate |
@@ -2321,14 +2334,18 @@ KYTY_CP_OP_PARSER(CpOpIndirectCxRegs) {
EXIT("indirect CX registers have null address, num_regs = %" PRIu32 "\n", indirect_num_dw); EXIT("indirect CX registers have null address, num_regs = %" PRIu32 "\n", indirect_num_dw);
} }
for (uint32_t i = 0; i < indirect_num_dw; i++, indirect_buffer += 2) { for (uint32_t i = 0; i < indirect_num_dw; i++, indirect_buffer += 2) {
auto cmd_offset = indirect_buffer[0]; // Keep the encoded offset for packet control values, and use the decoded offset only
auto value = indirect_buffer[1]; // for register dispatch.
auto raw_cmd_offset = indirect_buffer[0];
auto cmd_offset = DecodeIndirectCxRegisterOffset(raw_cmd_offset);
auto value = indirect_buffer[1];
if (HwCtxTrySetFakeRegister(cmd_offset, value)) { if (HwCtxTrySetFakeRegister(cmd_offset, value)) {
continue; continue;
} }
if (cmd_offset == 0xffffffffu) { // The sentinel is an encoded descriptor value and must be checked before normalization.
if (raw_cmd_offset == 0xffffffffu) {
static bool logged = false; static bool logged = false;
if (!logged) { if (!logged) {
LOGF("\t temporary: skipping indirect CX sentinel pair offset = 0xffffffff, value " LOGF("\t temporary: skipping indirect CX sentinel pair offset = 0xffffffff, value "
+3
View File
@@ -385,6 +385,9 @@ constexpr uint32_t SPI_SHADER_POS_FORMAT = 0x1C3;
constexpr uint32_t SPI_SHADER_Z_FORMAT = 0x1C4; constexpr uint32_t SPI_SHADER_Z_FORMAT = 0x1C4;
constexpr uint32_t SPI_SHADER_COL_FORMAT = 0x1C5; constexpr uint32_t SPI_SHADER_COL_FORMAT = 0x1C5;
// Indirect Cx descriptor selector for the 32-entry PS input-control register bank.
constexpr uint32_t CX_PS_SHADER_USAGE_BASE = 0x10000000u;
constexpr uint32_t CB_BLEND0_CONTROL = 0x1E0; constexpr uint32_t CB_BLEND0_CONTROL = 0x1E0;
constexpr uint32_t CB_BLEND0_CONTROL_COLOR_SRCBLEND_SHIFT = 0; constexpr uint32_t CB_BLEND0_CONTROL_COLOR_SRCBLEND_SHIFT = 0;
constexpr uint32_t CB_BLEND0_CONTROL_COLOR_SRCBLEND_MASK = 0x1F; constexpr uint32_t CB_BLEND0_CONTROL_COLOR_SRCBLEND_MASK = 0x1F;
+3 -1
View File
@@ -798,7 +798,9 @@ static void ShaderGetStaticInputInfoPS(
ps_info = {}; ps_info = {};
ps_info.input_num = sh.ps_in_control; // SPI_PS_IN_CONTROL.NUM_INTERP occupies bits 5:0. Keep the remaining control
// flags in the hardware state and extract only the input count here.
ps_info.input_num = sh.ps_in_control & 0x3fu;
ps_info.ps_system_input_base = ShaderCalcPsSystemInputBase(sh); ps_info.ps_system_input_base = ShaderCalcPsSystemInputBase(sh);
const uint32_t active_inputs = sh.ps_input_ena & sh.ps_input_addr; const uint32_t active_inputs = sh.ps_input_ena & sh.ps_input_addr;
ps_info.ps_pos_x = (active_inputs & 0x00000100u) != 0; ps_info.ps_pos_x = (active_inputs & 0x00000100u) != 0;
+3 -3
View File
@@ -1217,9 +1217,9 @@ static const ShaderSemantic* find_interpolant_output_semantic(const Shader* gs,
} }
static void set_interpolant_register(ShaderRegister* regs, uint32_t index, uint32_t value) { static void set_interpolant_register(ShaderRegister* regs, uint32_t index, uint32_t value) {
// The native implementation writes a descriptor offset (0x10000000 + index). Kyty stores // Interpolant mappings contain encoded Cx descriptors. Indirect PM4 ingestion resolves
// decoded PM4 register offsets here because direct/custom indirect paths consume them. // this selector and slot to the physical SPI_PS_INPUT_CNTL register.
regs[index].offset = Pm4::SPI_PS_INPUT_CNTL_0 + index; regs[index].offset = Pm4::CX_PS_SHADER_USAGE_BASE + index;
regs[index].value = value; regs[index].value = value;
} }