mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-12-10 05:38:49 +00:00
Random fixes (#3216)
* buffer_cache: Handle inline data to flexible memory
* control_flow: Fix single instruction scopes edge case
Fixes the following pattern
v_cmpx_gt_u32 cond
buffer_store_dword value
.LABEL:
Before
buffer[index] = value;
After
if (cond)
{
buffer[index] = value;
}
* vector_memory: Handle soffset when offen is false
When offen is not used we can substitute the offset argument with soffset and have it handled correctly
* scalar_alu: Handle sharp moves with S_MOV_B64
This fixes unable to track sharp errors when this pattern is used in a shader
* emulator: Add log
* video_core: Bump binary info search range and buffer num
This commit is contained in:
@@ -188,14 +188,15 @@ void CFG::SplitDivergenceScopes() {
|
||||
const bool is_close = is_close_scope(inst);
|
||||
if ((is_close || index == blk->end_index) && curr_begin != -1) {
|
||||
// If there are no instructions inside scope don't do anything.
|
||||
if (index - curr_begin == 1) {
|
||||
if (index - curr_begin == 1 && is_close) {
|
||||
curr_begin = -1;
|
||||
continue;
|
||||
}
|
||||
// If all instructions in the scope ignore exec masking, we shouldn't insert a
|
||||
// scope.
|
||||
const auto start = inst_list.begin() + curr_begin + 1;
|
||||
if (!std::ranges::all_of(start, inst_list.begin() + index, IgnoresExecMask)) {
|
||||
if (!std::ranges::all_of(start, inst_list.begin() + index + !is_close,
|
||||
IgnoresExecMask)) {
|
||||
// Determine the first instruction affected by the exec mask.
|
||||
do {
|
||||
++curr_begin;
|
||||
|
||||
@@ -586,6 +586,15 @@ void Translator::S_MOV(const GcnInst& inst) {
|
||||
}
|
||||
|
||||
void Translator::S_MOV_B64(const GcnInst& inst) {
|
||||
// Moving SGPR to SGPR is used for thread masks, like most operations, but it can also be used
|
||||
// for moving sharps.
|
||||
if (inst.dst[0].field == OperandField::ScalarGPR &&
|
||||
inst.src[0].field == OperandField::ScalarGPR) {
|
||||
ir.SetScalarReg(IR::ScalarReg(inst.dst[0].code),
|
||||
ir.GetScalarReg(IR::ScalarReg(inst.src[0].code)));
|
||||
ir.SetScalarReg(IR::ScalarReg(inst.dst[0].code + 1),
|
||||
ir.GetScalarReg(IR::ScalarReg(inst.src[0].code + 1)));
|
||||
}
|
||||
const IR::U1 src = [&] {
|
||||
switch (inst.src[0].field) {
|
||||
case OperandField::VccLo:
|
||||
|
||||
@@ -193,8 +193,8 @@ void Translator::BUFFER_LOAD(u32 num_dwords, bool is_inst_typed, bool is_buffer_
|
||||
const IR::ScalarReg sharp{inst.src[2].code * 4};
|
||||
const IR::Value soffset{GetSrc(inst.src[3])};
|
||||
if (info.stage != Stage::Geometry) {
|
||||
ASSERT_MSG(soffset.IsImmediate() && soffset.U32() == 0,
|
||||
"Non immediate offset not supported");
|
||||
ASSERT_MSG(soffset.IsImmediate() && soffset.U32() == 0 || !mubuf.offen,
|
||||
"Having both scalar and vector offsets is not supported");
|
||||
}
|
||||
|
||||
const IR::Value address = [&] -> IR::Value {
|
||||
@@ -204,15 +204,21 @@ void Translator::BUFFER_LOAD(u32 num_dwords, bool is_inst_typed, bool is_buffer_
|
||||
if (mubuf.idxen && mubuf.offen) {
|
||||
return ir.CompositeConstruct(ir.GetVectorReg(vaddr), ir.GetVectorReg(vaddr + 1));
|
||||
}
|
||||
if (mubuf.idxen && !soffset.IsImmediate()) {
|
||||
return ir.CompositeConstruct(ir.GetVectorReg(vaddr), soffset);
|
||||
}
|
||||
if (mubuf.idxen || mubuf.offen) {
|
||||
return ir.GetVectorReg(vaddr);
|
||||
}
|
||||
if (!soffset.IsImmediate()) {
|
||||
return soffset;
|
||||
}
|
||||
return {};
|
||||
}();
|
||||
|
||||
IR::BufferInstInfo buffer_info{};
|
||||
buffer_info.index_enable.Assign(mubuf.idxen);
|
||||
buffer_info.offset_enable.Assign(mubuf.offen);
|
||||
buffer_info.offset_enable.Assign(mubuf.offen || !soffset.IsImmediate());
|
||||
buffer_info.inst_offset.Assign(mubuf.offset);
|
||||
buffer_info.globally_coherent.Assign(mubuf.glc);
|
||||
buffer_info.system_coherent.Assign(mubuf.slc);
|
||||
|
||||
Reference in New Issue
Block a user