Skip to content

Commit b54c212

Browse files
committed
rsx: Refactor CgBinaryProgram to avoid namespace collision with X11
1 parent 9a150b6 commit b54c212

File tree

6 files changed

+262
-239
lines changed

6 files changed

+262
-239
lines changed

rpcs3/Emu/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,7 @@ target_sources(rpcs3_emu PRIVATE
511511
RSX/Overlays/overlay_video.cpp
512512
RSX/Overlays/Shaders/shader_loading_dialog.cpp
513513
RSX/Overlays/Shaders/shader_loading_dialog_native.cpp
514+
RSX/Program/CgBinaryProgram.cpp
514515
RSX/Program/CgBinaryFragmentProgram.cpp
515516
RSX/Program/CgBinaryVertexProgram.cpp
516517
RSX/Program/FragmentProgramDecompiler.cpp
Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
#include "stdafx.h"
2+
#include "CgBinaryProgram.h"
3+
4+
#ifndef WITHOUT_OPENGL
5+
#include "Emu/RSX/GL/GLVertexProgram.h"
6+
#include "Emu/RSX/GL/GLFragmentProgram.h"
7+
#endif
8+
9+
CgBinaryDisasm::CgBinaryDisasm(const std::string& path)
10+
: m_path(path)
11+
{
12+
fs::file f(path);
13+
if (!f)
14+
{
15+
return;
16+
}
17+
18+
usz buffer_size = f.size();
19+
m_buffer.resize(buffer_size);
20+
f.read(m_buffer, buffer_size);
21+
fmt::append(m_arb_shader, "Loading... [%s]\n", path.c_str());
22+
}
23+
24+
std::string CgBinaryDisasm::GetCgParamType(u32 type)
25+
{
26+
switch (type)
27+
{
28+
case 1045: return "float";
29+
case 1046:
30+
case 1047:
31+
case 1048: return fmt::format("float%d", type - 1044);
32+
case 1064: return "float4x4";
33+
case 1066: return "sampler2D";
34+
case 1069: return "samplerCUBE";
35+
case 1091: return "float1";
36+
37+
default: return fmt::format("!UnkCgType(%d)", type);
38+
}
39+
}
40+
41+
std::string CgBinaryDisasm::GetCgParamName(u32 offset) const
42+
{
43+
return std::string(&m_buffer[offset]);
44+
}
45+
46+
std::string CgBinaryDisasm::GetCgParamRes(u32 /*offset*/) const
47+
{
48+
// rsx_log.warning("GetCgParamRes offset 0x%x", offset);
49+
// TODO
50+
return "";
51+
}
52+
53+
std::string CgBinaryDisasm::GetCgParamSemantic(u32 offset) const
54+
{
55+
return std::string(&m_buffer[offset]);
56+
}
57+
58+
std::string CgBinaryDisasm::GetCgParamValue(u32 offset, u32 end_offset) const
59+
{
60+
std::string offsets = "offsets:";
61+
62+
u32 num = 0;
63+
offset += 6;
64+
while (offset < end_offset)
65+
{
66+
fmt::append(offsets, " %d,", m_buffer[offset] << 8 | m_buffer[offset + 1]);
67+
offset += 4;
68+
num++;
69+
}
70+
71+
if (num > 4)
72+
{
73+
return "";
74+
}
75+
76+
offsets.pop_back();
77+
return fmt::format("num %d ", num) + offsets;
78+
}
79+
80+
void CgBinaryDisasm::ConvertToLE(CgBinaryProgram& prog)
81+
{
82+
// BE payload, requires that data be swapped
83+
const auto be_profile = prog.profile;
84+
85+
auto swap_be32 = [&](u32 start_offset, size_t size_bytes)
86+
{
87+
auto start = reinterpret_cast<u32*>(m_buffer.data() + start_offset);
88+
auto end = reinterpret_cast<u32*>(m_buffer.data() + start_offset + size_bytes);
89+
90+
for (auto data = start; data < end; ++data)
91+
{
92+
*data = std::bit_cast<be_t<u32>>(*data);
93+
}
94+
};
95+
96+
// 1. Swap the header
97+
swap_be32(0, sizeof(CgBinaryProgram));
98+
99+
// 2. Swap parameters
100+
swap_be32(prog.parameterArray, sizeof(CgBinaryParameter) * prog.parameterCount);
101+
102+
// 3. Swap the ucode
103+
swap_be32(prog.ucode, m_buffer.size() - prog.ucode);
104+
105+
// 4. Swap the domain header
106+
if (be_profile == 7004u)
107+
{
108+
// Need to swap each field individually
109+
auto& fprog = GetCgRef<CgBinaryFragmentProgram>(prog.program);
110+
fprog.instructionCount = std::bit_cast<be_t<u32>>(fprog.instructionCount);
111+
fprog.attributeInputMask = std::bit_cast<be_t<u32>>(fprog.attributeInputMask);
112+
fprog.partialTexType = std::bit_cast<be_t<u32>>(fprog.partialTexType);
113+
fprog.texCoordsInputMask = std::bit_cast<be_t<u16>>(fprog.texCoordsInputMask);
114+
fprog.texCoords2D = std::bit_cast<be_t<u16>>(fprog.texCoords2D);
115+
fprog.texCoordsCentroid = std::bit_cast<be_t<u16>>(fprog.texCoordsCentroid);
116+
}
117+
else
118+
{
119+
// Swap entire header block as all fields are u32
120+
swap_be32(prog.program, sizeof(CgBinaryVertexProgram));
121+
}
122+
}
123+
124+
void CgBinaryDisasm::BuildShaderBody(bool include_glsl)
125+
{
126+
ParamArray param_array;
127+
128+
auto& prog = GetCgRef<CgBinaryProgram>(0);
129+
130+
if (const u32 be_profile = std::bit_cast<be_t<u32>>(prog.profile);
131+
be_profile == 7003u || be_profile == 7004u)
132+
{
133+
ConvertToLE(prog);
134+
ensure(be_profile == prog.profile);
135+
}
136+
137+
if (prog.profile == 7004u)
138+
{
139+
auto& fprog = GetCgRef<CgBinaryFragmentProgram>(prog.program);
140+
m_arb_shader += "\n";
141+
fmt::append(m_arb_shader, "# binaryFormatRevision 0x%x\n", prog.binaryFormatRevision);
142+
fmt::append(m_arb_shader, "# profile sce_fp_rsx\n");
143+
fmt::append(m_arb_shader, "# parameterCount %d\n", prog.parameterCount);
144+
fmt::append(m_arb_shader, "# instructionCount %d\n", fprog.instructionCount);
145+
fmt::append(m_arb_shader, "# attributeInputMask 0x%x\n", fprog.attributeInputMask);
146+
fmt::append(m_arb_shader, "# registerCount %d\n\n", fprog.registerCount);
147+
148+
CgBinaryParameterOffset offset = prog.parameterArray;
149+
for (u32 i = 0; i < prog.parameterCount; i++)
150+
{
151+
auto& fparam = GetCgRef<CgBinaryParameter>(offset);
152+
153+
std::string param_type = GetCgParamType(fparam.type) + " ";
154+
std::string param_name = GetCgParamName(fparam.name) + " ";
155+
std::string param_res = GetCgParamRes(fparam.res) + " ";
156+
std::string param_semantic = GetCgParamSemantic(fparam.semantic) + " ";
157+
std::string param_const = GetCgParamValue(fparam.embeddedConst, fparam.name);
158+
159+
fmt::append(m_arb_shader, "#%d%s%s%s%s\n", i, param_type, param_name, param_semantic, param_const);
160+
161+
offset += u32{sizeof(CgBinaryParameter)};
162+
}
163+
164+
m_arb_shader += "\n";
165+
m_offset = prog.ucode;
166+
TaskFP();
167+
168+
if (!include_glsl)
169+
{
170+
return;
171+
}
172+
173+
u32 unused;
174+
std::vector<u32> be_data;
175+
176+
// Swap bytes. FP decompiler expects input in BE
177+
for (u32* ptr = reinterpret_cast<u32*>(m_buffer.data() + m_offset),
178+
*end = reinterpret_cast<u32*>(m_buffer.data() + m_buffer.size());
179+
ptr < end; ++ptr)
180+
{
181+
be_data.push_back(std::bit_cast<be_t<u32>>(*ptr));
182+
}
183+
184+
RSXFragmentProgram rsx_prog;
185+
auto metadata = program_hash_util::fragment_program_utils::analyse_fragment_program(be_data.data());
186+
rsx_prog.ctrl = (fprog.outputFromH0 ? 0 : 0x40) | (fprog.depthReplace ? 0xe : 0);
187+
rsx_prog.offset = metadata.program_start_offset;
188+
rsx_prog.ucode_length = metadata.program_ucode_length;
189+
rsx_prog.total_length = metadata.program_ucode_length + metadata.program_start_offset;
190+
rsx_prog.data = reinterpret_cast<u8*>(be_data.data()) + metadata.program_start_offset;
191+
for (u32 i = 0; i < 16; ++i) rsx_prog.texture_state.set_dimension(rsx::texture_dimension_extended::texture_dimension_2d, i);
192+
#ifndef WITHOUT_OPENGL
193+
GLFragmentDecompilerThread(m_glsl_shader, param_array, rsx_prog, unused).Task();
194+
#endif
195+
}
196+
197+
else
198+
{
199+
const auto& vprog = GetCgRef<CgBinaryVertexProgram>(prog.program);
200+
m_arb_shader += "\n";
201+
fmt::append(m_arb_shader, "# binaryFormatRevision 0x%x\n", prog.binaryFormatRevision);
202+
fmt::append(m_arb_shader, "# profile sce_vp_rsx\n");
203+
fmt::append(m_arb_shader, "# parameterCount %d\n", prog.parameterCount);
204+
fmt::append(m_arb_shader, "# instructionCount %d\n", vprog.instructionCount);
205+
fmt::append(m_arb_shader, "# registerCount %d\n", vprog.registerCount);
206+
fmt::append(m_arb_shader, "# attributeInputMask 0x%x\n", vprog.attributeInputMask);
207+
fmt::append(m_arb_shader, "# attributeOutputMask 0x%x\n\n", vprog.attributeOutputMask);
208+
209+
CgBinaryParameterOffset offset = prog.parameterArray;
210+
for (u32 i = 0; i < prog.parameterCount; i++)
211+
{
212+
auto& vparam = GetCgRef<CgBinaryParameter>(offset);
213+
214+
std::string param_type = GetCgParamType(vparam.type) + " ";
215+
std::string param_name = GetCgParamName(vparam.name) + " ";
216+
std::string param_res = GetCgParamRes(vparam.res) + " ";
217+
std::string param_semantic = GetCgParamSemantic(vparam.semantic) + " ";
218+
std::string param_const = GetCgParamValue(vparam.embeddedConst, vparam.name);
219+
220+
fmt::append(m_arb_shader, "#%d%s%s%s%s\n", i, param_type, param_name, param_semantic, param_const);
221+
222+
offset += u32{sizeof(CgBinaryParameter)};
223+
}
224+
225+
m_arb_shader += "\n";
226+
m_offset = prog.ucode;
227+
ensure((m_buffer.size() - m_offset) % sizeof(u32) == 0);
228+
229+
u32* vdata = reinterpret_cast<u32*>(&m_buffer[m_offset]);
230+
m_data.resize(prog.ucodeSize / sizeof(u32));
231+
std::memcpy(m_data.data(), vdata, prog.ucodeSize);
232+
TaskVP();
233+
234+
if (!include_glsl)
235+
{
236+
return;
237+
}
238+
239+
RSXVertexProgram rsx_prog;
240+
program_hash_util::vertex_program_utils::analyse_vertex_program(vdata, 0, rsx_prog);
241+
for (u32 i = 0; i < 4; ++i) rsx_prog.texture_state.set_dimension(rsx::texture_dimension_extended::texture_dimension_2d, i);
242+
#ifndef WITHOUT_OPENGL
243+
GLVertexDecompilerThread(rsx_prog, m_glsl_shader, param_array).Task();
244+
#endif
245+
}
246+
}

0 commit comments

Comments
 (0)