mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-21 03:16:54 +02:00
shader: size per-thread LDS emulation by the guest LDS allocation
This commit is contained in:
@@ -157,9 +157,25 @@ void EmitMemoryOffsets(EmitterState& state) {
|
||||
}
|
||||
}
|
||||
|
||||
// Stages without a workgroup emulate LDS with one private array per invocation. A GPU keeps
|
||||
// hundreds of thousands of invocations in flight, so this size multiplies into driver local memory:
|
||||
// a fixed 8192 dwords (32 KB) asked for gigabytes and killed the device (a write fault in the
|
||||
// first heavy pixel shader that touched LDS). A pixel shader can only address the LDS that
|
||||
// EXTRA_LDS_SIZE reserves, a vertex shader the LDS_SIZE of its GS stage; hardware reads zero and
|
||||
// drops writes beyond it, as the bounds checks do.
|
||||
constexpr uint32_t FUNCTION_LDS_DWORDS = 1024u;
|
||||
|
||||
uint32_t LdsDwordCount(const EmitterState& state) {
|
||||
const auto* workgroup = ShaderWorkgroupInput(state.program.stage, state.input_info);
|
||||
return workgroup != nullptr ? workgroup->lds_size_dwords : 8192u;
|
||||
if (const auto* workgroup = ShaderWorkgroupInput(state.program.stage, state.input_info)) {
|
||||
return workgroup->lds_size_dwords;
|
||||
}
|
||||
if (state.program.stage == ShaderType::Pixel && state.input_info.pixel != nullptr) {
|
||||
return std::max(state.input_info.pixel->lds_size_dwords, 1u);
|
||||
}
|
||||
if (state.program.stage == ShaderType::Vertex && state.input_info.vertex != nullptr) {
|
||||
return std::max(state.input_info.vertex->lds_size_dwords, 1u);
|
||||
}
|
||||
return FUNCTION_LDS_DWORDS;
|
||||
}
|
||||
|
||||
void EnsureLdsStorage(EmitterState& state) {
|
||||
|
||||
@@ -315,6 +315,7 @@ static void ShaderGetStaticInputInfoPS(
|
||||
|
||||
ps_info = {};
|
||||
ps_info.scratch_size_dwords = data.scratch_size_dwords;
|
||||
ps_info.lds_size_dwords = static_cast<uint32_t>(regs.ps_regs.rsrc2.extra_lds_size) * 128u;
|
||||
|
||||
// SPI_PS_IN_CONTROL: NUM_INTERP occupies bits 5:0 and PS_W32_EN is bit 15.
|
||||
ps_info.input_num = sh.ps_in_control & 0x3fu;
|
||||
@@ -411,6 +412,7 @@ void BuildStageStaticKey(const ShaderVertexInputInfo& info, std::vector<uint32_t
|
||||
key.push_back(info.resources_num);
|
||||
key.push_back(info.wave_size);
|
||||
key.push_back(info.scratch_size_dwords);
|
||||
key.push_back(info.lds_size_dwords);
|
||||
key.push_back(info.pa_cl_vs_out_cntl);
|
||||
key.push_back(static_cast<uint32_t>(info.clip_space.enabled));
|
||||
if (info.clip_space.enabled) {
|
||||
@@ -454,6 +456,7 @@ void BuildStageStaticKey(const ShaderPixelInputInfo& info, std::vector<uint32_t>
|
||||
EXIT_IF(info.input_num > std::size(info.interpolator_settings));
|
||||
key.clear();
|
||||
key.push_back(info.scratch_size_dwords);
|
||||
key.push_back(info.lds_size_dwords);
|
||||
key.push_back(info.input_num);
|
||||
key.push_back(info.wave_size);
|
||||
key.push_back(info.ps_system_input_base);
|
||||
@@ -528,6 +531,7 @@ ShaderParams PrepareProgram(const HW::VertexShaderInfo& regs, const HW::Context&
|
||||
EXIT("failed to prepare vertex shader program\n");
|
||||
}
|
||||
info.wave_size = (context.GetShaderStages() & 0x00400000u) != 0 ? 32u : 64u;
|
||||
info.lds_size_dwords = static_cast<uint32_t>(regs.gs_regs.rsrc2.lds_size) * 128u;
|
||||
return params;
|
||||
}
|
||||
// NGG user SGPRs start at s8; a separately compiled GS back half also receives
|
||||
@@ -746,7 +750,8 @@ void ShaderDbgDumpInputInfo(const ShaderPixelInputInfo& info) {
|
||||
"\t ps_no_perspective = %s\n"
|
||||
"\t ps_pixel_kill_enable = %s\n"
|
||||
"\t ps_early_z = %s\n"
|
||||
"\t ps_execute_on_noop = %s\n",
|
||||
"\t ps_execute_on_noop = %s\n"
|
||||
"\t lds_size_dwords = %u\n",
|
||||
info.input_num, info.ps_system_input_base, info.custom_interpolation_mask,
|
||||
info.ps_perspective_center_vgpr, info.ps_perspective_sample_vgpr,
|
||||
info.ps_perspective_centroid_vgpr, info.ps_pos_x ? "true" : "false",
|
||||
@@ -755,7 +760,7 @@ void ShaderDbgDumpInputInfo(const ShaderPixelInputInfo& info) {
|
||||
info.ps_front_face_all_bits ? "true" : "false", info.ps_ancillary ? "true" : "false",
|
||||
info.ps_sample_shading ? "true" : "false", info.ps_no_perspective ? "true" : "false",
|
||||
info.ps_pixel_kill_enable ? "true" : "false", info.ps_early_z ? "true" : "false",
|
||||
info.ps_execute_on_noop ? "true" : "false");
|
||||
info.ps_execute_on_noop ? "true" : "false", info.lds_size_dwords);
|
||||
|
||||
for (uint32_t i = 0; i < info.input_num; i++) {
|
||||
LOGF("\t interpolator_settings[%u] = %u\n", i, info.interpolator_settings[i]);
|
||||
|
||||
@@ -149,6 +149,8 @@ struct ShaderVertexInputInfo {
|
||||
int buffers_num = 0;
|
||||
uint32_t wave_size = 64;
|
||||
uint32_t scratch_size_dwords = 0;
|
||||
// LDS_SIZE of the GS stage a non-NGG vertex shader runs on; usually zero.
|
||||
uint32_t lds_size_dwords = 0;
|
||||
uint32_t pa_cl_vs_out_cntl = 0;
|
||||
ShaderClipSpaceTransform clip_space;
|
||||
ShaderMeshInputInfo mesh;
|
||||
@@ -191,6 +193,8 @@ struct ShaderPixelInputInfo {
|
||||
// CB round mode per converted export: zero adds half an LSB, one truncates.
|
||||
uint8_t target_round_mode = 0;
|
||||
uint32_t scratch_size_dwords = 0;
|
||||
// EXTRA_LDS_SIZE: LDS reserved beyond the interpolants (VGPR spills to LDS).
|
||||
uint32_t lds_size_dwords = 0;
|
||||
bool ps_pos_x = false;
|
||||
bool ps_pos_y = false;
|
||||
bool ps_pos_z = false;
|
||||
|
||||
Reference in New Issue
Block a user