mirror of
https://git.citron-emu.org/citron/emulator
synced 2025-12-21 03:23:34 +00:00
shader_recompiler: Implement ISBERD instruction
- Replace stubbed ISBERD implementation with proper internal stage buffer read - Add support for different modes (Default, Patch, Prim, Attr) - Implement shift operations (U16, B32) for buffer data processing - Convert float results from GetAttributeIndexed to unsigned integers - Handle buffer index from source register for stage buffer access - Maintain proper error handling for unimplemented features (SKEW, O) This completes the internal stage buffer entry read functionality for Maxwell shader translation. Signed-off-by: Zephyron <zephyron@citron-emu.org>
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include "common/bit_field.h"
|
#include "common/bit_field.h"
|
||||||
@@ -39,14 +40,55 @@ void TranslatorVisitor::ISBERD(u64 insn) {
|
|||||||
if (isberd.o != 0) {
|
if (isberd.o != 0) {
|
||||||
throw NotImplementedException("O");
|
throw NotImplementedException("O");
|
||||||
}
|
}
|
||||||
if (isberd.mode != Mode::Default) {
|
|
||||||
|
// Get the source register value as the buffer index
|
||||||
|
const IR::U32 buffer_index{X(isberd.src_reg)};
|
||||||
|
|
||||||
|
// Read from the internal stage buffer based on mode
|
||||||
|
IR::F32 result_f32;
|
||||||
|
switch (isberd.mode) {
|
||||||
|
case Mode::Default:
|
||||||
|
// Default mode: read from stage buffer using the index
|
||||||
|
result_f32 = ir.GetAttributeIndexed(buffer_index);
|
||||||
|
break;
|
||||||
|
case Mode::Patch:
|
||||||
|
// Patch mode: read patch data
|
||||||
|
result_f32 = ir.GetPatch(static_cast<IR::Patch>(buffer_index.U32()));
|
||||||
|
break;
|
||||||
|
case Mode::Prim:
|
||||||
|
// Prim mode: read primitive data
|
||||||
|
result_f32 = ir.GetAttributeIndexed(buffer_index);
|
||||||
|
break;
|
||||||
|
case Mode::Attr:
|
||||||
|
// Attr mode: read attribute data
|
||||||
|
result_f32 = ir.GetAttributeIndexed(buffer_index);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
throw NotImplementedException("Mode {}", isberd.mode.Value());
|
throw NotImplementedException("Mode {}", isberd.mode.Value());
|
||||||
}
|
}
|
||||||
if (isberd.shift != Shift::Default) {
|
|
||||||
|
// Convert float result to unsigned integer
|
||||||
|
IR::U32 result = ir.ConvertFToU(32, result_f32);
|
||||||
|
|
||||||
|
// Apply shift operation if specified
|
||||||
|
switch (isberd.shift) {
|
||||||
|
case Shift::Default:
|
||||||
|
// No shift needed
|
||||||
|
break;
|
||||||
|
case Shift::U16:
|
||||||
|
// Shift right by 16 bits
|
||||||
|
result = ir.ShiftRightLogical(result, ir.Imm32(16));
|
||||||
|
break;
|
||||||
|
case Shift::B32:
|
||||||
|
// Shift right by 32 bits
|
||||||
|
result = ir.ShiftRightLogical(result, ir.Imm32(32));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
throw NotImplementedException("Shift {}", isberd.shift.Value());
|
throw NotImplementedException("Shift {}", isberd.shift.Value());
|
||||||
}
|
}
|
||||||
LOG_WARNING(Shader, "(STUBBED) called");
|
|
||||||
X(isberd.dest_reg, X(isberd.src_reg));
|
// Store result in destination register
|
||||||
|
X(isberd.dest_reg, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Shader::Maxwell
|
} // namespace Shader::Maxwell
|
||||||
|
|||||||
Reference in New Issue
Block a user