mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-20 19:45:20 +00:00
Merge branch 'master' into raw_mouse_fix
This commit is contained in:
commit
ce736e3578
15 changed files with 172 additions and 43 deletions
2
3rdparty/libpng/libpng
vendored
2
3rdparty/libpng/libpng
vendored
|
@ -1 +1 @@
|
|||
Subproject commit f5e92d76973a7a53f517579bc95d61483bf108c0
|
||||
Subproject commit 51f5bd68b9b806d2c92b4318164d28b49357da31
|
2
3rdparty/pugixml
vendored
2
3rdparty/pugixml
vendored
|
@ -1 +1 @@
|
|||
Subproject commit db78afc2b7d8f043b4bc6b185635d949ea2ed2a8
|
||||
Subproject commit ee86beb30e4973f5feffe3ce63bfa4fbadf72f38
|
|
@ -21,7 +21,7 @@ using namespace std::literals::string_literals;
|
|||
#include <cwchar>
|
||||
#include <Windows.h>
|
||||
|
||||
static std::unique_ptr<wchar_t[]> to_wchar(const std::string& source)
|
||||
static std::unique_ptr<wchar_t[]> to_wchar(std::string_view source)
|
||||
{
|
||||
// String size + null terminator
|
||||
const usz buf_size = source.size() + 1;
|
||||
|
@ -44,7 +44,7 @@ static std::unique_ptr<wchar_t[]> to_wchar(const std::string& source)
|
|||
std::memcpy(buffer.get() + 32768 + 4, L"UNC\\", 4 * sizeof(wchar_t));
|
||||
}
|
||||
|
||||
ensure(MultiByteToWideChar(CP_UTF8, 0, source.c_str(), size, buffer.get() + 32768 + (unc ? 8 : 4), size)); // "to_wchar"
|
||||
ensure(MultiByteToWideChar(CP_UTF8, 0, source.data(), size, buffer.get() + 32768 + (unc ? 8 : 4), size)); // "to_wchar"
|
||||
|
||||
// Canonicalize wide path (replace '/', ".", "..", \\ repetitions, etc)
|
||||
ensure(GetFullPathNameW(buffer.get() + 32768, 32768, buffer.get(), nullptr) - 1 < 32768 - 1); // "to_wchar"
|
||||
|
|
|
@ -49,12 +49,11 @@ std::string rXmlNode::GetName()
|
|||
return {};
|
||||
}
|
||||
|
||||
std::string rXmlNode::GetAttribute(const std::string& name)
|
||||
std::string rXmlNode::GetAttribute(std::string_view name)
|
||||
{
|
||||
if (handle)
|
||||
{
|
||||
const auto pred = [&name](const pugi::xml_attribute& attr) { return (name == attr.name()); };
|
||||
if (const pugi::xml_attribute attr = handle.find_attribute(pred))
|
||||
if (const pugi::xml_attribute attr = handle.attribute(name))
|
||||
{
|
||||
if (const pugi::char_t* value = attr.value())
|
||||
{
|
||||
|
@ -86,7 +85,7 @@ rXmlDocument::rXmlDocument()
|
|||
{
|
||||
}
|
||||
|
||||
pugi::xml_parse_result rXmlDocument::Read(const std::string& data)
|
||||
pugi::xml_parse_result rXmlDocument::Read(std::string_view data)
|
||||
{
|
||||
if (handle)
|
||||
{
|
||||
|
|
|
@ -23,7 +23,7 @@ struct rXmlNode
|
|||
std::shared_ptr<rXmlNode> GetChildren();
|
||||
std::shared_ptr<rXmlNode> GetNext();
|
||||
std::string GetName();
|
||||
std::string GetAttribute(const std::string& name);
|
||||
std::string GetAttribute(std::string_view name);
|
||||
std::string GetNodeContent();
|
||||
|
||||
pugi::xml_node handle{};
|
||||
|
@ -34,7 +34,7 @@ struct rXmlDocument
|
|||
rXmlDocument();
|
||||
rXmlDocument(const rXmlDocument& other) = delete;
|
||||
rXmlDocument &operator=(const rXmlDocument& other) = delete;
|
||||
pugi::xml_parse_result Read(const std::string& data);
|
||||
pugi::xml_parse_result Read(std::string_view data);
|
||||
virtual std::shared_ptr<rXmlNode> GetRoot();
|
||||
|
||||
pugi::xml_document handle{};
|
||||
|
|
|
@ -735,7 +735,7 @@ namespace rsx
|
|||
utils::stream_vector(dst + 4, 0u, fog_mode, std::bit_cast<u32>(wpos_scale), std::bit_cast<u32>(wpos_bias));
|
||||
}
|
||||
|
||||
void draw_command_processor::fill_constants_instancing_buffer(rsx::io_buffer& indirection_table_buf, rsx::io_buffer& constants_data_array_buffer, const VertexProgramBase& prog) const
|
||||
void draw_command_processor::fill_constants_instancing_buffer(rsx::io_buffer& indirection_table_buf, rsx::io_buffer& constants_data_array_buffer, const VertexProgramBase* prog) const
|
||||
{
|
||||
auto& draw_call = REGS(m_ctx)->current_draw_clause;
|
||||
|
||||
|
@ -745,8 +745,9 @@ namespace rsx
|
|||
// Temp indirection table. Used to track "running" updates.
|
||||
rsx::simple_array<u32> instancing_indirection_table;
|
||||
// indirection table size
|
||||
const auto reloc_table = prog.has_indexed_constants ? decltype(prog.constant_ids){} : prog.constant_ids;
|
||||
const auto redirection_table_size = prog.has_indexed_constants ? 468u : ::size32(prog.constant_ids);
|
||||
const auto full_reupload = !prog || prog->has_indexed_constants;
|
||||
const auto reloc_table = full_reupload ? decltype(prog->constant_ids){} : prog->constant_ids;
|
||||
const auto redirection_table_size = full_reupload ? 468u : ::size32(prog->constant_ids);
|
||||
instancing_indirection_table.resize(redirection_table_size);
|
||||
|
||||
// Temp constants data
|
||||
|
@ -787,9 +788,9 @@ namespace rsx
|
|||
continue;
|
||||
}
|
||||
|
||||
const int translated_offset = prog.has_indexed_constants
|
||||
const int translated_offset = full_reupload
|
||||
? instance_config.patch_load_offset
|
||||
: prog.TranslateConstantsRange(instance_config.patch_load_offset, instance_config.patch_load_count);
|
||||
: prog->translate_constants_range(instance_config.patch_load_offset, instance_config.patch_load_count);
|
||||
|
||||
if (translated_offset >= 0)
|
||||
{
|
||||
|
@ -809,14 +810,14 @@ namespace rsx
|
|||
continue;
|
||||
}
|
||||
|
||||
ensure(!prog.has_indexed_constants);
|
||||
ensure(!full_reupload);
|
||||
|
||||
// Sparse update. Update records individually instead of bulk
|
||||
// FIXME: Range batching optimization
|
||||
const auto load_end = instance_config.patch_load_offset + instance_config.patch_load_count;
|
||||
for (u32 i = 0; i < redirection_table_size; ++i)
|
||||
{
|
||||
const auto read_index = prog.constant_ids[i];
|
||||
const auto read_index = prog->constant_ids[i];
|
||||
if (read_index < instance_config.patch_load_offset || read_index >= load_end)
|
||||
{
|
||||
// Reading outside "hot" range.
|
||||
|
|
|
@ -105,6 +105,6 @@ namespace rsx
|
|||
|
||||
// Fill instancing buffers. A single iobuf is used for both. 256byte alignment enforced to allow global bind
|
||||
// Returns offsets to the index redirection lookup table and constants field array
|
||||
void fill_constants_instancing_buffer(rsx::io_buffer& indirection_table_buf, rsx::io_buffer& constants_data_array_buffer, const VertexProgramBase& prog) const;
|
||||
void fill_constants_instancing_buffer(rsx::io_buffer& indirection_table_buf, rsx::io_buffer& constants_data_array_buffer, const VertexProgramBase* prog) const;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -878,7 +878,7 @@ void GLGSRender::load_program_env()
|
|||
}
|
||||
}
|
||||
|
||||
if (update_fragment_constants && !update_instruction_buffers)
|
||||
if (update_fragment_constants && !m_shader_interpreter.is_interpreter(m_program))
|
||||
{
|
||||
// Fragment constants
|
||||
auto mapping = m_fragment_constants_buffer->alloc_from_heap(fragment_constants_size, m_uniform_buffer_offset_align);
|
||||
|
@ -978,12 +978,18 @@ void GLGSRender::load_program_env()
|
|||
}
|
||||
}
|
||||
|
||||
m_graphics_state.clear(
|
||||
rsx::flags32_t handled_flags =
|
||||
rsx::pipeline_state::fragment_state_dirty |
|
||||
rsx::pipeline_state::vertex_state_dirty |
|
||||
rsx::pipeline_state::transform_constants_dirty |
|
||||
rsx::pipeline_state::fragment_constants_dirty |
|
||||
rsx::pipeline_state::fragment_texture_state_dirty);
|
||||
rsx::pipeline_state::fragment_texture_state_dirty;
|
||||
|
||||
if (update_fragment_constants && !m_shader_interpreter.is_interpreter(m_program))
|
||||
{
|
||||
handled_flags |= rsx::pipeline_state::fragment_constants_dirty;
|
||||
}
|
||||
|
||||
m_graphics_state.clear(handled_flags);
|
||||
}
|
||||
|
||||
bool GLGSRender::is_current_program_interpreted() const
|
||||
|
@ -1039,13 +1045,19 @@ void GLGSRender::update_vertex_env(const gl::vertex_upload_info& upload_info)
|
|||
|
||||
void GLGSRender::patch_transform_constants(rsx::context* ctx, u32 index, u32 count)
|
||||
{
|
||||
if (!m_vertex_prog)
|
||||
if (!m_program || !m_vertex_prog)
|
||||
{
|
||||
// Shouldn't be reachable, but handle it correctly anyway
|
||||
m_graphics_state |= rsx::pipeline_state::transform_constants_dirty;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_vertex_prog->overlaps_constants_range(index, count))
|
||||
{
|
||||
// Nothing meaningful to us
|
||||
return;
|
||||
}
|
||||
|
||||
std::pair<u32, u32> data_range {};
|
||||
void* data_source = nullptr;
|
||||
const auto bound_range = m_transform_constants_buffer->bound_range();
|
||||
|
@ -1059,7 +1071,7 @@ void GLGSRender::patch_transform_constants(rsx::context* ctx, u32 index, u32 cou
|
|||
data_range = { bound_range.first + byte_offset, byte_count};
|
||||
data_source = ®S(ctx)->transform_constants[index];
|
||||
}
|
||||
else if (auto xform_id = m_vertex_prog->TranslateConstantsRange(index, count); xform_id >= 0)
|
||||
else if (auto xform_id = m_vertex_prog->translate_constants_range(index, count); xform_id >= 0)
|
||||
{
|
||||
const auto write_offset = xform_id * 16;
|
||||
const auto byte_count = count * 16;
|
||||
|
|
|
@ -34,7 +34,8 @@ vec2 texture2DMSCoord(const in vec2 coords, const in uint flags)
|
|||
return coords;
|
||||
}
|
||||
|
||||
const vec2 wrapped_coords = mod(coords, vec2(1.0));
|
||||
const vec2 wrapped_coords_raw = mod(coords, vec2(1.0));
|
||||
const vec2 wrapped_coords = mod(wrapped_coords_raw + vec2(1.0), vec2(1.0));
|
||||
const bvec2 wrap_control_mask = bvec2(uvec2(flags) & uvec2(WRAP_S_MASK, WRAP_T_MASK));
|
||||
return _select(coords, wrapped_coords, wrap_control_mask);
|
||||
}
|
||||
|
|
|
@ -110,7 +110,7 @@ namespace rsx
|
|||
multisampled_textures == other.multisampled_textures;
|
||||
}
|
||||
|
||||
int VertexProgramBase::TranslateConstantsRange(int first_index, int count) const
|
||||
int VertexProgramBase::translate_constants_range(int first_index, int count) const
|
||||
{
|
||||
// The constant ids should be sorted, so just find the first one and check for continuity
|
||||
int index = -1;
|
||||
|
@ -157,4 +157,31 @@ namespace rsx
|
|||
// OOB or partial match
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool VertexProgramBase::overlaps_constants_range(int first_index, int count) const
|
||||
{
|
||||
if (has_indexed_constants)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
const int last_index = first_index + count - 1;
|
||||
|
||||
// Early rejection test
|
||||
if (constant_ids.empty() || first_index > constant_ids.back() || last_index < first_index)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for any hits
|
||||
for (auto& idx : constant_ids)
|
||||
{
|
||||
if (idx >= first_index && idx <= last_index)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,6 +67,9 @@ namespace rsx
|
|||
// Translates an incoming range of constants against our mapping.
|
||||
// If there is no linear mapping available, return -1, otherwise returns the translated index of the first slot
|
||||
// TODO: Move this somewhere else during refactor
|
||||
int TranslateConstantsRange(int first_index, int count) const;
|
||||
int translate_constants_range(int first_index, int count) const;
|
||||
|
||||
// Returns true if this program consumes any constants in the range [first, first + count - 1]
|
||||
bool overlaps_constants_range(int first_index, int count) const;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -688,10 +688,10 @@ VKGSRender::VKGSRender(utils::serial* ar) noexcept : GSRender(ar)
|
|||
}
|
||||
|
||||
// Initialize optional allocation information with placeholders
|
||||
m_vertex_env_buffer_info = { m_vertex_env_ring_info.heap->value, 0, 32 };
|
||||
m_vertex_constants_buffer_info = { m_transform_constants_ring_info.heap->value, 0, 32 };
|
||||
m_fragment_env_buffer_info = { m_fragment_env_ring_info.heap->value, 0, 32 };
|
||||
m_fragment_texture_params_buffer_info = { m_fragment_texture_params_ring_info.heap->value, 0, 32 };
|
||||
m_vertex_env_buffer_info = { m_vertex_env_ring_info.heap->value, 0, 16 };
|
||||
m_vertex_constants_buffer_info = { m_transform_constants_ring_info.heap->value, 0, 16 };
|
||||
m_fragment_env_buffer_info = { m_fragment_env_ring_info.heap->value, 0, 16 };
|
||||
m_fragment_texture_params_buffer_info = { m_fragment_texture_params_ring_info.heap->value, 0, 16 };
|
||||
m_raster_env_buffer_info = { m_raster_env_ring_info.heap->value, 0, 128 };
|
||||
|
||||
const auto limits = m_device->gpu().get_limits();
|
||||
|
@ -2192,7 +2192,7 @@ void VKGSRender::load_program_env()
|
|||
return std::make_pair(m_instancing_buffer_ring_info.map(constants_data_table_offset, size), size);
|
||||
});
|
||||
|
||||
m_draw_processor.fill_constants_instancing_buffer(indirection_table_buf, constants_array_buf, *m_vertex_prog);
|
||||
m_draw_processor.fill_constants_instancing_buffer(indirection_table_buf, constants_array_buf, m_vertex_prog);
|
||||
m_instancing_buffer_ring_info.unmap();
|
||||
|
||||
m_instancing_indirection_buffer_info = { m_instancing_buffer_ring_info.heap->value, indirection_table_offset, indirection_table_buf.size() };
|
||||
|
@ -2219,7 +2219,7 @@ void VKGSRender::load_program_env()
|
|||
}
|
||||
}
|
||||
|
||||
if (update_fragment_constants && !update_instruction_buffers)
|
||||
if (update_fragment_constants && !m_shader_interpreter.is_interpreter(m_program))
|
||||
{
|
||||
check_heap_status(VK_HEAP_CHECK_FRAGMENT_CONSTANTS_STORAGE);
|
||||
|
||||
|
@ -2350,9 +2350,9 @@ void VKGSRender::load_program_env()
|
|||
}
|
||||
|
||||
// Clear flags
|
||||
u32 handled_flags = rsx::pipeline_state::fragment_state_dirty |
|
||||
rsx::flags32_t handled_flags =
|
||||
rsx::pipeline_state::fragment_state_dirty |
|
||||
rsx::pipeline_state::vertex_state_dirty |
|
||||
rsx::pipeline_state::fragment_constants_dirty |
|
||||
rsx::pipeline_state::fragment_texture_state_dirty;
|
||||
|
||||
if (!update_instancing_data)
|
||||
|
@ -2360,6 +2360,11 @@ void VKGSRender::load_program_env()
|
|||
handled_flags |= rsx::pipeline_state::transform_constants_dirty;
|
||||
}
|
||||
|
||||
if (update_fragment_constants && !m_shader_interpreter.is_interpreter(m_program))
|
||||
{
|
||||
handled_flags |= rsx::pipeline_state::fragment_constants_dirty;
|
||||
}
|
||||
|
||||
m_graphics_state.clear(handled_flags);
|
||||
}
|
||||
|
||||
|
@ -2438,13 +2443,19 @@ void VKGSRender::update_vertex_env(u32 id, const vk::vertex_upload_info& vertex_
|
|||
|
||||
void VKGSRender::patch_transform_constants(rsx::context* ctx, u32 index, u32 count)
|
||||
{
|
||||
if (!m_vertex_prog)
|
||||
if (!m_program || !m_vertex_prog)
|
||||
{
|
||||
// Shouldn't be reachable, but handle it correctly anyway
|
||||
m_graphics_state |= rsx::pipeline_state::transform_constants_dirty;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_vertex_prog->overlaps_constants_range(index, count))
|
||||
{
|
||||
// Nothing meaningful to us
|
||||
return;
|
||||
}
|
||||
|
||||
// Hot-patching transform constants mid-draw (instanced draw)
|
||||
std::pair<VkDeviceSize, VkDeviceSize> data_range;
|
||||
void* data_source = nullptr;
|
||||
|
@ -2458,7 +2469,7 @@ void VKGSRender::patch_transform_constants(rsx::context* ctx, u32 index, u32 cou
|
|||
data_range = { m_vertex_constants_buffer_info.offset + byte_offset, byte_count };
|
||||
data_source = ®S(ctx)->transform_constants[index];
|
||||
}
|
||||
else if (auto xform_id = m_vertex_prog->TranslateConstantsRange(index, count); xform_id >= 0)
|
||||
else if (auto xform_id = m_vertex_prog->translate_constants_range(index, count); xform_id >= 0)
|
||||
{
|
||||
const auto write_offset = xform_id * 16;
|
||||
const auto byte_count = count * 16;
|
||||
|
|
|
@ -387,7 +387,7 @@ namespace vk
|
|||
|
||||
struct stencilonly_unresolve : depth_resolve_base
|
||||
{
|
||||
VkClearRect region{};
|
||||
VkClearRect clear_region{};
|
||||
VkClearAttachment clear_info{};
|
||||
|
||||
stencilonly_unresolve()
|
||||
|
@ -402,8 +402,8 @@ namespace vk
|
|||
renderpass_config.set_depth_mask(false);
|
||||
|
||||
clear_info.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
region.baseArrayLayer = 0;
|
||||
region.layerCount = 1;
|
||||
clear_region.baseArrayLayer = 0;
|
||||
clear_region.layerCount = 1;
|
||||
|
||||
static_parameters_width = 3;
|
||||
|
||||
|
@ -425,7 +425,7 @@ namespace vk
|
|||
|
||||
void emit_geometry(vk::command_buffer& cmd) override
|
||||
{
|
||||
vkCmdClearAttachments(cmd, 1, &clear_info, 1, ®ion);
|
||||
vkCmdClearAttachments(cmd, 1, &clear_info, 1, &clear_region);
|
||||
|
||||
for (s32 write_mask = 0x1; write_mask <= 0x80; write_mask <<= 1)
|
||||
{
|
||||
|
@ -444,8 +444,8 @@ namespace vk
|
|||
|
||||
auto stencil_view = resolve_image->get_view(rsx::default_remap_vector.with_encoding(VK_REMAP_IDENTITY), VK_IMAGE_ASPECT_STENCIL_BIT);
|
||||
|
||||
region.rect.extent.width = resolve_image->width();
|
||||
region.rect.extent.height = resolve_image->height();
|
||||
clear_region.rect.extent.width = msaa_image->width();
|
||||
clear_region.rect.extent.height = msaa_image->height();
|
||||
|
||||
overlay_pass::run(
|
||||
cmd,
|
||||
|
|
|
@ -400,6 +400,7 @@ namespace rsx
|
|||
fp.texture_state.multisampled_textures = data.fp_multisampled_textures;
|
||||
fp.texcoord_control_mask = data.fp_texcoord_control;
|
||||
fp.two_sided_lighting = !!(data.fp_lighting_flags & 0x1);
|
||||
fp.mrt_buffers_count = data.fp_mrt_count;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -111,6 +111,65 @@ extern char **environ;
|
|||
LOG_CHANNEL(sys_log, "SYS");
|
||||
LOG_CHANNEL(q_debug, "QDEBUG");
|
||||
|
||||
#ifdef _WIN32
|
||||
std::set<std::string> get_one_drive_paths()
|
||||
{
|
||||
std::set<std::string> paths;
|
||||
for (const char* key : { "OneDrive", "OneDriveConsumer", "OneDriveCommercial" })
|
||||
{
|
||||
if (const char* env_path = std::getenv(key))
|
||||
{
|
||||
sys_log.notice("get_one_drive_paths: Found OneDrive env path: '%s' (key='%s')", env_path, key);
|
||||
paths.insert(env_path);
|
||||
}
|
||||
}
|
||||
|
||||
for (const wchar_t* key : { L"Software\\Microsoft\\OneDrive\\Accounts\\Personal" })
|
||||
{
|
||||
HKEY hkey = NULL;
|
||||
LSTATUS status = RegOpenKeyW(HKEY_CURRENT_USER, key, &hkey);
|
||||
if (status != ERROR_SUCCESS)
|
||||
{
|
||||
sys_log.trace("get_one_drive_paths: RegOpenKeyW failed: %s (key='%s')", fmt::win_error{static_cast<unsigned long>(status), nullptr}, wchar_to_utf8(key));
|
||||
continue;
|
||||
}
|
||||
|
||||
std::wstring path_buffer;
|
||||
static_cast<DWORD>(path_buffer.size() - 1);
|
||||
DWORD type = 0U;
|
||||
|
||||
do
|
||||
{
|
||||
path_buffer.resize(path_buffer.size() + MAX_PATH);
|
||||
DWORD buffer_size = static_cast<DWORD>(path_buffer.size() - 1);
|
||||
status = RegQueryValueExW(hkey, L"UserFolder", NULL, &type, reinterpret_cast<LPBYTE>(path_buffer.data()), &buffer_size);
|
||||
}
|
||||
while (status == ERROR_MORE_DATA);
|
||||
|
||||
const LSTATUS close_status = RegCloseKey(hkey);
|
||||
if (close_status != ERROR_SUCCESS)
|
||||
{
|
||||
sys_log.error("get_one_drive_paths: RegCloseKey failed: %s", fmt::win_error{static_cast<unsigned long>(close_status), nullptr});
|
||||
}
|
||||
|
||||
if (status != ERROR_SUCCESS)
|
||||
{
|
||||
sys_log.error("get_one_drive_paths: RegQueryValueExW failed: %s", fmt::win_error{static_cast<unsigned long>(status), nullptr});
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((type == REG_SZ) || (type == REG_EXPAND_SZ) || (type == REG_MULTI_SZ))
|
||||
{
|
||||
const std::string path = wchar_to_utf8(path_buffer.data());
|
||||
sys_log.notice("get_one_drive_paths: Found OneDrive registry path: '%s' (key='%s')", path, wchar_to_utf8(key));
|
||||
paths.insert(path);
|
||||
}
|
||||
}
|
||||
|
||||
return paths;
|
||||
}
|
||||
#endif
|
||||
|
||||
[[noreturn]] extern void report_fatal_error(std::string_view _text, bool is_html = false, bool include_help_text = true)
|
||||
{
|
||||
#ifdef __linux__
|
||||
|
@ -1135,6 +1194,21 @@ int main(int argc, char** argv)
|
|||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
// Check OneDrive locations
|
||||
for (const std::string& one_drive_path : get_one_drive_paths())
|
||||
{
|
||||
if (Emu.IsPathInsideDir(emu_dir, one_drive_path))
|
||||
{
|
||||
report_fatal_error(QObject::tr(
|
||||
"RPCS3 should never be run from a OneDrive path!\n"
|
||||
"Please move RPCS3 to a location not synced by OneDrive.\n"
|
||||
"Current location:\n%0").arg(QString::fromStdString(emu_dir)).toStdString());
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Set timerslack value for Linux. The default value is 50,000ns. Change this to just 1 since we value precise timers.
|
||||
|
|
Loading…
Add table
Reference in a new issue