mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-03 13:31:27 +12:00
Merge branch 'master' into nastys-patch-17
This commit is contained in:
commit
9c9bfaf0e3
29 changed files with 632 additions and 320 deletions
2
.gitmodules
vendored
2
.gitmodules
vendored
|
@ -106,5 +106,5 @@
|
|||
ignore = dirty
|
||||
[submodule "3rdparty/GPUOpen/VulkanMemoryAllocator"]
|
||||
path = 3rdparty/GPUOpen/VulkanMemoryAllocator
|
||||
url = ../../Megamouse/VulkanMemoryAllocator.git
|
||||
url = ../../GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git
|
||||
ignore = dirty
|
||||
|
|
2
3rdparty/GPUOpen/VulkanMemoryAllocator
vendored
2
3rdparty/GPUOpen/VulkanMemoryAllocator
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 37064843398c69cc0ca7f8cf5b33128c03a2bd74
|
||||
Subproject commit 1d8f600fd424278486eade7ed3e877c99f0846b1
|
2
3rdparty/hidapi/hidapi
vendored
2
3rdparty/hidapi/hidapi
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 6bfdcf7368169efe1b745cd4468d45cda05ef8de
|
||||
Subproject commit f42423643ec9011c98cccc0bb790722bbbd3f30b
|
|
@ -511,6 +511,7 @@ target_sources(rpcs3_emu PRIVATE
|
|||
RSX/Overlays/overlay_video.cpp
|
||||
RSX/Overlays/Shaders/shader_loading_dialog.cpp
|
||||
RSX/Overlays/Shaders/shader_loading_dialog_native.cpp
|
||||
RSX/Program/CgBinaryProgram.cpp
|
||||
RSX/Program/CgBinaryFragmentProgram.cpp
|
||||
RSX/Program/CgBinaryVertexProgram.cpp
|
||||
RSX/Program/FragmentProgramDecompiler.cpp
|
||||
|
|
|
@ -139,7 +139,7 @@ struct ppu_exec_select
|
|||
#define RETURN_(...) \
|
||||
if constexpr (Build == 0) { \
|
||||
static_cast<void>(exec); \
|
||||
if (is_debugger_present()) return +[](ppu_thread& ppu, ppu_opcode_t op, be_t<u32>* this_op, ppu_intrp_func* next_fn) { \
|
||||
if (is_debugger_present() || g_cfg.core.ppu_debug) return +[](ppu_thread& ppu, ppu_opcode_t op, be_t<u32>* this_op, ppu_intrp_func* next_fn) { \
|
||||
exec(__VA_ARGS__); \
|
||||
const auto next_op = this_op + 1; \
|
||||
const auto fn = atomic_storage<ppu_intrp_func_t>::load(next_fn->fn); \
|
||||
|
|
|
@ -6181,7 +6181,7 @@ s64 spu_thread::get_ch_value(u32 ch)
|
|||
{
|
||||
if (utils::has_waitpkg())
|
||||
{
|
||||
__tpause(std::min<u32>(eventstat_spin_count, 10) * 500, 0x1);
|
||||
__tpause(static_cast<u32>(std::min<u64>(eventstat_spin_count, 10) * 500), 0x1);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -6194,7 +6194,7 @@ s64 spu_thread::get_ch_value(u32 ch)
|
|||
};
|
||||
|
||||
// Provide the first X64 cache line of the reservation to be tracked
|
||||
__mwaitx<check_wait_t>(std::min<u32>(eventstat_spin_count, 17) * 500, 0xf0, std::addressof(*resrv_mem), +rtime, vm::reservation_acquire(raddr));
|
||||
__mwaitx<check_wait_t>(static_cast<u32>(std::min<u64>(eventstat_spin_count, 17) * 500), 0xf0, std::addressof(*resrv_mem), +rtime, vm::reservation_acquire(raddr));
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
@ -115,12 +115,8 @@ u16 usb_device_logitech_g27::get_num_emu_devices()
|
|||
|
||||
void usb_device_logitech_g27::control_transfer(u8 bmRequestType, u8 bRequest, u16 wValue, u16 wIndex, u16 wLength, u32 buf_size, u8* buf, UsbTransfer* transfer)
|
||||
{
|
||||
transfer->fake = true;
|
||||
transfer->expected_count = buf_size;
|
||||
transfer->expected_result = HC_CC_NOERR;
|
||||
transfer->expected_time = get_timestamp() + 100;
|
||||
logitech_g27_log.todo("control transfer bmRequestType %02x, bRequest %02x, wValue %04x, wIndex %04x, wLength %04x, %s", bmRequestType, bRequest, wValue, wIndex, wLength, fmt::buf_to_hexstring(buf, buf_size));
|
||||
|
||||
// Log these for now, might not need to implement anything
|
||||
usb_device_emulated::control_transfer(bmRequestType, bRequest, wValue, wIndex, wLength, buf_size, buf, transfer);
|
||||
}
|
||||
|
||||
|
@ -209,6 +205,7 @@ static inline logitech_g27_sdl_mapping get_runtime_mapping()
|
|||
convert_mapping(cfg.shifter_5, mapping.shifter_5);
|
||||
convert_mapping(cfg.shifter_6, mapping.shifter_6);
|
||||
convert_mapping(cfg.shifter_r, mapping.shifter_r);
|
||||
convert_mapping(cfg.shifter_press, mapping.shifter_press);
|
||||
|
||||
return mapping;
|
||||
}
|
||||
|
@ -711,6 +708,7 @@ void usb_device_logitech_g27::interrupt_transfer(u32 buf_size, u8* buf, u32 endp
|
|||
const bool shifter_5 = sdl_to_logitech_g27_button(m_joysticks, m_mapping.shifter_5);
|
||||
const bool shifter_6 = sdl_to_logitech_g27_button(m_joysticks, m_mapping.shifter_6);
|
||||
const bool shifter_r = sdl_to_logitech_g27_button(m_joysticks, m_mapping.shifter_r);
|
||||
const bool shifter_press = sdl_to_logitech_g27_button(m_joysticks, m_mapping.shifter_press);
|
||||
m_sdl_handles_mutex.unlock();
|
||||
|
||||
// populate buffer
|
||||
|
@ -749,8 +747,16 @@ void usb_device_logitech_g27::interrupt_transfer(u32 buf_size, u8* buf, u32 endp
|
|||
set_bit(buf, 82, true);
|
||||
// shifter connected
|
||||
set_bit(buf, 83, true);
|
||||
// shifter stick down
|
||||
set_bit(buf, 86, shifter_1 || shifter_2 || shifter_3 || shifter_4 || shifter_5 || shifter_6 || shifter_r);
|
||||
/*
|
||||
* shifter pressed/down bit
|
||||
* mechanical references:
|
||||
* - G29 shifter mechanical explanation https://youtu.be/d7qCn3o8K98?t=1124
|
||||
* - same mechanism on the G27 https://youtu.be/rdjejtIfkVA?t=760
|
||||
* - same mechanism on the G25 https://youtu.be/eCyt_4luwF0?t=130
|
||||
* on healthy G29/G27/G25 shifters, shifter is mechnically kept pressed in reverse, the bit should be set
|
||||
* the shifter_press mapping alone captures instead a shifter press without going into reverse, ie. neutral press, just in case there are games using it for input
|
||||
*/
|
||||
set_bit(buf, 86, shifter_press | shifter_r);
|
||||
|
||||
buf[3] = (steering << 2) | buf[3];
|
||||
buf[4] = steering >> 6;
|
||||
|
@ -758,8 +764,56 @@ void usb_device_logitech_g27::interrupt_transfer(u32 buf_size, u8* buf, u32 endp
|
|||
buf[6] = brake;
|
||||
buf[7] = clutch;
|
||||
|
||||
buf[8] = 0x80; // shifter x, don't own one to test gear/coord mapping
|
||||
buf[9] = 0x80; // shifter y
|
||||
// rough analog values recorded in https://github.com/RPCS3/rpcs3/pull/17199#issuecomment-2883934412
|
||||
// buf[8] shifter x
|
||||
// buf[9] shifter y
|
||||
constexpr u8 shifter_coord_center = 0x80;
|
||||
constexpr u8 shifter_coord_top = 0xb7;
|
||||
constexpr u8 shifter_coord_bottom = 0x32;
|
||||
constexpr u8 shifter_coord_left = 0x30;
|
||||
constexpr u8 shifter_coord_right = 0xb3;
|
||||
constexpr u8 shifter_coord_right_reverse = 0xaa;
|
||||
if (shifter_1)
|
||||
{
|
||||
buf[8] = shifter_coord_left;
|
||||
buf[9] = shifter_coord_top;
|
||||
}
|
||||
else if (shifter_2)
|
||||
{
|
||||
buf[8] = shifter_coord_left;
|
||||
buf[9] = shifter_coord_bottom;
|
||||
}
|
||||
else if (shifter_3)
|
||||
{
|
||||
buf[8] = shifter_coord_center;
|
||||
buf[9] = shifter_coord_top;
|
||||
}
|
||||
else if (shifter_4)
|
||||
{
|
||||
buf[8] = shifter_coord_center;
|
||||
buf[9] = shifter_coord_bottom;
|
||||
}
|
||||
else if (shifter_5)
|
||||
{
|
||||
buf[8] = shifter_coord_right;
|
||||
buf[9] = shifter_coord_top;
|
||||
}
|
||||
else if (shifter_6)
|
||||
{
|
||||
buf[8] = shifter_coord_right;
|
||||
buf[9] = shifter_coord_bottom;
|
||||
}
|
||||
else if (shifter_r)
|
||||
{
|
||||
buf[8] = shifter_coord_right_reverse;
|
||||
buf[9] = shifter_coord_bottom;
|
||||
}
|
||||
else
|
||||
{
|
||||
buf[8] = shifter_coord_center;
|
||||
buf[9] = shifter_coord_center;
|
||||
}
|
||||
|
||||
buf[10] = buf[10] | (m_wheel_range > 360 ? 0x90 : 0x10);
|
||||
|
||||
// logitech_g27_log.error("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10]);
|
||||
|
|
|
@ -94,6 +94,7 @@ struct logitech_g27_sdl_mapping
|
|||
sdl_mapping shifter_5 {};
|
||||
sdl_mapping shifter_6 {};
|
||||
sdl_mapping shifter_r {};
|
||||
sdl_mapping shifter_press {};
|
||||
};
|
||||
|
||||
class usb_device_logitech_g27 : public usb_device_emulated
|
||||
|
|
|
@ -107,6 +107,7 @@ public:
|
|||
emulated_logitech_g27_mapping shifter_5{this, "shifter_5", 0, sdl_mapping_type::hat, 0, hat_component::up, false};
|
||||
emulated_logitech_g27_mapping shifter_6{this, "shifter_6", 0, sdl_mapping_type::hat, 0, hat_component::down, false};
|
||||
emulated_logitech_g27_mapping shifter_r{this, "shifter_r", 0, sdl_mapping_type::hat, 0, hat_component::left, false};
|
||||
emulated_logitech_g27_mapping shifter_press{this, "shifter_press", 0, sdl_mapping_type::hat, 0, hat_component::right, false};
|
||||
|
||||
cfg::_bool reverse_effects{this, "reverse_effects", false};
|
||||
cfg::uint<0, 0xFFFFFFFFFFFFFFFF> ffb_device_type_id{this, "ffb_device_type_id", 0};
|
||||
|
|
|
@ -1629,17 +1629,6 @@ namespace rpcn
|
|||
{
|
||||
flatbuffers::FlatBufferBuilder builder(1024);
|
||||
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<BinAttr>>> final_binattrinternal_vec;
|
||||
if (req->roomBinAttrInternalNum && req->roomBinAttrInternal)
|
||||
{
|
||||
std::vector<flatbuffers::Offset<BinAttr>> davec;
|
||||
for (u32 i = 0; i < req->roomBinAttrInternalNum; i++)
|
||||
{
|
||||
auto bin = CreateBinAttr(builder, req->roomBinAttrInternal[i].id, builder.CreateVector(req->roomBinAttrInternal[i].ptr.get_ptr(), req->roomBinAttrInternal[i].size));
|
||||
davec.push_back(bin);
|
||||
}
|
||||
final_binattrinternal_vec = builder.CreateVector(davec);
|
||||
}
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<IntAttr>>> final_searchintattrexternal_vec;
|
||||
if (req->roomSearchableIntAttrExternalNum && req->roomSearchableIntAttrExternal)
|
||||
{
|
||||
|
@ -1651,28 +1640,74 @@ namespace rpcn
|
|||
}
|
||||
final_searchintattrexternal_vec = builder.CreateVector(davec);
|
||||
}
|
||||
|
||||
// WWE SmackDown vs. RAW 2009 passes roomBinAttrExternal in roomSearchableBinAttrExternal so we parse based on attribute ids
|
||||
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<BinAttr>>> final_binattrinternal_vec;
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<BinAttr>>> final_searchbinattrexternal_vec;
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<BinAttr>>> final_binattrexternal_vec;
|
||||
|
||||
std::vector<flatbuffers::Offset<BinAttr>> davec_binattrinternal;
|
||||
std::vector<flatbuffers::Offset<BinAttr>> davec_searchable_binattrexternal;
|
||||
std::vector<flatbuffers::Offset<BinAttr>> davec_binattrexternal;
|
||||
|
||||
auto put_binattr = [&](SceNpMatching2AttributeId id, flatbuffers::Offset<BinAttr> bin)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case SCE_NP_MATCHING2_ROOM_BIN_ATTR_INTERNAL_1_ID:
|
||||
case SCE_NP_MATCHING2_ROOM_BIN_ATTR_INTERNAL_2_ID:
|
||||
davec_binattrinternal.push_back(bin);
|
||||
break;
|
||||
case SCE_NP_MATCHING2_ROOM_BIN_ATTR_EXTERNAL_1_ID:
|
||||
case SCE_NP_MATCHING2_ROOM_BIN_ATTR_EXTERNAL_2_ID:
|
||||
davec_binattrexternal.push_back(bin);
|
||||
break;
|
||||
case SCE_NP_MATCHING2_ROOM_SEARCHABLE_BIN_ATTR_EXTERNAL_1_ID:
|
||||
davec_searchable_binattrexternal.push_back(bin);
|
||||
break;
|
||||
default:
|
||||
rpcn_log.error("Unexpected bin attribute id in createjoin_room request: 0x%x", id);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
if (req->roomBinAttrInternalNum && req->roomBinAttrInternal)
|
||||
{
|
||||
for (u32 i = 0; i < req->roomBinAttrInternalNum; i++)
|
||||
{
|
||||
auto bin = CreateBinAttr(builder, req->roomBinAttrInternal[i].id, builder.CreateVector(req->roomBinAttrInternal[i].ptr.get_ptr(), req->roomBinAttrInternal[i].size));
|
||||
put_binattr(req->roomBinAttrInternal[i].id, bin);
|
||||
}
|
||||
}
|
||||
|
||||
if (req->roomSearchableBinAttrExternalNum && req->roomSearchableBinAttrExternal)
|
||||
{
|
||||
std::vector<flatbuffers::Offset<BinAttr>> davec;
|
||||
for (u32 i = 0; i < req->roomSearchableBinAttrExternalNum; i++)
|
||||
{
|
||||
auto bin = CreateBinAttr(builder, req->roomSearchableBinAttrExternal[i].id, builder.CreateVector(req->roomSearchableBinAttrExternal[i].ptr.get_ptr(), req->roomSearchableBinAttrExternal[i].size));
|
||||
davec.push_back(bin);
|
||||
put_binattr(req->roomSearchableBinAttrExternal[i].id, bin);
|
||||
}
|
||||
final_searchbinattrexternal_vec = builder.CreateVector(davec);
|
||||
}
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<BinAttr>>> final_binattrexternal_vec;
|
||||
|
||||
if (req->roomBinAttrExternalNum && req->roomBinAttrExternal)
|
||||
{
|
||||
std::vector<flatbuffers::Offset<BinAttr>> davec;
|
||||
for (u32 i = 0; i < req->roomBinAttrExternalNum; i++)
|
||||
{
|
||||
auto bin = CreateBinAttr(builder, req->roomBinAttrExternal[i].id, builder.CreateVector(req->roomBinAttrExternal[i].ptr.get_ptr(), req->roomBinAttrExternal[i].size));
|
||||
davec.push_back(bin);
|
||||
put_binattr(req->roomBinAttrExternal[i].id, bin);
|
||||
}
|
||||
final_binattrexternal_vec = builder.CreateVector(davec);
|
||||
}
|
||||
|
||||
if (!davec_binattrinternal.empty())
|
||||
final_binattrinternal_vec = builder.CreateVector(davec_binattrinternal);
|
||||
|
||||
if (!davec_searchable_binattrexternal.empty())
|
||||
final_searchbinattrexternal_vec = builder.CreateVector(davec_searchable_binattrexternal);
|
||||
|
||||
if (!davec_binattrexternal.empty())
|
||||
final_binattrexternal_vec = builder.CreateVector(davec_binattrexternal);
|
||||
|
||||
flatbuffers::Offset<flatbuffers::Vector<u8>> final_roompassword;
|
||||
if (req->roomPassword)
|
||||
final_roompassword = builder.CreateVector(req->roomPassword->data, 8);
|
||||
|
@ -1884,28 +1919,54 @@ namespace rpcn
|
|||
}
|
||||
final_searchintattrexternal_vec = builder.CreateVector(davec);
|
||||
}
|
||||
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<BinAttr>>> final_searchbinattrexternal_vec;
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<BinAttr>>> final_binattrexternal_vec;
|
||||
|
||||
std::vector<flatbuffers::Offset<BinAttr>> davec_searchable_binattrexternal;
|
||||
std::vector<flatbuffers::Offset<BinAttr>> davec_binattrexternal;
|
||||
|
||||
auto put_binattr = [&](SceNpMatching2AttributeId id, flatbuffers::Offset<BinAttr> bin)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case SCE_NP_MATCHING2_ROOM_BIN_ATTR_EXTERNAL_1_ID:
|
||||
case SCE_NP_MATCHING2_ROOM_BIN_ATTR_EXTERNAL_2_ID:
|
||||
davec_binattrexternal.push_back(bin);
|
||||
break;
|
||||
case SCE_NP_MATCHING2_ROOM_SEARCHABLE_BIN_ATTR_EXTERNAL_1_ID:
|
||||
davec_searchable_binattrexternal.push_back(bin);
|
||||
break;
|
||||
default:
|
||||
rpcn_log.error("Unexpected bin attribute id in set_roomdata_external request: 0x%x", id);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
if (req->roomSearchableBinAttrExternalNum && req->roomSearchableBinAttrExternal)
|
||||
{
|
||||
std::vector<flatbuffers::Offset<BinAttr>> davec;
|
||||
for (u32 i = 0; i < req->roomSearchableBinAttrExternalNum; i++)
|
||||
{
|
||||
auto bin = CreateBinAttr(builder, req->roomSearchableBinAttrExternal[i].id, builder.CreateVector(req->roomSearchableBinAttrExternal[i].ptr.get_ptr(), req->roomSearchableBinAttrExternal[i].size));
|
||||
davec.push_back(bin);
|
||||
put_binattr(req->roomSearchableBinAttrExternal[i].id, bin);
|
||||
}
|
||||
final_searchbinattrexternal_vec = builder.CreateVector(davec);
|
||||
}
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<BinAttr>>> final_binattrexternal_vec;
|
||||
|
||||
if (req->roomBinAttrExternalNum && req->roomBinAttrExternal)
|
||||
{
|
||||
std::vector<flatbuffers::Offset<BinAttr>> davec;
|
||||
for (u32 i = 0; i < req->roomBinAttrExternalNum; i++)
|
||||
{
|
||||
auto bin = CreateBinAttr(builder, req->roomBinAttrExternal[i].id, builder.CreateVector(req->roomBinAttrExternal[i].ptr.get_ptr(), req->roomBinAttrExternal[i].size));
|
||||
davec.push_back(bin);
|
||||
put_binattr(req->roomBinAttrExternal[i].id, bin);
|
||||
}
|
||||
final_binattrexternal_vec = builder.CreateVector(davec);
|
||||
}
|
||||
|
||||
if (!davec_searchable_binattrexternal.empty())
|
||||
final_searchbinattrexternal_vec = builder.CreateVector(davec_searchable_binattrexternal);
|
||||
|
||||
if (!davec_binattrexternal.empty())
|
||||
final_binattrexternal_vec = builder.CreateVector(davec_binattrexternal);
|
||||
|
||||
auto req_finished = CreateSetRoomDataExternalRequest(builder, req->roomId, final_searchintattrexternal_vec, final_searchbinattrexternal_vec, final_binattrexternal_vec);
|
||||
builder.Finish(req_finished);
|
||||
|
||||
|
|
|
@ -230,7 +230,7 @@ void CgBinaryDisasm::TaskFP()
|
|||
{
|
||||
m_size = 0;
|
||||
u32* data = reinterpret_cast<u32*>(&m_buffer[m_offset]);
|
||||
ensure((m_buffer_size - m_offset) % sizeof(u32) == 0);
|
||||
ensure((m_buffer.size() - m_offset) % sizeof(u32) == 0);
|
||||
|
||||
enum
|
||||
{
|
||||
|
|
246
rpcs3/Emu/RSX/Program/CgBinaryProgram.cpp
Normal file
246
rpcs3/Emu/RSX/Program/CgBinaryProgram.cpp
Normal file
|
@ -0,0 +1,246 @@
|
|||
#include "stdafx.h"
|
||||
#include "CgBinaryProgram.h"
|
||||
|
||||
#ifndef WITHOUT_OPENGL
|
||||
#include "Emu/RSX/GL/GLVertexProgram.h"
|
||||
#include "Emu/RSX/GL/GLFragmentProgram.h"
|
||||
#endif
|
||||
|
||||
CgBinaryDisasm::CgBinaryDisasm(const std::string& path)
|
||||
: m_path(path)
|
||||
{
|
||||
fs::file f(path);
|
||||
if (!f)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
usz buffer_size = f.size();
|
||||
m_buffer.resize(buffer_size);
|
||||
f.read(m_buffer, buffer_size);
|
||||
fmt::append(m_arb_shader, "Loading... [%s]\n", path.c_str());
|
||||
}
|
||||
|
||||
std::string CgBinaryDisasm::GetCgParamType(u32 type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case 1045: return "float";
|
||||
case 1046:
|
||||
case 1047:
|
||||
case 1048: return fmt::format("float%d", type - 1044);
|
||||
case 1064: return "float4x4";
|
||||
case 1066: return "sampler2D";
|
||||
case 1069: return "samplerCUBE";
|
||||
case 1091: return "float1";
|
||||
|
||||
default: return fmt::format("!UnkCgType(%d)", type);
|
||||
}
|
||||
}
|
||||
|
||||
std::string CgBinaryDisasm::GetCgParamName(u32 offset) const
|
||||
{
|
||||
return std::string(&m_buffer[offset]);
|
||||
}
|
||||
|
||||
std::string CgBinaryDisasm::GetCgParamRes(u32 /*offset*/) const
|
||||
{
|
||||
// rsx_log.warning("GetCgParamRes offset 0x%x", offset);
|
||||
// TODO
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string CgBinaryDisasm::GetCgParamSemantic(u32 offset) const
|
||||
{
|
||||
return std::string(&m_buffer[offset]);
|
||||
}
|
||||
|
||||
std::string CgBinaryDisasm::GetCgParamValue(u32 offset, u32 end_offset) const
|
||||
{
|
||||
std::string offsets = "offsets:";
|
||||
|
||||
u32 num = 0;
|
||||
offset += 6;
|
||||
while (offset < end_offset)
|
||||
{
|
||||
fmt::append(offsets, " %d,", m_buffer[offset] << 8 | m_buffer[offset + 1]);
|
||||
offset += 4;
|
||||
num++;
|
||||
}
|
||||
|
||||
if (num > 4)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
offsets.pop_back();
|
||||
return fmt::format("num %d ", num) + offsets;
|
||||
}
|
||||
|
||||
void CgBinaryDisasm::ConvertToLE(CgBinaryProgram& prog)
|
||||
{
|
||||
// BE payload, requires that data be swapped
|
||||
const auto be_profile = prog.profile;
|
||||
|
||||
auto swap_be32 = [&](u32 start_offset, size_t size_bytes)
|
||||
{
|
||||
auto start = reinterpret_cast<u32*>(m_buffer.data() + start_offset);
|
||||
auto end = reinterpret_cast<u32*>(m_buffer.data() + start_offset + size_bytes);
|
||||
|
||||
for (auto data = start; data < end; ++data)
|
||||
{
|
||||
*data = std::bit_cast<be_t<u32>>(*data);
|
||||
}
|
||||
};
|
||||
|
||||
// 1. Swap the header
|
||||
swap_be32(0, sizeof(CgBinaryProgram));
|
||||
|
||||
// 2. Swap parameters
|
||||
swap_be32(prog.parameterArray, sizeof(CgBinaryParameter) * prog.parameterCount);
|
||||
|
||||
// 3. Swap the ucode
|
||||
swap_be32(prog.ucode, m_buffer.size() - prog.ucode);
|
||||
|
||||
// 4. Swap the domain header
|
||||
if (be_profile == 7004u)
|
||||
{
|
||||
// Need to swap each field individually
|
||||
auto& fprog = GetCgRef<CgBinaryFragmentProgram>(prog.program);
|
||||
fprog.instructionCount = std::bit_cast<be_t<u32>>(fprog.instructionCount);
|
||||
fprog.attributeInputMask = std::bit_cast<be_t<u32>>(fprog.attributeInputMask);
|
||||
fprog.partialTexType = std::bit_cast<be_t<u32>>(fprog.partialTexType);
|
||||
fprog.texCoordsInputMask = std::bit_cast<be_t<u16>>(fprog.texCoordsInputMask);
|
||||
fprog.texCoords2D = std::bit_cast<be_t<u16>>(fprog.texCoords2D);
|
||||
fprog.texCoordsCentroid = std::bit_cast<be_t<u16>>(fprog.texCoordsCentroid);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Swap entire header block as all fields are u32
|
||||
swap_be32(prog.program, sizeof(CgBinaryVertexProgram));
|
||||
}
|
||||
}
|
||||
|
||||
void CgBinaryDisasm::BuildShaderBody(bool include_glsl)
|
||||
{
|
||||
ParamArray param_array;
|
||||
|
||||
auto& prog = GetCgRef<CgBinaryProgram>(0);
|
||||
|
||||
if (const u32 be_profile = std::bit_cast<be_t<u32>>(prog.profile);
|
||||
be_profile == 7003u || be_profile == 7004u)
|
||||
{
|
||||
ConvertToLE(prog);
|
||||
ensure(be_profile == prog.profile);
|
||||
}
|
||||
|
||||
if (prog.profile == 7004u)
|
||||
{
|
||||
auto& fprog = GetCgRef<CgBinaryFragmentProgram>(prog.program);
|
||||
m_arb_shader += "\n";
|
||||
fmt::append(m_arb_shader, "# binaryFormatRevision 0x%x\n", prog.binaryFormatRevision);
|
||||
fmt::append(m_arb_shader, "# profile sce_fp_rsx\n");
|
||||
fmt::append(m_arb_shader, "# parameterCount %d\n", prog.parameterCount);
|
||||
fmt::append(m_arb_shader, "# instructionCount %d\n", fprog.instructionCount);
|
||||
fmt::append(m_arb_shader, "# attributeInputMask 0x%x\n", fprog.attributeInputMask);
|
||||
fmt::append(m_arb_shader, "# registerCount %d\n\n", fprog.registerCount);
|
||||
|
||||
CgBinaryParameterOffset offset = prog.parameterArray;
|
||||
for (u32 i = 0; i < prog.parameterCount; i++)
|
||||
{
|
||||
auto& fparam = GetCgRef<CgBinaryParameter>(offset);
|
||||
|
||||
std::string param_type = GetCgParamType(fparam.type) + " ";
|
||||
std::string param_name = GetCgParamName(fparam.name) + " ";
|
||||
std::string param_res = GetCgParamRes(fparam.res) + " ";
|
||||
std::string param_semantic = GetCgParamSemantic(fparam.semantic) + " ";
|
||||
std::string param_const = GetCgParamValue(fparam.embeddedConst, fparam.name);
|
||||
|
||||
fmt::append(m_arb_shader, "#%d%s%s%s%s\n", i, param_type, param_name, param_semantic, param_const);
|
||||
|
||||
offset += u32{sizeof(CgBinaryParameter)};
|
||||
}
|
||||
|
||||
m_arb_shader += "\n";
|
||||
m_offset = prog.ucode;
|
||||
TaskFP();
|
||||
|
||||
if (!include_glsl)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
u32 unused;
|
||||
std::vector<u32> be_data;
|
||||
|
||||
// Swap bytes. FP decompiler expects input in BE
|
||||
for (u32* ptr = reinterpret_cast<u32*>(m_buffer.data() + m_offset),
|
||||
*end = reinterpret_cast<u32*>(m_buffer.data() + m_buffer.size());
|
||||
ptr < end; ++ptr)
|
||||
{
|
||||
be_data.push_back(std::bit_cast<be_t<u32>>(*ptr));
|
||||
}
|
||||
|
||||
RSXFragmentProgram rsx_prog;
|
||||
auto metadata = program_hash_util::fragment_program_utils::analyse_fragment_program(be_data.data());
|
||||
rsx_prog.ctrl = (fprog.outputFromH0 ? 0 : 0x40) | (fprog.depthReplace ? 0xe : 0);
|
||||
rsx_prog.offset = metadata.program_start_offset;
|
||||
rsx_prog.ucode_length = metadata.program_ucode_length;
|
||||
rsx_prog.total_length = metadata.program_ucode_length + metadata.program_start_offset;
|
||||
rsx_prog.data = reinterpret_cast<u8*>(be_data.data()) + metadata.program_start_offset;
|
||||
for (u32 i = 0; i < 16; ++i) rsx_prog.texture_state.set_dimension(rsx::texture_dimension_extended::texture_dimension_2d, i);
|
||||
#ifndef WITHOUT_OPENGL
|
||||
GLFragmentDecompilerThread(m_glsl_shader, param_array, rsx_prog, unused).Task();
|
||||
#endif
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
const auto& vprog = GetCgRef<CgBinaryVertexProgram>(prog.program);
|
||||
m_arb_shader += "\n";
|
||||
fmt::append(m_arb_shader, "# binaryFormatRevision 0x%x\n", prog.binaryFormatRevision);
|
||||
fmt::append(m_arb_shader, "# profile sce_vp_rsx\n");
|
||||
fmt::append(m_arb_shader, "# parameterCount %d\n", prog.parameterCount);
|
||||
fmt::append(m_arb_shader, "# instructionCount %d\n", vprog.instructionCount);
|
||||
fmt::append(m_arb_shader, "# registerCount %d\n", vprog.registerCount);
|
||||
fmt::append(m_arb_shader, "# attributeInputMask 0x%x\n", vprog.attributeInputMask);
|
||||
fmt::append(m_arb_shader, "# attributeOutputMask 0x%x\n\n", vprog.attributeOutputMask);
|
||||
|
||||
CgBinaryParameterOffset offset = prog.parameterArray;
|
||||
for (u32 i = 0; i < prog.parameterCount; i++)
|
||||
{
|
||||
auto& vparam = GetCgRef<CgBinaryParameter>(offset);
|
||||
|
||||
std::string param_type = GetCgParamType(vparam.type) + " ";
|
||||
std::string param_name = GetCgParamName(vparam.name) + " ";
|
||||
std::string param_res = GetCgParamRes(vparam.res) + " ";
|
||||
std::string param_semantic = GetCgParamSemantic(vparam.semantic) + " ";
|
||||
std::string param_const = GetCgParamValue(vparam.embeddedConst, vparam.name);
|
||||
|
||||
fmt::append(m_arb_shader, "#%d%s%s%s%s\n", i, param_type, param_name, param_semantic, param_const);
|
||||
|
||||
offset += u32{sizeof(CgBinaryParameter)};
|
||||
}
|
||||
|
||||
m_arb_shader += "\n";
|
||||
m_offset = prog.ucode;
|
||||
ensure((m_buffer.size() - m_offset) % sizeof(u32) == 0);
|
||||
|
||||
u32* vdata = reinterpret_cast<u32*>(&m_buffer[m_offset]);
|
||||
m_data.resize(prog.ucodeSize / sizeof(u32));
|
||||
std::memcpy(m_data.data(), vdata, prog.ucodeSize);
|
||||
TaskVP();
|
||||
|
||||
if (!include_glsl)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RSXVertexProgram rsx_prog;
|
||||
program_hash_util::vertex_program_utils::analyse_vertex_program(vdata, 0, rsx_prog);
|
||||
for (u32 i = 0; i < 4; ++i) rsx_prog.texture_state.set_dimension(rsx::texture_dimension_extended::texture_dimension_2d, i);
|
||||
#ifndef WITHOUT_OPENGL
|
||||
GLVertexDecompilerThread(rsx_prog, m_glsl_shader, param_array).Task();
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -7,11 +7,6 @@
|
|||
#include "Emu/RSX/Program/ShaderParam.h"
|
||||
#include "Utilities/File.h"
|
||||
|
||||
#ifndef WITHOUT_OPENGL
|
||||
#include "Emu/RSX/GL/GLVertexProgram.h"
|
||||
#include "Emu/RSX/GL/GLFragmentProgram.h"
|
||||
#endif
|
||||
|
||||
using CGprofile = u32;
|
||||
using CGbool = s32;
|
||||
using CGresource = u32;
|
||||
|
@ -133,8 +128,7 @@ class CgBinaryDisasm
|
|||
|
||||
std::string m_path; // used for FP decompiler thread, delete this later
|
||||
|
||||
u8* m_buffer = nullptr;
|
||||
usz m_buffer_size = 0;
|
||||
std::vector<char> m_buffer;
|
||||
std::string m_arb_shader;
|
||||
std::string m_glsl_shader;
|
||||
std::string m_dst_reg_name;
|
||||
|
@ -190,76 +184,17 @@ public:
|
|||
void SetDSTScaDisasm(const std::string& code);
|
||||
|
||||
|
||||
CgBinaryDisasm(const std::string& path)
|
||||
: m_path(path)
|
||||
{
|
||||
fs::file f(path);
|
||||
if (!f) return;
|
||||
CgBinaryDisasm(const std::string& path);
|
||||
|
||||
m_buffer_size = f.size();
|
||||
m_buffer = new u8[m_buffer_size];
|
||||
f.read(m_buffer, m_buffer_size);
|
||||
fmt::append(m_arb_shader, "Loading... [%s]\n", path.c_str());
|
||||
template <typename T>
|
||||
CgBinaryDisasm(const std::span<T>& data)
|
||||
: m_path("<raw>")
|
||||
{
|
||||
m_buffer.resize(data.size_bytes());
|
||||
std::memcpy(m_buffer.data(), data.data(), data.size_bytes());
|
||||
}
|
||||
|
||||
~CgBinaryDisasm()
|
||||
{
|
||||
delete[] m_buffer;
|
||||
}
|
||||
|
||||
static std::string GetCgParamType(u32 type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case 1045: return "float";
|
||||
case 1046:
|
||||
case 1047:
|
||||
case 1048: return fmt::format("float%d", type - 1044);
|
||||
case 1064: return "float4x4";
|
||||
case 1066: return "sampler2D";
|
||||
case 1069: return "samplerCUBE";
|
||||
case 1091: return "float1";
|
||||
|
||||
default: return fmt::format("!UnkCgType(%d)", type);
|
||||
}
|
||||
}
|
||||
|
||||
std::string GetCgParamName(u32 offset) const
|
||||
{
|
||||
return std::string(reinterpret_cast<char*>(&m_buffer[offset]));
|
||||
}
|
||||
|
||||
std::string GetCgParamRes(u32 /*offset*/) const
|
||||
{
|
||||
// rsx_log.warning("GetCgParamRes offset 0x%x", offset);
|
||||
// TODO
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string GetCgParamSemantic(u32 offset) const
|
||||
{
|
||||
return std::string(reinterpret_cast<char*>(&m_buffer[offset]));
|
||||
}
|
||||
|
||||
std::string GetCgParamValue(u32 offset, u32 end_offset) const
|
||||
{
|
||||
std::string offsets = "offsets:";
|
||||
|
||||
u32 num = 0;
|
||||
offset += 6;
|
||||
while (offset < end_offset)
|
||||
{
|
||||
fmt::append(offsets, " %d,", m_buffer[offset] << 8 | m_buffer[offset + 1]);
|
||||
offset += 4;
|
||||
num++;
|
||||
}
|
||||
|
||||
if (num > 4)
|
||||
return "";
|
||||
|
||||
offsets.pop_back();
|
||||
return fmt::format("num %d ", num) + offsets;
|
||||
}
|
||||
~CgBinaryDisasm() = default;
|
||||
|
||||
template<typename T>
|
||||
T& GetCgRef(const u32 offset)
|
||||
|
@ -267,163 +202,14 @@ public:
|
|||
return reinterpret_cast<T&>(m_buffer[offset]);
|
||||
}
|
||||
|
||||
void ConvertToLE(CgBinaryProgram& prog)
|
||||
{
|
||||
// BE payload, requires that data be swapped
|
||||
const auto be_profile = prog.profile;
|
||||
static std::string GetCgParamType(u32 type);
|
||||
std::string GetCgParamName(u32 offset) const;
|
||||
std::string GetCgParamRes(u32 /*offset*/) const;
|
||||
std::string GetCgParamSemantic(u32 offset) const;
|
||||
std::string GetCgParamValue(u32 offset, u32 end_offset) const;
|
||||
|
||||
auto swap_be32 = [&](u32 start_offset, size_t size_bytes)
|
||||
{
|
||||
auto start = reinterpret_cast<u32*>(m_buffer + start_offset);
|
||||
auto end = reinterpret_cast<u32*>(m_buffer + start_offset + size_bytes);
|
||||
|
||||
for (auto data = start; data < end; ++data)
|
||||
{
|
||||
*data = std::bit_cast<be_t<u32>>(*data);
|
||||
}
|
||||
};
|
||||
|
||||
// 1. Swap the header
|
||||
swap_be32(0, sizeof(CgBinaryProgram));
|
||||
|
||||
// 2. Swap parameters
|
||||
swap_be32(prog.parameterArray, sizeof(CgBinaryParameter) * prog.parameterCount);
|
||||
|
||||
// 3. Swap the ucode
|
||||
swap_be32(prog.ucode, m_buffer_size - prog.ucode);
|
||||
|
||||
// 4. Swap the domain header
|
||||
if (be_profile == 7004u)
|
||||
{
|
||||
// Need to swap each field individually
|
||||
auto& fprog = GetCgRef<CgBinaryFragmentProgram>(prog.program);
|
||||
fprog.instructionCount = std::bit_cast<be_t<u32>>(fprog.instructionCount);
|
||||
fprog.attributeInputMask = std::bit_cast<be_t<u32>>(fprog.attributeInputMask);
|
||||
fprog.partialTexType = std::bit_cast<be_t<u32>>(fprog.partialTexType);
|
||||
fprog.texCoordsInputMask = std::bit_cast<be_t<u16>>(fprog.texCoordsInputMask);
|
||||
fprog.texCoords2D = std::bit_cast<be_t<u16>>(fprog.texCoords2D);
|
||||
fprog.texCoordsCentroid = std::bit_cast<be_t<u16>>(fprog.texCoordsCentroid);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Swap entire header block as all fields are u32
|
||||
swap_be32(prog.program, sizeof(CgBinaryVertexProgram));
|
||||
}
|
||||
}
|
||||
|
||||
void BuildShaderBody()
|
||||
{
|
||||
ParamArray param_array;
|
||||
|
||||
auto& prog = GetCgRef<CgBinaryProgram>(0);
|
||||
|
||||
if (const u32 be_profile = std::bit_cast<be_t<u32>>(prog.profile);
|
||||
be_profile == 7003u || be_profile == 7004u)
|
||||
{
|
||||
ConvertToLE(prog);
|
||||
ensure(be_profile == prog.profile);
|
||||
}
|
||||
|
||||
if (prog.profile == 7004u)
|
||||
{
|
||||
auto& fprog = GetCgRef<CgBinaryFragmentProgram>(prog.program);
|
||||
m_arb_shader += "\n";
|
||||
fmt::append(m_arb_shader, "# binaryFormatRevision 0x%x\n", prog.binaryFormatRevision);
|
||||
fmt::append(m_arb_shader, "# profile sce_fp_rsx\n");
|
||||
fmt::append(m_arb_shader, "# parameterCount %d\n", prog.parameterCount);
|
||||
fmt::append(m_arb_shader, "# instructionCount %d\n", fprog.instructionCount);
|
||||
fmt::append(m_arb_shader, "# attributeInputMask 0x%x\n", fprog.attributeInputMask);
|
||||
fmt::append(m_arb_shader, "# registerCount %d\n\n", fprog.registerCount);
|
||||
|
||||
CgBinaryParameterOffset offset = prog.parameterArray;
|
||||
for (u32 i = 0; i < prog.parameterCount; i++)
|
||||
{
|
||||
auto& fparam = GetCgRef<CgBinaryParameter>(offset);
|
||||
|
||||
std::string param_type = GetCgParamType(fparam.type) + " ";
|
||||
std::string param_name = GetCgParamName(fparam.name) + " ";
|
||||
std::string param_res = GetCgParamRes(fparam.res) + " ";
|
||||
std::string param_semantic = GetCgParamSemantic(fparam.semantic) + " ";
|
||||
std::string param_const = GetCgParamValue(fparam.embeddedConst, fparam.name);
|
||||
|
||||
fmt::append(m_arb_shader, "#%d%s%s%s%s\n", i, param_type, param_name, param_semantic, param_const);
|
||||
|
||||
offset += u32{sizeof(CgBinaryParameter)};
|
||||
}
|
||||
|
||||
m_arb_shader += "\n";
|
||||
m_offset = prog.ucode;
|
||||
TaskFP();
|
||||
|
||||
u32 unused;
|
||||
std::vector<u32> be_data;
|
||||
|
||||
// Swap bytes. FP decompiler expects input in BE
|
||||
for (u32* ptr = reinterpret_cast<u32*>(m_buffer + m_offset),
|
||||
*end = reinterpret_cast<u32*>(m_buffer + m_buffer_size);
|
||||
ptr < end; ++ptr)
|
||||
{
|
||||
be_data.push_back(std::bit_cast<be_t<u32>>(*ptr));
|
||||
}
|
||||
|
||||
RSXFragmentProgram prog;
|
||||
auto metadata = program_hash_util::fragment_program_utils::analyse_fragment_program(be_data.data());
|
||||
prog.ctrl = (fprog.outputFromH0 ? 0 : 0x40) | (fprog.depthReplace ? 0xe : 0);
|
||||
prog.offset = metadata.program_start_offset;
|
||||
prog.ucode_length = metadata.program_ucode_length;
|
||||
prog.total_length = metadata.program_ucode_length + metadata.program_start_offset;
|
||||
prog.data = reinterpret_cast<u8*>(be_data.data()) + metadata.program_start_offset;
|
||||
for (u32 i = 0; i < 16; ++i) prog.texture_state.set_dimension(rsx::texture_dimension_extended::texture_dimension_2d, i);
|
||||
#ifndef WITHOUT_OPENGL
|
||||
GLFragmentDecompilerThread(m_glsl_shader, param_array, prog, unused).Task();
|
||||
#endif
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
const auto& vprog = GetCgRef<CgBinaryVertexProgram>(prog.program);
|
||||
m_arb_shader += "\n";
|
||||
fmt::append(m_arb_shader, "# binaryFormatRevision 0x%x\n", prog.binaryFormatRevision);
|
||||
fmt::append(m_arb_shader, "# profile sce_vp_rsx\n");
|
||||
fmt::append(m_arb_shader, "# parameterCount %d\n", prog.parameterCount);
|
||||
fmt::append(m_arb_shader, "# instructionCount %d\n", vprog.instructionCount);
|
||||
fmt::append(m_arb_shader, "# registerCount %d\n", vprog.registerCount);
|
||||
fmt::append(m_arb_shader, "# attributeInputMask 0x%x\n", vprog.attributeInputMask);
|
||||
fmt::append(m_arb_shader, "# attributeOutputMask 0x%x\n\n", vprog.attributeOutputMask);
|
||||
|
||||
CgBinaryParameterOffset offset = prog.parameterArray;
|
||||
for (u32 i = 0; i < prog.parameterCount; i++)
|
||||
{
|
||||
auto& vparam = GetCgRef<CgBinaryParameter>(offset);
|
||||
|
||||
std::string param_type = GetCgParamType(vparam.type) + " ";
|
||||
std::string param_name = GetCgParamName(vparam.name) + " ";
|
||||
std::string param_res = GetCgParamRes(vparam.res) + " ";
|
||||
std::string param_semantic = GetCgParamSemantic(vparam.semantic) + " ";
|
||||
std::string param_const = GetCgParamValue(vparam.embeddedConst, vparam.name);
|
||||
|
||||
fmt::append(m_arb_shader, "#%d%s%s%s%s\n", i, param_type, param_name, param_semantic, param_const);
|
||||
|
||||
offset += u32{sizeof(CgBinaryParameter)};
|
||||
}
|
||||
|
||||
m_arb_shader += "\n";
|
||||
m_offset = prog.ucode;
|
||||
ensure((m_buffer_size - m_offset) % sizeof(u32) == 0);
|
||||
|
||||
u32* vdata = reinterpret_cast<u32*>(&m_buffer[m_offset]);
|
||||
m_data.resize(prog.ucodeSize / sizeof(u32));
|
||||
std::memcpy(m_data.data(), vdata, prog.ucodeSize);
|
||||
TaskVP();
|
||||
|
||||
RSXVertexProgram prog;
|
||||
program_hash_util::vertex_program_utils::analyse_vertex_program(vdata, 0, prog);
|
||||
for (u32 i = 0; i < 4; ++i) prog.texture_state.set_dimension(rsx::texture_dimension_extended::texture_dimension_2d, i);
|
||||
#ifndef WITHOUT_OPENGL
|
||||
GLVertexDecompilerThread(prog, m_glsl_shader, param_array).Task();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
void ConvertToLE(CgBinaryProgram& prog);
|
||||
void BuildShaderBody(bool include_glsl = true);
|
||||
|
||||
static u32 GetData(const u32 d) { return d << 16 | d >> 16; }
|
||||
void TaskFP();
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#define VMA_IMPLEMENTATION
|
||||
#define VMA_VULKAN_VERSION 1000000
|
||||
|
||||
#include "util/atomic.hpp"
|
||||
#include "Utilities/mutex.h"
|
||||
|
@ -49,11 +50,12 @@ private:
|
|||
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic ignored "-Winconsistent-missing-override"
|
||||
#pragma clang diagnostic ignored "-Wnullability-completeness"
|
||||
#else
|
||||
#pragma GCC diagnostic ignored "-Wsuggest-attribute=noreturn"
|
||||
#endif
|
||||
#endif
|
||||
#include "3rdparty/GPUOpen/VulkanMemoryAllocator/src/vk_mem_alloc.h"
|
||||
#include "3rdparty/GPUOpen/VulkanMemoryAllocator/include/vk_mem_alloc.h"
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#else
|
||||
|
|
|
@ -880,7 +880,7 @@ namespace vk
|
|||
}
|
||||
else
|
||||
{
|
||||
m_allocator = std::make_unique<vk::mem_allocator_vma>(*this, pdev);
|
||||
m_allocator = std::make_unique<vk::mem_allocator_vma>(*this, pdev, pdev);
|
||||
}
|
||||
|
||||
// Useful for debugging different VRAM configurations
|
||||
|
|
|
@ -153,11 +153,11 @@ namespace vk
|
|||
rsx_log.warning("Rebalanced memory types successfully");
|
||||
}
|
||||
|
||||
mem_allocator_base::mem_allocator_base(const vk::render_device& dev, VkPhysicalDevice)
|
||||
mem_allocator_base::mem_allocator_base(const vk::render_device& dev, VkPhysicalDevice /*pdev*/)
|
||||
: m_device(dev), m_allocation_flags(0)
|
||||
{}
|
||||
|
||||
mem_allocator_vma::mem_allocator_vma(const vk::render_device& dev, VkPhysicalDevice pdev)
|
||||
mem_allocator_vma::mem_allocator_vma(const vk::render_device& dev, VkPhysicalDevice pdev, VkInstance inst)
|
||||
: mem_allocator_base(dev, pdev)
|
||||
{
|
||||
// Initialize stats pool
|
||||
|
@ -166,6 +166,8 @@ namespace vk
|
|||
VmaAllocatorCreateInfo allocatorInfo = {};
|
||||
allocatorInfo.physicalDevice = pdev;
|
||||
allocatorInfo.device = dev;
|
||||
allocatorInfo.instance = inst;
|
||||
allocatorInfo.vulkanApiVersion = VK_API_VERSION_1_0;
|
||||
|
||||
std::vector<VkDeviceSize> heap_limits;
|
||||
const auto vram_allocation_limit = g_cfg.video.vk.vram_allocation_limit * 0x100000ull;
|
||||
|
@ -299,7 +301,7 @@ namespace vk
|
|||
|
||||
f32 mem_allocator_vma::get_memory_usage()
|
||||
{
|
||||
vmaGetBudget(m_allocator, stats.data());
|
||||
vmaGetHeapBudgets(m_allocator, stats.data());
|
||||
|
||||
float max_usage = 0.f;
|
||||
for (const auto& info : stats)
|
||||
|
|
|
@ -4,7 +4,15 @@
|
|||
#include "../../rsx_utils.h"
|
||||
#include "shared.h"
|
||||
|
||||
#include "3rdparty/GPUOpen/VulkanMemoryAllocator/src/vk_mem_alloc.h"
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wnullability-completeness"
|
||||
#endif
|
||||
#define VMA_VULKAN_VERSION 1000000
|
||||
#include "3rdparty/GPUOpen/VulkanMemoryAllocator/include/vk_mem_alloc.h"
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
namespace vk
|
||||
{
|
||||
|
@ -55,7 +63,7 @@ namespace vk
|
|||
public:
|
||||
using mem_handle_t = void*;
|
||||
|
||||
mem_allocator_base(const vk::render_device& dev, VkPhysicalDevice /*pdev*/);
|
||||
mem_allocator_base(const vk::render_device& dev, VkPhysicalDevice pdev);
|
||||
virtual ~mem_allocator_base() = default;
|
||||
|
||||
virtual void destroy() = 0;
|
||||
|
@ -83,7 +91,7 @@ namespace vk
|
|||
class mem_allocator_vma : public mem_allocator_base
|
||||
{
|
||||
public:
|
||||
mem_allocator_vma(const vk::render_device& dev, VkPhysicalDevice pdev);
|
||||
mem_allocator_vma(const vk::render_device& dev, VkPhysicalDevice pdev, VkInstance inst);
|
||||
~mem_allocator_vma() override = default;
|
||||
|
||||
void destroy() override;
|
||||
|
|
|
@ -705,6 +705,11 @@ namespace rsx
|
|||
return decode<NV4097_SET_USER_CLIP_PLANE_CONTROL>().clip_plane5();
|
||||
}
|
||||
|
||||
u32 clip_planes_mask() const
|
||||
{
|
||||
return registers[NV4097_SET_USER_CLIP_PLANE_CONTROL];
|
||||
}
|
||||
|
||||
front_face front_face_mode() const
|
||||
{
|
||||
return decode<NV4097_SET_FRONT_FACE>().front_face_mode();
|
||||
|
|
|
@ -185,13 +185,13 @@ void Emulator::CallFromMainThread(std::function<void()>&& func, atomic_t<u32>* w
|
|||
m_cb.call_from_main_thread(std::move(final_func), wake_up);
|
||||
}
|
||||
|
||||
void Emulator::BlockingCallFromMainThread(std::function<void()>&& func, std::source_location src_loc) const
|
||||
void Emulator::BlockingCallFromMainThread(std::function<void()>&& func, bool track_emu_state, std::source_location src_loc) const
|
||||
{
|
||||
atomic_t<u32> wake_up = 0;
|
||||
|
||||
sys_log.trace("Blocking Callback from thread '%s' at [%s] is queued", thread_ctrl::get_name(), src_loc);
|
||||
|
||||
CallFromMainThread(std::move(func), &wake_up, true, umax, src_loc);
|
||||
CallFromMainThread(std::move(func), &wake_up, track_emu_state, umax, src_loc);
|
||||
|
||||
bool logged = false;
|
||||
|
||||
|
|
|
@ -210,7 +210,7 @@ public:
|
|||
std::source_location src_loc = std::source_location::current()) const;
|
||||
|
||||
// Blocking call from the GUI thread
|
||||
void BlockingCallFromMainThread(std::function<void()>&& func, std::source_location src_loc = std::source_location::current()) const;
|
||||
void BlockingCallFromMainThread(std::function<void()>&& func, bool track_emu_state = true, std::source_location src_loc = std::source_location::current()) const;
|
||||
|
||||
enum class stop_counter_t : u64{};
|
||||
|
||||
|
|
|
@ -646,7 +646,7 @@ int ds4_pad_handler::send_output_report(DS4Device* device)
|
|||
|
||||
const auto config = device->config;
|
||||
if (config == nullptr)
|
||||
return -2; // hid_write and hid_write_control return -1 on error
|
||||
return -2; // hid_write returns -1 on error
|
||||
|
||||
// write rumble state
|
||||
ds4_output_report_common common{};
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#ifdef HAVE_SDL3
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "sdl_instance.h"
|
||||
#include "Emu/System.h"
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#pragma GCC diagnostic push
|
||||
|
@ -11,10 +13,6 @@
|
|||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#include "util/logs.hpp"
|
||||
|
||||
#include "sdl_instance.h"
|
||||
|
||||
LOG_CHANNEL(sdl_log, "SDL");
|
||||
|
||||
sdl_instance::~sdl_instance()
|
||||
|
@ -35,9 +33,12 @@ sdl_instance& sdl_instance::get_instance()
|
|||
|
||||
void sdl_instance::pump_events()
|
||||
{
|
||||
const std::lock_guard<std::mutex> lock(m_instance_mutex);
|
||||
std::lock_guard lock(m_instance_mutex);
|
||||
|
||||
if (m_initialized)
|
||||
{
|
||||
SDL_PumpEvents();
|
||||
}
|
||||
}
|
||||
|
||||
void sdl_instance::set_hint(const char* name, const char* value)
|
||||
|
@ -50,7 +51,25 @@ void sdl_instance::set_hint(const char* name, const char* value)
|
|||
|
||||
bool sdl_instance::initialize()
|
||||
{
|
||||
const std::lock_guard<std::mutex> lock(m_instance_mutex);
|
||||
std::lock_guard lock(m_instance_mutex);
|
||||
|
||||
if (m_initialized)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool instance_success = false;
|
||||
|
||||
Emu.BlockingCallFromMainThread([this, &instance_success]()
|
||||
{
|
||||
instance_success = initialize_impl();
|
||||
}, false);
|
||||
|
||||
return instance_success;
|
||||
}
|
||||
|
||||
bool sdl_instance::initialize_impl()
|
||||
{
|
||||
// Only init SDL once. SDL uses a global state internally...
|
||||
if (m_initialized)
|
||||
{
|
||||
|
|
|
@ -8,7 +8,7 @@ struct sdl_instance
|
|||
{
|
||||
public:
|
||||
sdl_instance() = default;
|
||||
~sdl_instance();
|
||||
virtual ~sdl_instance();
|
||||
|
||||
static sdl_instance& get_instance();
|
||||
|
||||
|
@ -17,6 +17,7 @@ public:
|
|||
|
||||
private:
|
||||
void set_hint(const char* name, const char* value);
|
||||
bool initialize_impl();
|
||||
|
||||
bool m_initialized = false;
|
||||
std::mutex m_instance_mutex;
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
#include "stdafx.h"
|
||||
#include "sdl_pad_handler.h"
|
||||
#include "sdl_instance.h"
|
||||
#include "Emu/system_utils.hpp"
|
||||
#include "Emu/system_config.h"
|
||||
#include "Emu/System.h"
|
||||
#include "sdl_instance.h"
|
||||
|
||||
#include <mutex>
|
||||
|
||||
|
@ -180,14 +180,7 @@ bool sdl_pad_handler::Init()
|
|||
if (m_is_init)
|
||||
return true;
|
||||
|
||||
bool instance_success;
|
||||
|
||||
Emu.BlockingCallFromMainThread([&instance_success]()
|
||||
{
|
||||
instance_success = sdl_instance::get_instance().initialize();
|
||||
});
|
||||
|
||||
if (!instance_success)
|
||||
if (!sdl_instance::get_instance().initialize())
|
||||
return false;
|
||||
|
||||
if (g_cfg.io.load_sdl_mappings)
|
||||
|
@ -301,7 +294,7 @@ SDLDevice::sdl_info sdl_pad_handler::get_sdl_info(SDL_JoystickID id)
|
|||
}
|
||||
}
|
||||
|
||||
sdl_log.error("Found game pad %d: type=%d, real_type=%d, name='%s', guid='%s', path='%s', serial='%s', vid=0x%x, pid=0x%x, product_version=0x%x, firmware_version=0x%x, has_led=%d, has_player_led=%d, has_mono_led=%d, has_rumble=%d, has_rumble_triggers=%d, has_accel=%d, has_gyro=%d",
|
||||
sdl_log.notice("Found game pad %d: type=%d, real_type=%d, name='%s', guid='%s', path='%s', serial='%s', vid=0x%x, pid=0x%x, product_version=0x%x, firmware_version=0x%x, has_led=%d, has_player_led=%d, has_mono_led=%d, has_rumble=%d, has_rumble_triggers=%d, has_accel=%d, has_gyro=%d",
|
||||
id, static_cast<int>(info.type), static_cast<int>(info.real_type), info.name, info.guid, info.path, info.serial, info.vid, info.pid, info.product_version, info.firmware_version, info.has_led, info.has_player_led, info.has_mono_led, info.has_rumble, info.has_rumble_triggers, info.has_accel, info.has_gyro);
|
||||
|
||||
if (info.has_accel)
|
||||
|
|
|
@ -454,6 +454,7 @@
|
|||
<ClCompile Include="Emu\Io\usb_vfs.cpp" />
|
||||
<ClCompile Include="Emu\RSX\Capture\rsx_capture.cpp" />
|
||||
<ClCompile Include="Emu\RSX\Capture\rsx_replay.cpp" />
|
||||
<ClCompile Include="Emu\RSX\Program\CgBinaryProgram.cpp" />
|
||||
<ClCompile Include="Emu\RSX\Program\CgBinaryFragmentProgram.cpp" />
|
||||
<ClCompile Include="Emu\RSX\Program\CgBinaryVertexProgram.cpp" />
|
||||
<ClCompile Include="Emu\RSX\Common\BufferUtils.cpp" />
|
||||
|
|
|
@ -1099,6 +1099,9 @@
|
|||
<ClCompile Include="Emu\RSX\Program\VertexProgramDecompiler.cpp">
|
||||
<Filter>Emu\GPU\RSX\Program</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\RSX\Program\CgBinaryProgram.cpp">
|
||||
<Filter>Emu\GPU\RSX\Program</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\RSX\Program\CgBinaryFragmentProgram.cpp">
|
||||
<Filter>Emu\GPU\RSX\Program</Filter>
|
||||
</ClCompile>
|
||||
|
|
|
@ -68,6 +68,7 @@ enum class mapping_device
|
|||
SHIFTER_5,
|
||||
SHIFTER_6,
|
||||
SHIFTER_R,
|
||||
SHIFTER_PRESS,
|
||||
|
||||
// Enum count
|
||||
COUNT
|
||||
|
@ -109,6 +110,7 @@ QString device_name(mapping_device dev)
|
|||
case mapping_device::SHIFTER_5: return QObject::tr("Gear 5");
|
||||
case mapping_device::SHIFTER_6: return QObject::tr("Gear 6");
|
||||
case mapping_device::SHIFTER_R: return QObject::tr("Gear R");
|
||||
case mapping_device::SHIFTER_PRESS: return QObject::tr("Shifter press");
|
||||
case mapping_device::COUNT: return "";
|
||||
}
|
||||
return "";
|
||||
|
@ -151,6 +153,7 @@ emulated_logitech_g27_mapping& device_cfg(mapping_device dev)
|
|||
case mapping_device::SHIFTER_5: return cfg.shifter_5;
|
||||
case mapping_device::SHIFTER_6: return cfg.shifter_6;
|
||||
case mapping_device::SHIFTER_R: return cfg.shifter_r;
|
||||
case mapping_device::SHIFTER_PRESS: return cfg.shifter_press;
|
||||
default: fmt::throw_exception("Unexpected mapping_device %d", static_cast<int>(dev));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
#include "table_item_delegate.h"
|
||||
#include "Emu/RSX/RSXThread.h"
|
||||
#include "Emu/RSX/gcm_printing.h"
|
||||
#include "Emu/RSX/Common/BufferUtils.h"
|
||||
#include "Emu/RSX/Program/CgBinaryProgram.h"
|
||||
#include "Utilities/File.h"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
|
@ -123,17 +125,6 @@ rsx_debugger::rsx_debugger(std::shared_ptr<gui_settings> gui_settings, QWidget*
|
|||
vbox_tools->addLayout(hbox_controls);
|
||||
vbox_tools->addWidget(m_tw_rsx);
|
||||
|
||||
// State explorer
|
||||
m_text_transform_program = new QLabel();
|
||||
m_text_transform_program->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextSelectableByKeyboard);
|
||||
m_text_transform_program->setFont(mono);
|
||||
m_text_transform_program->setText("");
|
||||
|
||||
m_text_shader_program = new QLabel();
|
||||
m_text_shader_program->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextSelectableByKeyboard);
|
||||
m_text_shader_program->setFont(mono);
|
||||
m_text_shader_program->setText("");
|
||||
|
||||
m_list_index_buffer = new QListWidget();
|
||||
m_list_index_buffer->setFont(mono);
|
||||
|
||||
|
@ -208,11 +199,31 @@ rsx_debugger::rsx_debugger(std::shared_ptr<gui_settings> gui_settings, QWidget*
|
|||
QWidget* buffers = new QWidget();
|
||||
buffers->setLayout(buffer_layout);
|
||||
|
||||
auto xp_layout = new QHBoxLayout();
|
||||
m_transform_disasm = new QTextEdit(this);
|
||||
m_transform_disasm->setReadOnly(true);
|
||||
m_transform_disasm->setWordWrapMode(QTextOption::NoWrap);
|
||||
m_transform_disasm->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont));
|
||||
xp_layout->addWidget(m_transform_disasm);
|
||||
|
||||
auto xp_tab = new QWidget();
|
||||
xp_tab->setLayout(xp_layout);
|
||||
|
||||
auto fp_layout = new QHBoxLayout();
|
||||
m_fragment_disasm = new QTextEdit(this);
|
||||
m_fragment_disasm->setReadOnly(true);
|
||||
m_fragment_disasm->setWordWrapMode(QTextOption::NoWrap);
|
||||
m_fragment_disasm->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont));
|
||||
fp_layout->addWidget(m_fragment_disasm);
|
||||
|
||||
auto fp_tab = new QWidget();
|
||||
fp_tab->setLayout(fp_layout);
|
||||
|
||||
QTabWidget* state_rsx = new QTabWidget();
|
||||
state_rsx->addTab(buffers, tr("RTTs and DS"));
|
||||
state_rsx->addTab(m_text_transform_program, tr("Transform program"));
|
||||
state_rsx->addTab(m_text_shader_program, tr("Shader program"));
|
||||
state_rsx->addTab(m_list_index_buffer, tr("Index buffer"));
|
||||
state_rsx->addTab(xp_tab, tr("Vertex Program"));
|
||||
state_rsx->addTab(fp_tab, tr("Fragment Program"));
|
||||
state_rsx->addTab(m_list_index_buffer, tr("Index Buffer"));
|
||||
|
||||
QHBoxLayout* main_layout = new QHBoxLayout();
|
||||
main_layout->addLayout(vbox_tools, 1);
|
||||
|
@ -592,10 +603,10 @@ void rsx_debugger::OnClickDrawCalls()
|
|||
}
|
||||
|
||||
// Programs
|
||||
m_text_transform_program->clear();
|
||||
m_text_transform_program->setText(qstr(frame_debug.draw_calls[draw_id].programs.first));
|
||||
m_text_shader_program->clear();
|
||||
m_text_shader_program->setText(qstr(frame_debug.draw_calls[draw_id].programs.second));
|
||||
m_transform_disasm->clear();
|
||||
m_transform_disasm->setText(qstr(frame_debug.draw_calls[draw_id].programs.first));
|
||||
m_fragment_disasm->clear();
|
||||
m_fragment_disasm->setText(qstr(frame_debug.draw_calls[draw_id].programs.second));
|
||||
|
||||
m_list_index_buffer->clear();
|
||||
//m_list_index_buffer->insertColumn(0, "Index", 0, 700);
|
||||
|
@ -621,6 +632,8 @@ void rsx_debugger::UpdateInformation() const
|
|||
{
|
||||
GetMemory();
|
||||
GetBuffers();
|
||||
GetVertexProgram();
|
||||
GetFragmentProgram();
|
||||
}
|
||||
|
||||
void rsx_debugger::GetMemory() const
|
||||
|
@ -1202,3 +1215,111 @@ void rsx_debugger::GetBuffers() const
|
|||
|
||||
m_buffer_tex->showImage(QImage(m_buffer_tex->cache.data(), width, height, QImage::Format_RGB32));
|
||||
}
|
||||
|
||||
void rsx_debugger::GetVertexProgram() const
|
||||
{
|
||||
const auto render = rsx::get_current_renderer();
|
||||
if (!render || !render->is_initialized || !render->local_mem_size || !render->is_paused())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RSXVertexProgram vp;
|
||||
vp.data.reserve(512 * 4);
|
||||
|
||||
const u32 vp_entry = rsx::method_registers.transform_program_start();
|
||||
program_hash_util::vertex_program_utils::analyse_vertex_program
|
||||
(
|
||||
rsx::method_registers.transform_program.data(), // Input raw block
|
||||
vp_entry, // Address of entry point
|
||||
vp // [out] Program object
|
||||
);
|
||||
|
||||
const u32 ucode_len = static_cast<u32>(vp.data.size() * sizeof(u32));
|
||||
std::vector<u32> vp_blob = {
|
||||
7003u, // Type
|
||||
6u, // Revision
|
||||
56u + ucode_len, // Total size
|
||||
0, // paramCount
|
||||
0, // paramArray
|
||||
32u, // Program header offset
|
||||
ucode_len, // Ucode length
|
||||
56u, // Ucode start
|
||||
|
||||
::size32(vp.data) / 4, // Instruction count
|
||||
0, // Slot
|
||||
16u, // Registers used
|
||||
rsx::method_registers.vertex_attrib_input_mask(),
|
||||
rsx::method_registers.vertex_attrib_output_mask(),
|
||||
rsx::method_registers.clip_planes_mask()
|
||||
};
|
||||
|
||||
vp_blob.resize(vp_blob.size() + vp.data.size());
|
||||
std::copy(vp.data.begin(), vp.data.end(), vp_blob.begin() + 14);
|
||||
|
||||
std::span<u32> vp_binary(vp_blob);
|
||||
CgBinaryDisasm vp_disasm(vp_binary);
|
||||
vp_disasm.BuildShaderBody(false);
|
||||
|
||||
m_transform_disasm->clear();
|
||||
m_transform_disasm->setText(QString::fromStdString(vp_disasm.GetArbShader()));
|
||||
}
|
||||
|
||||
void rsx_debugger::GetFragmentProgram() const
|
||||
{
|
||||
const auto render = rsx::get_current_renderer();
|
||||
if (!render || !render->is_initialized || !render->local_mem_size || !render->is_paused())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto [program_offset, program_location] = rsx::method_registers.shader_program_address();
|
||||
const auto address = rsx::get_address(program_offset, program_location, 4);
|
||||
if (!address)
|
||||
{
|
||||
m_fragment_disasm->clear();
|
||||
return;
|
||||
}
|
||||
|
||||
// NOTE: Reading through super ptr while crash-safe means we're probably reading incorrect bytes, but should be fine in 99% of cases
|
||||
auto data_ptr = vm::get_super_ptr(address);
|
||||
const auto fp_metadata = program_hash_util::fragment_program_utils::analyse_fragment_program(data_ptr);
|
||||
|
||||
const bool output_h0 = rsx::method_registers.shader_control() & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS ? false : true;
|
||||
const bool depth_replace = rsx::method_registers.shader_control() & CELL_GCM_SHADER_CONTROL_DEPTH_EXPORT ? true : false;
|
||||
const u32 flags = 16u /* Reg count */ | ((output_h0 /* 16-bit exports? */ ? 1u : 0u) << 8u) | ((depth_replace /* Export depth? */ ? 1u : 0u) << 16u) | (0u /* Uses KILL? */ << 24u);
|
||||
const auto ucode_len = fp_metadata.program_ucode_length;
|
||||
|
||||
std::vector<u32> blob = {
|
||||
7004u, // Type
|
||||
6u, // Revision
|
||||
56u + ucode_len, // Total size
|
||||
0, // paramCount
|
||||
0, // paramArray
|
||||
32u, // Program header offset
|
||||
ucode_len, // Ucode length
|
||||
56u, // Ucode start
|
||||
|
||||
ucode_len / 16, // Instruction count
|
||||
rsx::method_registers.vertex_attrib_output_mask(), // Slot
|
||||
0u, // Partial load
|
||||
0u | (rsx::method_registers.texcoord_control_mask() << 16u), // Texcoord input mask | tex2d control
|
||||
0u | (flags << 16u), // Centroid inputs (xor tex2d control) | flags (regs, 16-bit, fragDepth, KILL)
|
||||
|
||||
0u, // Padding
|
||||
};
|
||||
|
||||
// Copy in the program bytes, swapped
|
||||
const u32 start_offset_in_words = fp_metadata.program_start_offset / 4;
|
||||
const u32 ucode_length_in_words = fp_metadata.program_ucode_length / 4;
|
||||
blob.resize(blob.size() + ucode_length_in_words);
|
||||
copy_data_swap_u32(blob.data() + 14, utils::bless<u32>(data_ptr) + start_offset_in_words, ucode_length_in_words);
|
||||
//std::memcpy(blob.data() + 14, utils::bless<char>(data_ptr) + fp_metadata.program_start_offset, fp_metadata.program_ucode_length);
|
||||
|
||||
std::span<u32> fp_binary(blob);
|
||||
CgBinaryDisasm fp_disasm(fp_binary);
|
||||
fp_disasm.BuildShaderBody(false);
|
||||
|
||||
m_fragment_disasm->clear();
|
||||
m_fragment_disasm->setText(QString::fromStdString(fp_disasm.GetArbShader()));
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <QListWidget>
|
||||
#include <QTableWidget>
|
||||
#include <QTabWidget>
|
||||
#include <QTextEdit>
|
||||
|
||||
#include <memory>
|
||||
|
||||
|
@ -61,8 +62,8 @@ class rsx_debugger : public QDialog
|
|||
Buffer* m_buffer_tex;
|
||||
QLabel* m_enabled_textures_label;
|
||||
|
||||
QLabel* m_text_transform_program;
|
||||
QLabel* m_text_shader_program;
|
||||
QTextEdit* m_transform_disasm;
|
||||
QTextEdit* m_fragment_disasm;
|
||||
|
||||
u32 m_cur_texture = 0;
|
||||
u32 m_texture_format_override = 0;
|
||||
|
@ -87,4 +88,7 @@ protected:
|
|||
|
||||
private:
|
||||
void PerformJump(u32 address);
|
||||
|
||||
void GetVertexProgram() const;
|
||||
void GetFragmentProgram() const;
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue