44#include " table_item_delegate.h"
55#include " Emu/RSX/RSXThread.h"
66#include " Emu/RSX/gcm_printing.h"
7+ #include " Emu/RSX/Common/BufferUtils.h"
8+ #include " Emu/RSX/Program/CgBinaryProgram.h"
79#include " Utilities/File.h"
810
911#include < QHBoxLayout>
@@ -123,17 +125,6 @@ rsx_debugger::rsx_debugger(std::shared_ptr<gui_settings> gui_settings, QWidget*
123125 vbox_tools->addLayout (hbox_controls);
124126 vbox_tools->addWidget (m_tw_rsx);
125127
126- // State explorer
127- m_text_transform_program = new QLabel ();
128- m_text_transform_program->setTextInteractionFlags (Qt::TextSelectableByMouse | Qt::TextSelectableByKeyboard);
129- m_text_transform_program->setFont (mono);
130- m_text_transform_program->setText (" " );
131-
132- m_text_shader_program = new QLabel ();
133- m_text_shader_program->setTextInteractionFlags (Qt::TextSelectableByMouse | Qt::TextSelectableByKeyboard);
134- m_text_shader_program->setFont (mono);
135- m_text_shader_program->setText (" " );
136-
137128 m_list_index_buffer = new QListWidget ();
138129 m_list_index_buffer->setFont (mono);
139130
@@ -208,11 +199,31 @@ rsx_debugger::rsx_debugger(std::shared_ptr<gui_settings> gui_settings, QWidget*
208199 QWidget* buffers = new QWidget ();
209200 buffers->setLayout (buffer_layout);
210201
202+ auto xp_layout = new QHBoxLayout ();
203+ m_transform_disasm = new QTextEdit (this );
204+ m_transform_disasm->setReadOnly (true );
205+ m_transform_disasm->setWordWrapMode (QTextOption::NoWrap);
206+ m_transform_disasm->setFont (QFontDatabase::systemFont (QFontDatabase::FixedFont));
207+ xp_layout->addWidget (m_transform_disasm);
208+
209+ auto xp_tab = new QWidget ();
210+ xp_tab->setLayout (xp_layout);
211+
212+ auto fp_layout = new QHBoxLayout ();
213+ m_fragment_disasm = new QTextEdit (this );
214+ m_fragment_disasm->setReadOnly (true );
215+ m_fragment_disasm->setWordWrapMode (QTextOption::NoWrap);
216+ m_fragment_disasm->setFont (QFontDatabase::systemFont (QFontDatabase::FixedFont));
217+ fp_layout->addWidget (m_fragment_disasm);
218+
219+ auto fp_tab = new QWidget ();
220+ fp_tab->setLayout (fp_layout);
221+
211222 QTabWidget* state_rsx = new QTabWidget ();
212223 state_rsx->addTab (buffers, tr (" RTTs and DS" ));
213- state_rsx->addTab (m_text_transform_program , tr (" Transform program " ));
214- state_rsx->addTab (m_text_shader_program , tr (" Shader program " ));
215- state_rsx->addTab (m_list_index_buffer, tr (" Index buffer " ));
224+ state_rsx->addTab (xp_tab , tr (" Vertex Program " ));
225+ state_rsx->addTab (fp_tab , tr (" Fragment Program " ));
226+ state_rsx->addTab (m_list_index_buffer, tr (" Index Buffer " ));
216227
217228 QHBoxLayout* main_layout = new QHBoxLayout ();
218229 main_layout->addLayout (vbox_tools, 1 );
@@ -592,10 +603,10 @@ void rsx_debugger::OnClickDrawCalls()
592603 }
593604
594605 // Programs
595- m_text_transform_program ->clear ();
596- m_text_transform_program ->setText (qstr (frame_debug.draw_calls [draw_id].programs .first ));
597- m_text_shader_program ->clear ();
598- m_text_shader_program ->setText (qstr (frame_debug.draw_calls [draw_id].programs .second ));
606+ m_transform_disasm ->clear ();
607+ m_transform_disasm ->setText (qstr (frame_debug.draw_calls [draw_id].programs .first ));
608+ m_fragment_disasm ->clear ();
609+ m_fragment_disasm ->setText (qstr (frame_debug.draw_calls [draw_id].programs .second ));
599610
600611 m_list_index_buffer->clear ();
601612 // m_list_index_buffer->insertColumn(0, "Index", 0, 700);
@@ -621,6 +632,8 @@ void rsx_debugger::UpdateInformation() const
621632{
622633 GetMemory ();
623634 GetBuffers ();
635+ GetVertexProgram ();
636+ GetFragmentProgram ();
624637}
625638
626639void rsx_debugger::GetMemory () const
@@ -1202,3 +1215,103 @@ void rsx_debugger::GetBuffers() const
12021215
12031216 m_buffer_tex->showImage (QImage (m_buffer_tex->cache .data (), width, height, QImage::Format_RGB32));
12041217}
1218+
1219+ void rsx_debugger::GetVertexProgram () const
1220+ {
1221+ const auto render = rsx::get_current_renderer ();
1222+ if (!render || !render->is_initialized || !render->local_mem_size || !render->is_paused ())
1223+ {
1224+ return ;
1225+ }
1226+
1227+ RSXVertexProgram vp;
1228+ vp.data .reserve (512 * 4 );
1229+
1230+ const u32 vp_entry = rsx::method_registers.transform_program_start ();
1231+ const auto vp_metadata = program_hash_util::vertex_program_utils::analyse_vertex_program
1232+ (
1233+ rsx::method_registers.transform_program .data (), // Input raw block
1234+ vp_entry, // Address of entry point
1235+ vp // [out] Program object
1236+ );
1237+
1238+ const u32 ucode_len = static_cast <u32 >(vp.data .size () * sizeof (u32 ));
1239+ std::vector<u32 > vp_blob = {
1240+ 7003u , // Type
1241+ 6u , // Revision
1242+ 56u + ucode_len, // Total size
1243+ 0 , // paramCount
1244+ 0 , // paramArray
1245+ 32u , // Program header offset
1246+ ucode_len, // Ucode length
1247+ 56u , // Ucode start
1248+
1249+ ::size32 (vp.data) / 4, // Instruction count
1250+ 0, // Slot
1251+ 16u, // Registers used
1252+ rsx::method_registers.vertex_attrib_input_mask(),
1253+ rsx::method_registers.vertex_attrib_output_mask(),
1254+ rsx::method_registers.clip_planes_mask()
1255+ };
1256+
1257+ vp_blob.resize (vp_blob.size () + vp.data .size ());
1258+ std::copy (vp.data .begin (), vp.data .end (), vp_blob.begin () + 14 );
1259+
1260+ std::span<u32 > vp_binary (vp_blob);
1261+ CgBinaryDisasm vp_disasm (vp_binary);
1262+ vp_disasm.BuildShaderBody (false );
1263+
1264+ m_transform_disasm->clear ();
1265+ m_transform_disasm->setText (QString::fromStdString (vp_disasm.GetArbShader ()));
1266+ }
1267+
1268+ void rsx_debugger::GetFragmentProgram () const
1269+ {
1270+ const auto render = rsx::get_current_renderer ();
1271+ if (!render || !render->is_initialized || !render->local_mem_size || !render->is_paused ())
1272+ {
1273+ return ;
1274+ }
1275+
1276+ const auto [program_offset, program_location] = rsx::method_registers.shader_program_address ();
1277+ auto data_ptr = vm::base (rsx::get_address (program_offset, program_location));
1278+ const auto fp_metadata = program_hash_util::fragment_program_utils::analyse_fragment_program (data_ptr);
1279+
1280+ const bool output_h0 = rsx::method_registers.shader_control () & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS ? false : true ;
1281+ const bool depth_replace = rsx::method_registers.shader_control () & CELL_GCM_SHADER_CONTROL_DEPTH_EXPORT ? true : false ;
1282+ 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 );
1283+ const auto ucode_len = fp_metadata.program_ucode_length ;
1284+
1285+ std::vector<u32 > blob = {
1286+ 7004u , // Type
1287+ 6u , // Revision
1288+ 56u + ucode_len, // Total size
1289+ 0 , // paramCount
1290+ 0 , // paramArray
1291+ 32u , // Program header offset
1292+ ucode_len, // Ucode length
1293+ 56u , // Ucode start
1294+
1295+ ucode_len / 16 , // Instruction count
1296+ rsx::method_registers.vertex_attrib_output_mask (), // Slot
1297+ 0u , // Partial load
1298+ 0u | (rsx::method_registers.texcoord_control_mask () << 16u ), // Texcoord input mask | tex2d control
1299+ 0u | (flags << 16u ), // Centroid inputs (xor tex2d control) | flags (regs, 16-bit, fragDepth, KILL)
1300+
1301+ 0u , // Padding
1302+ };
1303+
1304+ // Copy in the program bytes, swapped
1305+ const u32 start_offset_in_words = fp_metadata.program_start_offset / 4 ;
1306+ const u32 ucode_length_in_words = fp_metadata.program_ucode_length / 4 ;
1307+ blob.resize (blob.size () + ucode_length_in_words);
1308+ copy_data_swap_u32 (blob.data () + 14 , utils::bless<u32 >(data_ptr) + start_offset_in_words, ucode_length_in_words);
1309+ // std::memcpy(blob.data() + 14, utils::bless<char>(data_ptr) + fp_metadata.program_start_offset, fp_metadata.program_ucode_length);
1310+
1311+ std::span<u32 > fp_binary (blob);
1312+ CgBinaryDisasm fp_disasm (fp_binary);
1313+ fp_disasm.BuildShaderBody (false );
1314+
1315+ m_fragment_disasm->clear ();
1316+ m_fragment_disasm->setText (QString::fromStdString (fp_disasm.GetArbShader ()));
1317+ }
0 commit comments