Skip to content

Commit

Permalink
rsx: Fix creation of corrupted shaders
Browse files Browse the repository at this point in the history
Add some optimizations as well.
  • Loading branch information
elad335 committed Jan 2, 2021
1 parent 2b8eb8d commit 35057fa
Showing 1 changed file with 39 additions and 21 deletions.
60 changes: 39 additions & 21 deletions rpcs3/Emu/RSX/rsx_cache.h
Expand Up @@ -447,17 +447,31 @@ namespace rsx
fs::dir_entry tmp = entries[pos];

const auto filename = directory_path + "/" + tmp.name;
std::vector<u8> bytes;
fs::file f(filename);

if (!f)
{
// Unexpected error, but avoid crash
continue;
}

if (f.size() != sizeof(pipeline_data))
{
rsx_log.error("Removing cached pipeline object %s since it's not binary compatible with the current shader cache", tmp.name.c_str());
fs::remove_file(filename);
continue;
}
f.read<u8>(bytes, f.size());

auto entry = unpack(*reinterpret_cast<pipeline_data*>(bytes.data()));
pipeline_data pdata{};
f.read(&pdata, f.size();

auto entry = unpack(pdata);

if (std::get<1>(entry).data.empty() || !std::get<2>(entry).ucode_length)
{
continue;
}

m_storage.preload_programs(std::get<1>(entry), std::get<2>(entry));

unpacked[unpacked.push_begin()] = entry;
Expand Down Expand Up @@ -573,23 +587,22 @@ namespace rsx

std::string directory_path = root_path + "/pipelines/" + pipeline_class_name + "/" + version_prefix;

if (!fs::is_dir(directory_path))
fs::dir root = fs::dir(directory_path);

if (!root)
{
fs::create_path(directory_path);
fs::create_path(root_path + "/raw");

return;
}

fs::dir root = fs::dir(directory_path);

u32 entry_count = 0;
std::vector<fs::dir_entry> entries;
for (auto It = root.begin(); It != root.end(); ++It, entry_count++)
{
fs::dir_entry tmp = *It;

if (tmp.name == "." || tmp.name == "..")
if (tmp.is_directory || tmp.name.ends_with(".temp"))
continue;

entries.push_back(tmp);
Expand Down Expand Up @@ -648,12 +661,16 @@ namespace rsx

if (!fs::is_file(fp_name))
{
fs::file(fp_name, fs::rewrite).write(fp.get_data(), fp.ucode_length);
const std::string temp_name = fmt::format("%s.%s.temp", fp_name, fmt::base57(utils::get_unique_tsc()));
fs::file(temp_name, fs::rewrite).write(fp.get_data(), fp.ucode_length);
fs::rename(temp_name, fp_name, true); // Atomically write data
}

if (!fs::is_file(vp_name))
{
fs::file(vp_name, fs::rewrite).write<u32>(vp.data);
const std::string temp_name = fmt::format("%s.%s.temp", vp_name, fmt::base57(utils::get_unique_tsc()));
fs::file(temp_name, fs::rewrite).write(vp.data);
fs::rename(temp_name, fp_name, true); // Atomically write data
}

u64 state_hash = 0;
Expand All @@ -669,21 +686,22 @@ namespace rsx
state_hash ^= rpcs3::hash_base<u16>(data.fp_shadow_textures);
state_hash ^= rpcs3::hash_base<u16>(data.fp_redirected_textures);

std::string pipeline_file_name = fmt::format("%llX+%llX+%llX+%llX.bin", data.vertex_program_hash, data.fragment_program_hash, data.pipeline_storage_hash, state_hash);
std::string pipeline_path = root_path + "/pipelines/" + pipeline_class_name + "/" + version_prefix + "/" + pipeline_file_name;
fs::file(pipeline_path, fs::rewrite).write(&data, sizeof(pipeline_data));
const std::string pipeline_file_name = fmt::format("%llX+%llX+%llX+%llX.bin", data.vertex_program_hash, data.fragment_program_hash, data.pipeline_storage_hash, state_hash);
const std::string pipeline_path = root_path + "/pipelines/" + pipeline_class_name + "/" + version_prefix + "/" + pipeline_file_name;
const std::string temp_path = fmt::format("%s.%s.temp", pipeline_path, fmt::base57(utils::get_unique_tsc()));
fs::file(temp_path, fs::rewrite).write(&data, sizeof(data));
fs::rename(temp_path, pipeline_path, true);
}

RSXVertexProgram load_vp_raw(u64 program_hash)
{
std::vector<u32> data;
RSXVertexProgram vp = {};

std::string filename = fmt::format("%llX.vp", program_hash);

fs::file f(root_path + "/raw/" + filename);
f.read<u32>(data, f.size() / sizeof(u32));
if (f) f.read(vp.data, f.size() / sizeof(u32));

RSXVertexProgram vp = {};
vp.data = data;
vp.skip_vertex_input_check = true;

return vp;
Expand All @@ -695,15 +713,15 @@ namespace rsx
std::string filename = fmt::format("%llX.fp", program_hash);

fs::file f(root_path + "/raw/" + filename);
f.read<u8>(data, f.size());
if (f) f.read(data, f.size() / sizeof(u32));

RSXFragmentProgram fp = {};
fp.ucode_length = ::size32(data);
{
std::lock_guard<std::mutex> lock(fpd_mutex);
fragment_program_data[program_hash] = data;
std::lock_guard lock(fpd_mutex);
fragment_program_data.insert_or_assign(program_hash, std::move(data));
fp.data = fragment_program_data[program_hash].data();
}
fp.ucode_length = ::size32(data);

return fp;
}
Expand Down

0 comments on commit 35057fa

Please sign in to comment.