Compare commits

..

4 commits

Author SHA1 Message Date
177a4d8e6d [compat] improve thread naming logic
All checks were successful
eden-license / license-header (pull_request) Successful in 17s
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2025-09-22 18:43:19 +02:00
7050b92d61
[vk, gl] fix missing spline1 header (#2551)
Thanks to @chemicalwarrior for the patch
Signed-off-by: lizzie <lizzie@eden-emu.dev>

Reviewed-on: #2551
Co-authored-by: lizzie <lizzie@eden-emu.dev>
Co-committed-by: lizzie <lizzie@eden-emu.dev>
2025-09-22 18:21:59 +02:00
48f7387e3a
[texture_cache, nifm] fix crashes for linear image type and set nifm logs to debug (#2549)
Example game was Mario+Rabbits Kingdom Battle. It crashes when reaches that part of copy image. Also put NIFM requests to log in DEBUG due to request spam and not being useful in debugging at all.

Reviewed-on: #2549
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: Shinmegumi <shinmegumi@eden-emu.dev>
Co-authored-by: Maufeat <sahyno1996@gmail.com>
Co-committed-by: Maufeat <sahyno1996@gmail.com>
2025-09-22 17:56:20 +02:00
49f29e5071
[shader_recompiler] Rewrite ISBERD (#2541)
I tried to simplify ISBERD a little bit, and remove unneeded data shifting, and unneeded complexity through helper functions I previously added.

Reviewed-on: #2541
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: crueter <crueter@eden-emu.dev>
Co-authored-by: SDK Chan <sdkchan@eden-emu.dev>
Co-committed-by: SDK Chan <sdkchan@eden-emu.dev>
2025-09-22 17:55:41 +02:00
7 changed files with 109 additions and 109 deletions

View file

@ -381,7 +381,7 @@ public:
private:
void Submit(HLERequestContext& ctx) {
LOG_WARNING(Service_NIFM, "(STUBBED) called");
LOG_DEBUG(Service_NIFM, "(STUBBED) called");
if (state == RequestState::NotSubmitted) {
UpdateState(RequestState::OnHold);
@ -392,7 +392,7 @@ private:
}
void GetRequestState(HLERequestContext& ctx) {
LOG_WARNING(Service_NIFM, "(STUBBED) called");
LOG_DEBUG(Service_NIFM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
@ -424,7 +424,7 @@ private:
}
void GetResult(HLERequestContext& ctx) {
LOG_WARNING(Service_NIFM, "(STUBBED) called");
LOG_DEBUG(Service_NIFM, "(STUBBED) called");
const auto result = [this] {
const auto has_connection = Network::GetHostIPv4Address().has_value() &&
@ -486,7 +486,7 @@ private:
}
void UpdateState(RequestState new_state) {
LOG_WARNING(Service_NIFM, "(STUBBED) called");
LOG_DEBUG(Service_NIFM, "(STUBBED) called");
state = new_state;
event1->Signal();
}

View file

@ -271,40 +271,4 @@ void TranslatorVisitor::ResetOFlag() {
SetOFlag(ir.Imm1(false));
}
IR::U32 TranslatorVisitor::apply_ISBERD_shift(IR::U32 result, Isberd::Shift shift_value) {
if (shift_value != Isberd::Shift::Default) {
return ir.ShiftLeftLogical(result, ir.Imm32(1));
}
return result;
}
IR::U32 TranslatorVisitor::apply_ISBERD_size_read(IR::U32 address, Isberd::SZ sz) {
switch (sz) {
case Isberd::SZ::U8:
return ir.LoadGlobalU8(ir.UConvert(64, address));
case Isberd::SZ::U16:
return ir.LoadGlobalU16(ir.UConvert(64, address));
case Isberd::SZ::U32:
case Isberd::SZ::F32:
return ir.LoadGlobal32(ir.UConvert(64, address));
default:
UNREACHABLE();
}
}
IR::U32 TranslatorVisitor::compute_ISBERD_address(IR::Reg src_reg, u32 src_reg_num, u32 imm, u64 skew_value) {
IR::U32 address{};
if (src_reg_num == 0xFF) {
address = ir.Imm32(imm);
} else {
auto offset = ir.Imm32(imm);
address = ir.IAdd(X(src_reg), offset);
if (skew_value != 0) {
address = ir.IAdd(address, ir.LaneId());
}
}
return address;
};
} // namespace Shader::Maxwell

View file

@ -56,30 +56,6 @@ enum class FPCompareOp : u64 {
T,
};
namespace Isberd {
enum class Mode : u64 {
Default,
Patch,
Prim,
Attr,
};
enum class Shift : u64 {
Default,
U16,
B32,
};
enum class SZ : u64 {
U8,
U16,
U32,
F32,
};
} // namespace Isberd
class TranslatorVisitor {
public:
explicit TranslatorVisitor(Environment& env_, IR::Block& block) : env{env_}, ir(block) {}
@ -408,12 +384,6 @@ public:
void ResetSFlag();
void ResetCFlag();
void ResetOFlag();
private:
// Helper functions for various translator visitors
IR::U32 apply_ISBERD_shift(IR::U32 result, Isberd::Shift shift_value);
IR::U32 apply_ISBERD_size_read(IR::U32 address, Isberd::SZ sz_value);
IR::U32 compute_ISBERD_address(IR::Reg src_reg, u32 src_reg_num, u32 imm, u64 skew_value);
};
} // namespace Shader::Maxwell

View file

@ -9,9 +9,52 @@
#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h"
namespace Shader::Maxwell {
namespace {
enum class Mode : u64 {
Default,
Patch,
Prim,
Attr,
};
enum class SZ : u64 {
U8,
U16,
U32,
F32
};
enum class Shift : u64 {
Default,
U16,
B32,
};
IR::U32 scaleIndex(IR::IREmitter& ir, IR::U32 index, Shift shift) {
switch (shift) {
case Shift::Default: return index;
case Shift::U16: return ir.ShiftLeftLogical(index, ir.Imm32(1));
case Shift::B32: return ir.ShiftLeftLogical(index, ir.Imm32(2));
default: UNREACHABLE();
}
}
IR::U32 skewBytes(IR::IREmitter& ir, SZ sizeRead) {
const IR::U32 lane = ir.LaneId();
switch (sizeRead) {
case SZ::U8: return lane;
case SZ::U16: return ir.ShiftLeftLogical(lane, ir.Imm32(1));
case SZ::U32:
case SZ::F32: return ir.ShiftLeftLogical(lane, ir.Imm32(2));
default: UNREACHABLE();
}
}
} // Anonymous namespace
// Valid only for GS, TI, VS and trap
void TranslatorVisitor::ISBERD(u64 insn) {
LOG_DEBUG(Shader, "called with insn={:#X}", insn);
union {
u64 raw;
BitField<0, 8, IR::Reg> dest_reg;
@ -20,49 +63,66 @@ void TranslatorVisitor::ISBERD(u64 insn) {
BitField<24, 8, u32> imm;
BitField<31, 1, u64> skew;
BitField<32, 1, u64> o;
BitField<33, 2, Isberd::Mode> mode;
BitField<36, 4, Isberd::SZ> sz;
BitField<47, 2, Isberd::Shift> shift;
BitField<33, 2, Mode> mode;
BitField<36, 4, SZ> sz;
BitField<47, 2, Shift> shift;
} const isberd{insn};
auto address = compute_ISBERD_address(isberd.src_reg, isberd.src_reg_num, isberd.imm, isberd.skew);
if (isberd.o != 0) {
auto result = apply_ISBERD_size_read(address, isberd.sz.Value());
X(isberd.dest_reg, apply_ISBERD_shift(result, isberd.shift.Value()));
return;
IR::U32 index{};
if (isberd.src_reg_num.Value() == 0xFF) {
index = ir.Imm32(isberd.imm.Value());
} else {
const IR::U32 scaledIndex = scaleIndex(ir, X(isberd.src_reg.Value()), isberd.shift.Value());
index = ir.IAdd(scaledIndex, ir.Imm32(isberd.imm.Value()));
}
if (isberd.mode != Isberd::Mode::Default) {
IR::F32 result_f32{};
switch (isberd.mode.Value()) {
case Isberd::Mode::Patch:
result_f32 = ir.GetPatch(address.Patch());
break;
case Isberd::Mode::Prim:
result_f32 = ir.GetAttribute(address.Attribute());
break;
case Isberd::Mode::Attr:
result_f32 = ir.GetAttributeIndexed(address);
break;
default:
UNREACHABLE();
if (isberd.o.Value()) {
if (isberd.skew.Value()) {
index = ir.IAdd(index, skewBytes(ir, isberd.sz.Value()));
}
auto result_u32 = ir.BitCast<IR::U32>(result_f32);
X(isberd.dest_reg, apply_ISBERD_shift(result_u32, isberd.shift.Value()));
return;
}
if (isberd.skew != 0) {
auto result = ir.IAdd(X(isberd.src_reg), ir.LaneId());
X(isberd.dest_reg, result);
const IR::U64 index64 = ir.UConvert(64, index);
IR::U32 globalLoaded{};
switch (isberd.sz.Value()) {
case SZ::U8: globalLoaded = ir.LoadGlobalU8 (index64); break;
case SZ::U16: globalLoaded = ir.LoadGlobalU16(index64); break;
case SZ::U32:
case SZ::F32: globalLoaded = ir.LoadGlobal32(index64); break;
default: UNREACHABLE();
}
X(isberd.dest_reg.Value(), globalLoaded);
return;
}
// Fallback if nothing else applies
X(isberd.dest_reg, X(isberd.src_reg));
if (isberd.mode.Value() != Mode::Default) {
if (isberd.skew.Value()) {
index = ir.IAdd(index, skewBytes(ir, SZ::U32));
}
IR::F32 float_index{};
switch (isberd.mode.Value()) {
case Mode::Patch: float_index = ir.GetPatch(index.Patch());
break;
case Mode::Prim: float_index = ir.GetAttribute(index.Attribute());
break;
case Mode::Attr: float_index = ir.GetAttributeIndexed(index);
break;
default: UNREACHABLE();
}
X(isberd.dest_reg.Value(), ir.BitCast<IR::U32>(float_index));
return;
}
if (isberd.skew.Value()) {
X(isberd.dest_reg.Value(), ir.IAdd(X(isberd.src_reg.Value()), ir.LaneId()));
return;
}
// Fallback copy
X(isberd.dest_reg.Value(), X(isberd.src_reg.Value()));
}
} // namespace Shader::Maxwell

View file

@ -13,6 +13,7 @@
#include "video_core/host_shaders/present_bicubic_frag.h"
#include "video_core/host_shaders/present_gaussian_frag.h"
#include "video_core/host_shaders/present_lanczos_frag.h"
#include "video_core/host_shaders/present_spline1_frag.h"
#include "video_core/renderer_opengl/present/filters.h"
#include "video_core/renderer_opengl/present/util.h"

View file

@ -13,6 +13,7 @@
#include "video_core/host_shaders/present_bicubic_frag_spv.h"
#include "video_core/host_shaders/present_gaussian_frag_spv.h"
#include "video_core/host_shaders/present_lanczos_frag_spv.h"
#include "video_core/host_shaders/present_spline1_frag_spv.h"
#include "video_core/host_shaders/vulkan_present_frag_spv.h"
#include "video_core/host_shaders/vulkan_present_scaleforce_fp16_frag_spv.h"
#include "video_core/host_shaders/vulkan_present_scaleforce_fp32_frag_spv.h"

View file

@ -1377,13 +1377,17 @@ void TextureCacheRuntime::CopyImage(Image& dst, Image& src,
// As per the size-compatible formats section of vulkan, copy manually via ReinterpretImage
// these images that aren't size-compatible
if (BytesPerBlock(src.info.format) != BytesPerBlock(dst.info.format)) {
auto oneCopy = VideoCommon::ImageCopy{
.src_offset = VideoCommon::Offset3D(0, 0, 0),
.dst_offset = VideoCommon::Offset3D(0, 0, 0),
.extent = dst.info.size
};
if (src.info.type == ImageType::Linear || dst.info.type == ImageType::Linear) {
return;
}
auto oneCopy = VideoCommon::ImageCopy{.src_offset = VideoCommon::Offset3D(0, 0, 0),
.dst_offset = VideoCommon::Offset3D(0, 0, 0),
.extent = dst.info.size};
return ReinterpretImage(dst, src, std::span{&oneCopy, 1});
}
boost::container::small_vector<VkImageCopy, 16> vk_copies(copies.size());
const VkImageAspectFlags aspect_mask = dst.AspectMask();
ASSERT(aspect_mask == src.AspectMask());