summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/CMakeLists.txt3
-rw-r--r--src/common/lz4_compression.cpp76
-rw-r--r--src/common/lz4_compression.h55
-rw-r--r--src/core/CMakeLists.txt2
-rw-r--r--src/core/hle/kernel/object.cpp1
-rw-r--r--src/core/hle/kernel/object.h1
-rw-r--r--src/core/hle/kernel/transfer_memory.cpp22
-rw-r--r--src/core/hle/kernel/transfer_memory.h20
-rw-r--r--src/core/hle/service/am/am.cpp12
-rw-r--r--src/core/loader/nso.cpp17
-rw-r--r--src/video_core/CMakeLists.txt2
-rw-r--r--src/video_core/renderer_opengl/gl_buffer_cache.cpp1
-rw-r--r--src/video_core/renderer_opengl/gl_global_cache.cpp1
-rw-r--r--src/video_core/renderer_opengl/gl_primitive_assembler.cpp2
-rw-r--r--src/video_core/renderer_opengl/gl_primitive_assembler.h2
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp4
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h5
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.cpp1
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.h3
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.cpp2
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.h5
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.h1
-rw-r--r--src/video_core/renderer_opengl/gl_shader_disk_cache.cpp46
-rw-r--r--src/video_core/renderer_opengl/gl_shader_gen.cpp1
-rw-r--r--src/video_core/renderer_opengl/gl_shader_gen.h3
-rw-r--r--src/video_core/renderer_opengl/gl_shader_manager.cpp17
-rw-r--r--src/video_core/renderer_opengl/gl_shader_manager.h11
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp1
-rw-r--r--src/yuzu/game_list.cpp4
-rw-r--r--src/yuzu/game_list.h1
-rw-r--r--src/yuzu/main.cpp48
-rw-r--r--src/yuzu/main.h1
32 files changed, 256 insertions, 115 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index 850ce8006..5639021d3 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -91,6 +91,8 @@ add_library(common STATIC
logging/log.h
logging/text_formatter.cpp
logging/text_formatter.h
+ lz4_compression.cpp
+ lz4_compression.h
math_util.h
memory_hook.cpp
memory_hook.h
@@ -136,3 +138,4 @@ endif()
create_target_directory_groups(common)
target_link_libraries(common PUBLIC Boost::boost fmt microprofile)
+target_link_libraries(common PRIVATE lz4_static)
diff --git a/src/common/lz4_compression.cpp b/src/common/lz4_compression.cpp
new file mode 100644
index 000000000..ade6759bb
--- /dev/null
+++ b/src/common/lz4_compression.cpp
@@ -0,0 +1,76 @@
+// Copyright 2019 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <algorithm>
+#include <lz4hc.h>
+
+#include "common/assert.h"
+#include "common/lz4_compression.h"
+
+namespace Common::Compression {
+
+std::vector<u8> CompressDataLZ4(const u8* source, std::size_t source_size) {
+ ASSERT_MSG(source_size <= LZ4_MAX_INPUT_SIZE, "Source size exceeds LZ4 maximum input size");
+
+ const auto source_size_int = static_cast<int>(source_size);
+ const int max_compressed_size = LZ4_compressBound(source_size_int);
+ std::vector<u8> compressed(max_compressed_size);
+
+ const int compressed_size = LZ4_compress_default(reinterpret_cast<const char*>(source),
+ reinterpret_cast<char*>(compressed.data()),
+ source_size_int, max_compressed_size);
+
+ if (compressed_size <= 0) {
+ // Compression failed
+ return {};
+ }
+
+ compressed.resize(compressed_size);
+
+ return compressed;
+}
+
+std::vector<u8> CompressDataLZ4HC(const u8* source, std::size_t source_size,
+ s32 compression_level) {
+ ASSERT_MSG(source_size <= LZ4_MAX_INPUT_SIZE, "Source size exceeds LZ4 maximum input size");
+
+ compression_level = std::clamp(compression_level, LZ4HC_CLEVEL_MIN, LZ4HC_CLEVEL_MAX);
+
+ const auto source_size_int = static_cast<int>(source_size);
+ const int max_compressed_size = LZ4_compressBound(source_size_int);
+ std::vector<u8> compressed(max_compressed_size);
+
+ const int compressed_size = LZ4_compress_HC(
+ reinterpret_cast<const char*>(source), reinterpret_cast<char*>(compressed.data()),
+ source_size_int, max_compressed_size, compression_level);
+
+ if (compressed_size <= 0) {
+ // Compression failed
+ return {};
+ }
+
+ compressed.resize(compressed_size);
+
+ return compressed;
+}
+
+std::vector<u8> CompressDataLZ4HCMax(const u8* source, std::size_t source_size) {
+ return CompressDataLZ4HC(source, source_size, LZ4HC_CLEVEL_MAX);
+}
+
+std::vector<u8> DecompressDataLZ4(const std::vector<u8>& compressed,
+ std::size_t uncompressed_size) {
+ std::vector<u8> uncompressed(uncompressed_size);
+ const int size_check = LZ4_decompress_safe(reinterpret_cast<const char*>(compressed.data()),
+ reinterpret_cast<char*>(uncompressed.data()),
+ static_cast<int>(compressed.size()),
+ static_cast<int>(uncompressed.size()));
+ if (static_cast<int>(uncompressed_size) != size_check) {
+ // Decompression failed
+ return {};
+ }
+ return uncompressed;
+}
+
+} // namespace Common::Compression
diff --git a/src/common/lz4_compression.h b/src/common/lz4_compression.h
new file mode 100644
index 000000000..fe2231a6c
--- /dev/null
+++ b/src/common/lz4_compression.h
@@ -0,0 +1,55 @@
+// Copyright 2019 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <vector>
+
+#include "common/common_types.h"
+
+namespace Common::Compression {
+
+/**
+ * Compresses a source memory region with LZ4 and returns the compressed data in a vector.
+ *
+ * @param source the uncompressed source memory region.
+ * @param source_size the size in bytes of the uncompressed source memory region.
+ *
+ * @return the compressed data.
+ */
+std::vector<u8> CompressDataLZ4(const u8* source, std::size_t source_size);
+
+/**
+ * Utilizes the LZ4 subalgorithm LZ4HC with the specified compression level. Higher compression
+ * levels result in a smaller compressed size, but require more CPU time for compression. The
+ * compression level has almost no impact on decompression speed. Data compressed with LZ4HC can
+ * also be decompressed with the default LZ4 decompression.
+ *
+ * @param source the uncompressed source memory region.
+ * @param source_size the size in bytes of the uncompressed source memory region.
+ * @param compression_level the used compression level. Should be between 3 and 12.
+ *
+ * @return the compressed data.
+ */
+std::vector<u8> CompressDataLZ4HC(const u8* source, std::size_t source_size, s32 compression_level);
+
+/**
+ * Utilizes the LZ4 subalgorithm LZ4HC with the highest possible compression level.
+ *
+ * @param source the uncompressed source memory region.
+ * @param source_size the size in bytes of the uncompressed source memory region.
+ *
+ * @return the compressed data.
+ */
+std::vector<u8> CompressDataLZ4HCMax(const u8* source, std::size_t source_size);
+
+/**
+ * Decompresses a source memory region with LZ4 and returns the uncompressed data in a vector.
+ *
+ * @param compressed the compressed source memory region.
+ * @param uncompressed_size the size in bytes of the uncompressed data.
+ *
+ * @return the decompressed data.
+ */
+std::vector<u8> DecompressDataLZ4(const std::vector<u8>& compressed, std::size_t uncompressed_size);
+
+} // namespace Common::Compression \ No newline at end of file
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 9e23afe85..c59107102 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -458,7 +458,7 @@ add_library(core STATIC
create_target_directory_groups(core)
target_link_libraries(core PUBLIC common PRIVATE audio_core video_core)
-target_link_libraries(core PUBLIC Boost::boost PRIVATE fmt lz4_static mbedtls opus unicorn open_source_archives)
+target_link_libraries(core PUBLIC Boost::boost PRIVATE fmt mbedtls opus unicorn open_source_archives)
if (ENABLE_WEB_SERVICE)
target_compile_definitions(core PRIVATE -DENABLE_WEB_SERVICE)
target_link_libraries(core PRIVATE web_service)
diff --git a/src/core/hle/kernel/object.cpp b/src/core/hle/kernel/object.cpp
index 217144efc..10431e94c 100644
--- a/src/core/hle/kernel/object.cpp
+++ b/src/core/hle/kernel/object.cpp
@@ -24,7 +24,6 @@ bool Object::IsWaitable() const {
case HandleType::WritableEvent:
case HandleType::SharedMemory:
case HandleType::TransferMemory:
- case HandleType::AddressArbiter:
case HandleType::ResourceLimit:
case HandleType::ClientPort:
case HandleType::ClientSession:
diff --git a/src/core/hle/kernel/object.h b/src/core/hle/kernel/object.h
index 3f6baa094..332876c27 100644
--- a/src/core/hle/kernel/object.h
+++ b/src/core/hle/kernel/object.h
@@ -25,7 +25,6 @@ enum class HandleType : u32 {
TransferMemory,
Thread,
Process,
- AddressArbiter,
ResourceLimit,
ClientPort,
ServerPort,
diff --git a/src/core/hle/kernel/transfer_memory.cpp b/src/core/hle/kernel/transfer_memory.cpp
index 23228e1b5..26c4e5e67 100644
--- a/src/core/hle/kernel/transfer_memory.cpp
+++ b/src/core/hle/kernel/transfer_memory.cpp
@@ -14,8 +14,8 @@ namespace Kernel {
TransferMemory::TransferMemory(KernelCore& kernel) : Object{kernel} {}
TransferMemory::~TransferMemory() = default;
-SharedPtr<TransferMemory> TransferMemory::Create(KernelCore& kernel, VAddr base_address,
- size_t size, MemoryPermission permissions) {
+SharedPtr<TransferMemory> TransferMemory::Create(KernelCore& kernel, VAddr base_address, u64 size,
+ MemoryPermission permissions) {
SharedPtr<TransferMemory> transfer_memory{new TransferMemory(kernel)};
transfer_memory->base_address = base_address;
@@ -26,7 +26,15 @@ SharedPtr<TransferMemory> TransferMemory::Create(KernelCore& kernel, VAddr base_
return transfer_memory;
}
-ResultCode TransferMemory::MapMemory(VAddr address, size_t size, MemoryPermission permissions) {
+const u8* TransferMemory::GetPointer() const {
+ return backing_block.get()->data();
+}
+
+u64 TransferMemory::GetSize() const {
+ return memory_size;
+}
+
+ResultCode TransferMemory::MapMemory(VAddr address, u64 size, MemoryPermission permissions) {
if (memory_size != size) {
return ERR_INVALID_SIZE;
}
@@ -39,13 +47,13 @@ ResultCode TransferMemory::MapMemory(VAddr address, size_t size, MemoryPermissio
return ERR_INVALID_STATE;
}
+ backing_block = std::make_shared<std::vector<u8>>(size);
+
const auto map_state = owner_permissions == MemoryPermission::None
? MemoryState::TransferMemoryIsolated
: MemoryState::TransferMemory;
auto& vm_manager = owner_process->VMManager();
- const auto map_result = vm_manager.MapMemoryBlock(
- address, std::make_shared<std::vector<u8>>(size), 0, size, map_state);
-
+ const auto map_result = vm_manager.MapMemoryBlock(address, backing_block, 0, size, map_state);
if (map_result.Failed()) {
return map_result.Code();
}
@@ -54,7 +62,7 @@ ResultCode TransferMemory::MapMemory(VAddr address, size_t size, MemoryPermissio
return RESULT_SUCCESS;
}
-ResultCode TransferMemory::UnmapMemory(VAddr address, size_t size) {
+ResultCode TransferMemory::UnmapMemory(VAddr address, u64 size) {
if (memory_size != size) {
return ERR_INVALID_SIZE;
}
diff --git a/src/core/hle/kernel/transfer_memory.h b/src/core/hle/kernel/transfer_memory.h
index ec294951e..a140b1e2b 100644
--- a/src/core/hle/kernel/transfer_memory.h
+++ b/src/core/hle/kernel/transfer_memory.h
@@ -4,6 +4,9 @@
#pragma once
+#include <memory>
+#include <vector>
+
#include "core/hle/kernel/object.h"
union ResultCode;
@@ -25,7 +28,7 @@ class TransferMemory final : public Object {
public:
static constexpr HandleType HANDLE_TYPE = HandleType::TransferMemory;
- static SharedPtr<TransferMemory> Create(KernelCore& kernel, VAddr base_address, size_t size,
+ static SharedPtr<TransferMemory> Create(KernelCore& kernel, VAddr base_address, u64 size,
MemoryPermission permissions);
TransferMemory(const TransferMemory&) = delete;
@@ -46,6 +49,12 @@ public:
return HANDLE_TYPE;
}
+ /// Gets a pointer to the backing block of this instance.
+ const u8* GetPointer() const;
+
+ /// Gets the size of the memory backing this instance in bytes.
+ u64 GetSize() const;
+
/// Attempts to map transfer memory with the given range and memory permissions.
///
/// @param address The base address to being mapping memory at.
@@ -56,7 +65,7 @@ public:
/// the same values that were given when creating the transfer memory
/// instance.
///
- ResultCode MapMemory(VAddr address, size_t size, MemoryPermission permissions);
+ ResultCode MapMemory(VAddr address, u64 size, MemoryPermission permissions);
/// Unmaps the transfer memory with the given range
///
@@ -66,17 +75,20 @@ public:
/// @pre The given address and size must be the same as the ones used
/// to create the transfer memory instance.
///
- ResultCode UnmapMemory(VAddr address, size_t size);
+ ResultCode UnmapMemory(VAddr address, u64 size);
private:
explicit TransferMemory(KernelCore& kernel);
~TransferMemory() override;
+ /// Memory block backing this instance.
+ std::shared_ptr<std::vector<u8>> backing_block;
+
/// The base address for the memory managed by this instance.
VAddr base_address = 0;
/// Size of the memory, in bytes, that this instance manages.
- size_t memory_size = 0;
+ u64 memory_size = 0;
/// The memory permissions that are applied to this instance.
MemoryPermission owner_permissions{};
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index d31ab7970..a13433bcf 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -13,7 +13,7 @@
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/readable_event.h"
-#include "core/hle/kernel/shared_memory.h"
+#include "core/hle/kernel/transfer_memory.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/service/acc/profile_manager.h"
#include "core/hle/service/am/am.h"
@@ -931,19 +931,19 @@ void ILibraryAppletCreator::CreateTransferMemoryStorage(Kernel::HLERequestContex
rp.SetCurrentOffset(3);
const auto handle{rp.Pop<Kernel::Handle>()};
- const auto shared_mem =
- Core::System::GetInstance().CurrentProcess()->GetHandleTable().Get<Kernel::SharedMemory>(
+ const auto transfer_mem =
+ Core::System::GetInstance().CurrentProcess()->GetHandleTable().Get<Kernel::TransferMemory>(
handle);
- if (shared_mem == nullptr) {
+ if (transfer_mem == nullptr) {
LOG_ERROR(Service_AM, "shared_mem is a nullpr for handle={:08X}", handle);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultCode(-1));
return;
}
- const u8* mem_begin = shared_mem->GetPointer();
- const u8* mem_end = mem_begin + shared_mem->GetSize();
+ const u8* const mem_begin = transfer_mem->GetPointer();
+ const u8* const mem_end = mem_begin + transfer_mem->GetSize();
std::vector<u8> memory{mem_begin, mem_end};
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp
index babc7e646..ffe2eea8a 100644
--- a/src/core/loader/nso.cpp
+++ b/src/core/loader/nso.cpp
@@ -4,11 +4,12 @@
#include <cinttypes>
#include <vector>
-#include <lz4.h>
+
#include "common/common_funcs.h"
#include "common/file_util.h"
#include "common/hex_util.h"
#include "common/logging/log.h"
+#include "common/lz4_compression.h"
#include "common/swap.h"
#include "core/core.h"
#include "core/file_sys/patch_manager.h"
@@ -35,15 +36,11 @@ static_assert(sizeof(MODHeader) == 0x1c, "MODHeader has incorrect size.");
std::vector<u8> DecompressSegment(const std::vector<u8>& compressed_data,
const NSOSegmentHeader& header) {
- std::vector<u8> uncompressed_data(header.size);
- const int bytes_uncompressed =
- LZ4_decompress_safe(reinterpret_cast<const char*>(compressed_data.data()),
- reinterpret_cast<char*>(uncompressed_data.data()),
- static_cast<int>(compressed_data.size()), header.size);
-
- ASSERT_MSG(bytes_uncompressed == static_cast<int>(header.size) &&
- bytes_uncompressed == static_cast<int>(uncompressed_data.size()),
- "{} != {} != {}", bytes_uncompressed, header.size, uncompressed_data.size());
+ const std::vector<u8> uncompressed_data =
+ Common::Compression::DecompressDataLZ4(compressed_data, header.size);
+
+ ASSERT_MSG(uncompressed_data.size() == static_cast<int>(header.size), "{} != {}", header.size,
+ uncompressed_data.size());
return uncompressed_data;
}
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt
index 44c761d3e..242a0d1cd 100644
--- a/src/video_core/CMakeLists.txt
+++ b/src/video_core/CMakeLists.txt
@@ -139,4 +139,4 @@ endif()
create_target_directory_groups(video_core)
target_link_libraries(video_core PUBLIC common core)
-target_link_libraries(video_core PRIVATE glad lz4_static)
+target_link_libraries(video_core PRIVATE glad)
diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.cpp b/src/video_core/renderer_opengl/gl_buffer_cache.cpp
index fd091c84c..7989ec11b 100644
--- a/src/video_core/renderer_opengl/gl_buffer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_buffer_cache.cpp
@@ -7,7 +7,6 @@
#include "common/alignment.h"
#include "core/core.h"
-#include "core/memory.h"
#include "video_core/renderer_opengl/gl_buffer_cache.h"
#include "video_core/renderer_opengl/gl_rasterizer.h"
diff --git a/src/video_core/renderer_opengl/gl_global_cache.cpp b/src/video_core/renderer_opengl/gl_global_cache.cpp
index da9326253..5842d6213 100644
--- a/src/video_core/renderer_opengl/gl_global_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_global_cache.cpp
@@ -4,7 +4,6 @@
#include <glad/glad.h>
-#include "common/assert.h"
#include "common/logging/log.h"
#include "core/core.h"
#include "video_core/renderer_opengl/gl_global_cache.h"
diff --git a/src/video_core/renderer_opengl/gl_primitive_assembler.cpp b/src/video_core/renderer_opengl/gl_primitive_assembler.cpp
index 2bcbd3da2..c3e94d917 100644
--- a/src/video_core/renderer_opengl/gl_primitive_assembler.cpp
+++ b/src/video_core/renderer_opengl/gl_primitive_assembler.cpp
@@ -7,7 +7,7 @@
#include "common/assert.h"
#include "common/common_types.h"
#include "core/core.h"
-#include "core/memory.h"
+#include "video_core/memory_manager.h"
#include "video_core/renderer_opengl/gl_buffer_cache.h"
#include "video_core/renderer_opengl/gl_primitive_assembler.h"
diff --git a/src/video_core/renderer_opengl/gl_primitive_assembler.h b/src/video_core/renderer_opengl/gl_primitive_assembler.h
index 0e2e7dc36..4e87ce4d6 100644
--- a/src/video_core/renderer_opengl/gl_primitive_assembler.h
+++ b/src/video_core/renderer_opengl/gl_primitive_assembler.h
@@ -4,11 +4,9 @@
#pragma once
-#include <vector>
#include <glad/glad.h>
#include "common/common_types.h"
-#include "video_core/memory_manager.h"
namespace OpenGL {
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 046fc935b..7ff1e6737 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -17,7 +17,6 @@
#include "common/microprofile.h"
#include "common/scope_exit.h"
#include "core/core.h"
-#include "core/frontend/emu_window.h"
#include "core/hle/kernel/process.h"
#include "core/settings.h"
#include "video_core/engines/maxwell_3d.h"
@@ -26,7 +25,6 @@
#include "video_core/renderer_opengl/gl_shader_gen.h"
#include "video_core/renderer_opengl/maxwell_to_gl.h"
#include "video_core/renderer_opengl/renderer_opengl.h"
-#include "video_core/video_core.h"
namespace OpenGL {
@@ -318,7 +316,7 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) {
const std::size_t stage{index == 0 ? 0 : index - 1}; // Stage indices are 0 - 5
GLShader::MaxwellUniformData ubo{};
- ubo.SetFromRegs(gpu.state.shader_stages[stage]);
+ ubo.SetFromRegs(gpu, stage);
const GLintptr offset = buffer_cache.UploadHostMemory(
&ubo, sizeof(ubo), static_cast<std::size_t>(uniform_buffer_alignment));
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index 4de565321..54fbf48aa 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -12,15 +12,12 @@
#include <optional>
#include <tuple>
#include <utility>
-#include <vector>
#include <boost/icl/interval_map.hpp>
-#include <boost/range/iterator_range.hpp>
#include <glad/glad.h>
#include "common/common_types.h"
#include "video_core/engines/maxwell_3d.h"
-#include "video_core/memory_manager.h"
#include "video_core/rasterizer_cache.h"
#include "video_core/rasterizer_interface.h"
#include "video_core/renderer_opengl/gl_buffer_cache.h"
@@ -29,10 +26,8 @@
#include "video_core/renderer_opengl/gl_rasterizer_cache.h"
#include "video_core/renderer_opengl/gl_resource_manager.h"
#include "video_core/renderer_opengl/gl_shader_cache.h"
-#include "video_core/renderer_opengl/gl_shader_gen.h"
#include "video_core/renderer_opengl/gl_shader_manager.h"
#include "video_core/renderer_opengl/gl_state.h"
-#include "video_core/renderer_opengl/gl_stream_buffer.h"
namespace Core {
class System;
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
index aba6ce731..7a3280620 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
@@ -13,7 +13,6 @@
#include "common/scope_exit.h"
#include "core/core.h"
#include "core/hle/kernel/process.h"
-#include "core/memory.h"
#include "core/settings.h"
#include "video_core/engines/maxwell_3d.h"
#include "video_core/morton.h"
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
index e8073579f..ad4fd3ad2 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
@@ -5,10 +5,9 @@
#pragma once
#include <array>
-#include <map>
#include <memory>
#include <string>
-#include <unordered_set>
+#include <tuple>
#include <vector>
#include "common/alignment.h"
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp
index 290e654bc..7030db365 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp
@@ -6,13 +6,11 @@
#include "common/assert.h"
#include "common/hash.h"
#include "core/core.h"
-#include "core/memory.h"
#include "video_core/engines/maxwell_3d.h"
#include "video_core/renderer_opengl/gl_rasterizer.h"
#include "video_core/renderer_opengl/gl_shader_cache.h"
#include "video_core/renderer_opengl/gl_shader_decompiler.h"
#include "video_core/renderer_opengl/gl_shader_disk_cache.h"
-#include "video_core/renderer_opengl/gl_shader_manager.h"
#include "video_core/renderer_opengl/utils.h"
#include "video_core/shader/shader_ir.h"
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.h b/src/video_core/renderer_opengl/gl_shader_cache.h
index fd1c85115..0cf8e0b3d 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.h
+++ b/src/video_core/renderer_opengl/gl_shader_cache.h
@@ -5,21 +5,20 @@
#pragma once
#include <array>
+#include <atomic>
#include <memory>
#include <set>
#include <tuple>
#include <unordered_map>
+#include <vector>
#include <glad/glad.h>
-#include "common/assert.h"
#include "common/common_types.h"
#include "video_core/rasterizer_cache.h"
-#include "video_core/renderer_base.h"
#include "video_core/renderer_opengl/gl_resource_manager.h"
#include "video_core/renderer_opengl/gl_shader_decompiler.h"
#include "video_core/renderer_opengl/gl_shader_disk_cache.h"
-#include "video_core/renderer_opengl/gl_shader_gen.h"
namespace Core {
class System;
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.h b/src/video_core/renderer_opengl/gl_shader_decompiler.h
index 72aca4938..4e04ab2f8 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.h
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.h
@@ -5,7 +5,6 @@
#pragma once
#include <array>
-#include <set>
#include <string>
#include <utility>
#include <vector>
diff --git a/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp b/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp
index 82fc4d44b..d2d979997 100644
--- a/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp
@@ -4,13 +4,13 @@
#include <cstring>
#include <fmt/format.h>
-#include <lz4.h>
#include "common/assert.h"
#include "common/common_paths.h"
#include "common/common_types.h"
#include "common/file_util.h"
#include "common/logging/log.h"
+#include "common/lz4_compression.h"
#include "common/scm_rev.h"
#include "core/core.h"
@@ -49,39 +49,6 @@ ShaderCacheVersionHash GetShaderCacheVersionHash() {
return hash;
}
-template <typename T>
-std::vector<u8> CompressData(const T* source, std::size_t source_size) {
- if (source_size > LZ4_MAX_INPUT_SIZE) {
- // Source size exceeds LZ4 maximum input size
- return {};
- }
- const auto source_size_int = static_cast<int>(source_size);
- const int max_compressed_size = LZ4_compressBound(source_size_int);
- std::vector<u8> compressed(max_compressed_size);
- const int compressed_size = LZ4_compress_default(reinterpret_cast<const char*>(source),
- reinterpret_cast<char*>(compressed.data()),
- source_size_int, max_compressed_size);
- if (compressed_size <= 0) {
- // Compression failed
- return {};
- }
- compressed.resize(compressed_size);
- return compressed;
-}
-
-std::vector<u8> DecompressData(const std::vector<u8>& compressed, std::size_t uncompressed_size) {
- std::vector<u8> uncompressed(uncompressed_size);
- const int size_check = LZ4_decompress_safe(reinterpret_cast<const char*>(compressed.data()),
- reinterpret_cast<char*>(uncompressed.data()),
- static_cast<int>(compressed.size()),
- static_cast<int>(uncompressed.size()));
- if (static_cast<int>(uncompressed_size) != size_check) {
- // Decompression failed
- return {};
- }
- return uncompressed;
-}
-
} // namespace
ShaderDiskCacheRaw::ShaderDiskCacheRaw(u64 unique_identifier, Maxwell::ShaderProgram program_type,
@@ -292,7 +259,7 @@ ShaderDiskCacheOpenGL::LoadPrecompiledFile(FileUtil::IOFile& file) {
return {};
}
- dump.binary = DecompressData(compressed_binary, binary_length);
+ dump.binary = Common::Compression::DecompressDataLZ4(compressed_binary, binary_length);
if (dump.binary.empty()) {
return {};
}
@@ -321,7 +288,7 @@ std::optional<ShaderDiskCacheDecompiled> ShaderDiskCacheOpenGL::LoadDecompiledEn
return {};
}
- const std::vector<u8> code = DecompressData(compressed_code, code_size);
+ const std::vector<u8> code = Common::Compression::DecompressDataLZ4(compressed_code, code_size);
if (code.empty()) {
return {};
}
@@ -507,7 +474,8 @@ void ShaderDiskCacheOpenGL::SaveDecompiled(u64 unique_identifier, const std::str
if (!IsUsable())
return;
- const std::vector<u8> compressed_code{CompressData(code.data(), code.size())};
+ const std::vector<u8> compressed_code{Common::Compression::CompressDataLZ4HC(
+ reinterpret_cast<const u8*>(code.data()), code.size(), 9)};
if (compressed_code.empty()) {
LOG_ERROR(Render_OpenGL, "Failed to compress GLSL code - skipping shader {:016x}",
unique_identifier);
@@ -537,7 +505,9 @@ void ShaderDiskCacheOpenGL::SaveDump(const ShaderDiskCacheUsage& usage, GLuint p
std::vector<u8> binary(binary_length);
glGetProgramBinary(program, binary_length, nullptr, &binary_format, binary.data());
- const std::vector<u8> compressed_binary = CompressData(binary.data(), binary.size());
+ const std::vector<u8> compressed_binary =
+ Common::Compression::CompressDataLZ4HC(binary.data(), binary.size(), 9);
+
if (compressed_binary.empty()) {
LOG_ERROR(Render_OpenGL, "Failed to compress binary program in shader={:016x}",
usage.unique_identifier);
diff --git a/src/video_core/renderer_opengl/gl_shader_gen.cpp b/src/video_core/renderer_opengl/gl_shader_gen.cpp
index 7d96649af..8763d9c71 100644
--- a/src/video_core/renderer_opengl/gl_shader_gen.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_gen.cpp
@@ -3,7 +3,6 @@
// Refer to the license.txt file included.
#include <fmt/format.h>
-#include "common/assert.h"
#include "video_core/engines/maxwell_3d.h"
#include "video_core/renderer_opengl/gl_shader_decompiler.h"
#include "video_core/renderer_opengl/gl_shader_gen.h"
diff --git a/src/video_core/renderer_opengl/gl_shader_gen.h b/src/video_core/renderer_opengl/gl_shader_gen.h
index fba8e681b..fad346b48 100644
--- a/src/video_core/renderer_opengl/gl_shader_gen.h
+++ b/src/video_core/renderer_opengl/gl_shader_gen.h
@@ -4,12 +4,9 @@
#pragma once
-#include <array>
-#include <string>
#include <vector>
#include "common/common_types.h"
-#include "video_core/engines/shader_bytecode.h"
#include "video_core/renderer_opengl/gl_shader_decompiler.h"
#include "video_core/shader/shader_ir.h"
diff --git a/src/video_core/renderer_opengl/gl_shader_manager.cpp b/src/video_core/renderer_opengl/gl_shader_manager.cpp
index 6a30c28d2..eaf3e03a0 100644
--- a/src/video_core/renderer_opengl/gl_shader_manager.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_manager.cpp
@@ -2,15 +2,15 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include "core/core.h"
#include "video_core/renderer_opengl/gl_shader_manager.h"
namespace OpenGL::GLShader {
-void MaxwellUniformData::SetFromRegs(const Maxwell3D::State::ShaderStageInfo& shader_stage) {
- const auto& gpu = Core::System::GetInstance().GPU().Maxwell3D();
- const auto& regs = gpu.regs;
- const auto& state = gpu.state;
+using Tegra::Engines::Maxwell3D;
+
+void MaxwellUniformData::SetFromRegs(const Maxwell3D& maxwell, std::size_t shader_stage) {
+ const auto& regs = maxwell.regs;
+ const auto& state = maxwell.state;
// TODO(bunnei): Support more than one viewport
viewport_flip[0] = regs.viewport_transform[0].scale_x < 0.0 ? -1.0f : 1.0f;
@@ -18,7 +18,7 @@ void MaxwellUniformData::SetFromRegs(const Maxwell3D::State::ShaderStageInfo& sh
u32 func = static_cast<u32>(regs.alpha_test_func);
// Normalize the gl variants of opCompare to be the same as the normal variants
- u32 op_gl_variant_base = static_cast<u32>(Tegra::Engines::Maxwell3D::Regs::ComparisonOp::Never);
+ const u32 op_gl_variant_base = static_cast<u32>(Maxwell3D::Regs::ComparisonOp::Never);
if (func >= op_gl_variant_base) {
func = func - op_gl_variant_base + 1U;
}
@@ -31,8 +31,9 @@ void MaxwellUniformData::SetFromRegs(const Maxwell3D::State::ShaderStageInfo& sh
// Assign in which stage the position has to be flipped
// (the last stage before the fragment shader).
- if (gpu.regs.shader_config[static_cast<u32>(Maxwell3D::Regs::ShaderProgram::Geometry)].enable) {
- flip_stage = static_cast<u32>(Maxwell3D::Regs::ShaderProgram::Geometry);
+ constexpr u32 geometry_index = static_cast<u32>(Maxwell3D::Regs::ShaderProgram::Geometry);
+ if (maxwell.regs.shader_config[geometry_index].enable) {
+ flip_stage = geometry_index;
} else {
flip_stage = static_cast<u32>(Maxwell3D::Regs::ShaderProgram::VertexB);
}
diff --git a/src/video_core/renderer_opengl/gl_shader_manager.h b/src/video_core/renderer_opengl/gl_shader_manager.h
index 4970aafed..8eef2a920 100644
--- a/src/video_core/renderer_opengl/gl_shader_manager.h
+++ b/src/video_core/renderer_opengl/gl_shader_manager.h
@@ -12,14 +12,13 @@
namespace OpenGL::GLShader {
-using Tegra::Engines::Maxwell3D;
-
/// Uniform structure for the Uniform Buffer Object, all vectors must be 16-byte aligned
-// NOTE: Always keep a vec4 at the end. The GL spec is not clear whether the alignment at
-// the end of a uniform block is included in UNIFORM_BLOCK_DATA_SIZE or not.
-// Not following that rule will cause problems on some AMD drivers.
+/// @note Always keep a vec4 at the end. The GL spec is not clear whether the alignment at
+/// the end of a uniform block is included in UNIFORM_BLOCK_DATA_SIZE or not.
+/// Not following that rule will cause problems on some AMD drivers.
struct MaxwellUniformData {
- void SetFromRegs(const Maxwell3D::State::ShaderStageInfo& shader_stage);
+ void SetFromRegs(const Tegra::Engines::Maxwell3D& maxwell, std::size_t shader_stage);
+
alignas(16) GLvec4 viewport_flip;
struct alignas(16) {
GLuint instance_id;
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index a01efeb05..d69cba9c3 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -5,7 +5,6 @@
#include <algorithm>
#include <cstddef>
#include <cstdlib>
-#include <cstring>
#include <memory>
#include <glad/glad.h>
#include "common/assert.h"
diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp
index c0e3c5fa9..4422a572b 100644
--- a/src/yuzu/game_list.cpp
+++ b/src/yuzu/game_list.cpp
@@ -329,6 +329,8 @@ void GameList::PopupContextMenu(const QPoint& menu_location) {
QMenu context_menu;
QAction* open_save_location = context_menu.addAction(tr("Open Save Data Location"));
QAction* open_lfs_location = context_menu.addAction(tr("Open Mod Data Location"));
+ QAction* open_transferable_shader_cache =
+ context_menu.addAction(tr("Open Transferable Shader Cache"));
context_menu.addSeparator();
QAction* dump_romfs = context_menu.addAction(tr("Dump RomFS"));
QAction* copy_tid = context_menu.addAction(tr("Copy Title ID to Clipboard"));
@@ -344,6 +346,8 @@ void GameList::PopupContextMenu(const QPoint& menu_location) {
[&]() { emit OpenFolderRequested(program_id, GameListOpenTarget::SaveData); });
connect(open_lfs_location, &QAction::triggered,
[&]() { emit OpenFolderRequested(program_id, GameListOpenTarget::ModData); });
+ connect(open_transferable_shader_cache, &QAction::triggered,
+ [&]() { emit OpenTransferableShaderCacheRequested(program_id); });
connect(dump_romfs, &QAction::triggered, [&]() { emit DumpRomFSRequested(program_id, path); });
connect(copy_tid, &QAction::triggered, [&]() { emit CopyTIDRequested(program_id); });
connect(navigate_to_gamedb_entry, &QAction::triggered,
diff --git a/src/yuzu/game_list.h b/src/yuzu/game_list.h
index b317eb2fc..8ea5cbaaa 100644
--- a/src/yuzu/game_list.h
+++ b/src/yuzu/game_list.h
@@ -66,6 +66,7 @@ signals:
void GameChosen(QString game_path);
void ShouldCancelWorker();
void OpenFolderRequested(u64 program_id, GameListOpenTarget target);
+ void OpenTransferableShaderCacheRequested(u64 program_id);
void DumpRomFSRequested(u64 program_id, const std::string& game_path);
void CopyTIDRequested(u64 program_id);
void NavigateToGamedbEntryRequested(u64 program_id,
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 41ba3c4c6..2b9db69a3 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -37,14 +37,20 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual
#include <glad/glad.h>
#define QT_NO_OPENGL
+#include <QClipboard>
+#include <QDesktopServices>
#include <QDesktopWidget>
#include <QDialogButtonBox>
#include <QFile>
#include <QFileDialog>
+#include <QInputDialog>
#include <QMessageBox>
+#include <QProgressBar>
+#include <QProgressDialog>
+#include <QShortcut>
+#include <QStatusBar>
#include <QtConcurrent/QtConcurrent>
-#include <QtGui>
-#include <QtWidgets>
+
#include <fmt/format.h>
#include "common/common_paths.h"
#include "common/detached_tasks.h"
@@ -55,11 +61,9 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual
#include "common/microprofile.h"
#include "common/scm_rev.h"
#include "common/scope_exit.h"
-#include "common/string_util.h"
#include "common/telemetry.h"
#include "core/core.h"
#include "core/crypto/key_manager.h"
-#include "core/file_sys/bis_factory.h"
#include "core/file_sys/card_image.h"
#include "core/file_sys/content_archive.h"
#include "core/file_sys/control_metadata.h"
@@ -71,7 +75,6 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual
#include "core/frontend/applets/software_keyboard.h"
#include "core/hle/kernel/process.h"
#include "core/hle/service/filesystem/filesystem.h"
-#include "core/hle/service/filesystem/fsp_ldr.h"
#include "core/hle/service/nfp/nfp.h"
#include "core/hle/service/sm/sm.h"
#include "core/loader/loader.h"
@@ -648,6 +651,8 @@ void GMainWindow::RestoreUIState() {
void GMainWindow::ConnectWidgetEvents() {
connect(game_list, &GameList::GameChosen, this, &GMainWindow::OnGameListLoadFile);
connect(game_list, &GameList::OpenFolderRequested, this, &GMainWindow::OnGameListOpenFolder);
+ connect(game_list, &GameList::OpenTransferableShaderCacheRequested, this,
+ &GMainWindow::OnTransferableShaderCacheOpenFile);
connect(game_list, &GameList::DumpRomFSRequested, this, &GMainWindow::OnGameListDumpRomFS);
connect(game_list, &GameList::CopyTIDRequested, this, &GMainWindow::OnGameListCopyTID);
connect(game_list, &GameList::NavigateToGamedbEntryRequested, this,
@@ -1082,6 +1087,39 @@ void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target
QDesktopServices::openUrl(QUrl::fromLocalFile(qpath));
}
+void GMainWindow::OnTransferableShaderCacheOpenFile(u64 program_id) {
+ ASSERT(program_id != 0);
+
+ const QString tranferable_shader_cache_folder_path =
+ QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::ShaderDir)) + "opengl" +
+ DIR_SEP + "transferable";
+
+ const QString transferable_shader_cache_file_path =
+ tranferable_shader_cache_folder_path + DIR_SEP +
+ QString::fromStdString(fmt::format("{:016X}.bin", program_id));
+
+ if (!QFile::exists(transferable_shader_cache_file_path)) {
+ QMessageBox::warning(this, tr("Error Opening Transferable Shader Cache"),
+ tr("A shader cache for this title does not exist."));
+ return;
+ }
+
+ // Windows supports opening a folder with selecting a specified file in explorer. On every other
+ // OS we just open the transferable shader cache folder without preselecting the transferable
+ // shader cache file for the selected game.
+#if defined(Q_OS_WIN)
+ const QString explorer = QStringLiteral("explorer");
+ QStringList param;
+ if (!QFileInfo(transferable_shader_cache_file_path).isDir()) {
+ param << QStringLiteral("/select,");
+ }
+ param << QDir::toNativeSeparators(transferable_shader_cache_file_path);
+ QProcess::startDetached(explorer, param);
+#else
+ QDesktopServices::openUrl(QUrl::fromLocalFile(tranferable_shader_cache_folder_path));
+#endif
+}
+
static std::size_t CalculateRomFSEntrySize(const FileSys::VirtualDir& dir, bool full) {
std::size_t out = 0;
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index e07c892cf..7f3aa998e 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -176,6 +176,7 @@ private slots:
/// Called whenever a user selects a game in the game list widget.
void OnGameListLoadFile(QString game_path);
void OnGameListOpenFolder(u64 program_id, GameListOpenTarget target);
+ void OnTransferableShaderCacheOpenFile(u64 program_id);
void OnGameListDumpRomFS(u64 program_id, const std::string& game_path);
void OnGameListCopyTID(u64 program_id);
void OnGameListNavigateToGamedbEntry(u64 program_id,