summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt3
-rw-r--r--src/core/hle/kernel/errors.h8
-rw-r--r--src/core/hle/kernel/svc.cpp14
-rw-r--r--src/core/hle/kernel/svc_wrap.h4
-rw-r--r--src/core/hle/kernel/thread.cpp4
-rw-r--r--src/core/hle/service/audio/audio.cpp1
-rw-r--r--src/core/hle/service/audio/audio.h4
-rw-r--r--src/core/hle/service/audio/audout_u.cpp17
-rw-r--r--src/core/hle/service/audio/audout_u.h17
-rw-r--r--src/core/hle/service/audio/audren_u.cpp6
-rw-r--r--src/core/hle/service/audio/audren_u.h1
-rw-r--r--src/core/hle/service/audio/hwopus.cpp5
-rw-r--r--src/core/hle/service/prepo/prepo.cpp63
-rw-r--r--src/core/hle/service/prepo/prepo.h16
-rw-r--r--src/video_core/engines/shader_bytecode.h64
-rw-r--r--src/video_core/renderer_base.cpp1
-rw-r--r--src/video_core/renderer_base.h1
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.cpp41
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.h8
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp91
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp6
-rw-r--r--src/yuzu/configuration/configure_graphics.cpp16
-rw-r--r--src/yuzu/configuration/configure_graphics.h1
-rw-r--r--src/yuzu/configuration/configure_graphics.ui21
-rw-r--r--src/yuzu/game_list.cpp8
-rw-r--r--src/yuzu/main.cpp2
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl2.cpp2
27 files changed, 324 insertions, 101 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0f32ecfba..500d099fc 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -431,6 +431,9 @@ enable_testing()
add_subdirectory(externals)
add_subdirectory(src)
+# Set yuzu project as default StartUp Project in Visual Studio
+set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT yuzu)
+
# Installation instructions
# =========================
diff --git a/src/core/hle/kernel/errors.h b/src/core/hle/kernel/errors.h
index 4054d5db6..ad39c8271 100644
--- a/src/core/hle/kernel/errors.h
+++ b/src/core/hle/kernel/errors.h
@@ -21,6 +21,7 @@ enum {
HandleTableFull = 105,
InvalidMemoryState = 106,
InvalidMemoryPermissions = 108,
+ InvalidThreadPriority = 112,
InvalidProcessorId = 113,
InvalidHandle = 114,
InvalidCombination = 116,
@@ -36,7 +37,7 @@ enum {
// WARNING: The kernel is quite inconsistent in it's usage of errors code. Make sure to always
// double check that the code matches before re-using the constant.
-// TODO(bunnei): Replace these with correct errors for Switch OS
+// TODO(bunnei): Replace -1 with correct errors for Switch OS
constexpr ResultCode ERR_HANDLE_TABLE_FULL(ErrorModule::Kernel, ErrCodes::HandleTableFull);
constexpr ResultCode ERR_SESSION_CLOSED_BY_REMOTE(-1);
constexpr ResultCode ERR_PORT_NAME_TOO_LONG(ErrorModule::Kernel, ErrCodes::TooLarge);
@@ -53,15 +54,16 @@ constexpr ResultCode ERR_INVALID_ADDRESS_STATE(ErrorModule::Kernel, ErrCodes::In
constexpr ResultCode ERR_INVALID_MEMORY_PERMISSIONS(ErrorModule::Kernel,
ErrCodes::InvalidMemoryPermissions);
constexpr ResultCode ERR_INVALID_HANDLE(ErrorModule::Kernel, ErrCodes::InvalidHandle);
+constexpr ResultCode ERR_INVALID_PROCESSOR_ID(ErrorModule::Kernel, ErrCodes::InvalidProcessorId);
constexpr ResultCode ERR_INVALID_STATE(ErrorModule::Kernel, ErrCodes::InvalidState);
+constexpr ResultCode ERR_INVALID_THREAD_PRIORITY(ErrorModule::Kernel,
+ ErrCodes::InvalidThreadPriority);
constexpr ResultCode ERR_INVALID_POINTER(-1);
constexpr ResultCode ERR_INVALID_OBJECT_ADDR(-1);
constexpr ResultCode ERR_NOT_AUTHORIZED(-1);
/// Alternate code returned instead of ERR_INVALID_HANDLE in some code paths.
constexpr ResultCode ERR_INVALID_HANDLE_OS(-1);
constexpr ResultCode ERR_NOT_FOUND(-1);
-constexpr ResultCode ERR_OUT_OF_RANGE(-1);
-constexpr ResultCode ERR_OUT_OF_RANGE_KERNEL(-1);
constexpr ResultCode RESULT_TIMEOUT(ErrorModule::Kernel, ErrCodes::Timeout);
/// Returned when Accept() is called on a port with no sessions to be accepted.
constexpr ResultCode ERR_NO_PENDING_SESSIONS(-1);
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 1c9373ed8..f500fd2e7 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -273,7 +273,11 @@ static void Break(u64 reason, u64 info1, u64 info2) {
}
/// Used to output a message on a debug hardware unit - does nothing on a retail unit
-static void OutputDebugString(VAddr address, s32 len) {
+static void OutputDebugString(VAddr address, u64 len) {
+ if (len == 0) {
+ return;
+ }
+
std::string str(len, '\0');
Memory::ReadBlock(address, str.data(), str.size());
LOG_DEBUG(Debug_Emulated, "{}", str);
@@ -378,7 +382,7 @@ static ResultCode GetThreadPriority(u32* priority, Handle handle) {
/// Sets the priority for the specified thread
static ResultCode SetThreadPriority(Handle handle, u32 priority) {
if (priority > THREADPRIO_LOWEST) {
- return ERR_OUT_OF_RANGE;
+ return ERR_INVALID_THREAD_PRIORITY;
}
auto& kernel = Core::System::GetInstance().Kernel();
@@ -523,7 +527,7 @@ static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, V
std::string name = fmt::format("unknown-{:X}", entry_point);
if (priority > THREADPRIO_LOWEST) {
- return ERR_OUT_OF_RANGE;
+ return ERR_INVALID_THREAD_PRIORITY;
}
SharedPtr<ResourceLimit>& resource_limit = Core::CurrentProcess()->resource_limit;
@@ -544,8 +548,8 @@ static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, V
case THREADPROCESSORID_3:
break;
default:
- ASSERT_MSG(false, "Unsupported thread processor ID: {}", processor_id);
- break;
+ LOG_ERROR(Kernel_SVC, "Invalid thread processor ID: {}", processor_id);
+ return ERR_INVALID_PROCESSOR_ID;
}
auto& kernel = Core::System::GetInstance().Kernel();
diff --git a/src/core/hle/kernel/svc_wrap.h b/src/core/hle/kernel/svc_wrap.h
index 79c3fe31b..1eda5f879 100644
--- a/src/core/hle/kernel/svc_wrap.h
+++ b/src/core/hle/kernel/svc_wrap.h
@@ -222,9 +222,9 @@ void SvcWrap() {
func((s64)PARAM(0));
}
-template <void func(u64, s32 len)>
+template <void func(u64, u64 len)>
void SvcWrap() {
- func(PARAM(0), (s32)(PARAM(1) & 0xFFFFFFFF));
+ func(PARAM(0), PARAM(1));
}
template <void func(u64, u64, u64)>
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 3d10d9af2..3f12a84dc 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -227,12 +227,12 @@ ResultVal<SharedPtr<Thread>> Thread::Create(KernelCore& kernel, std::string name
// Check if priority is in ranged. Lowest priority -> highest priority id.
if (priority > THREADPRIO_LOWEST) {
LOG_ERROR(Kernel_SVC, "Invalid thread priority: {}", priority);
- return ERR_OUT_OF_RANGE;
+ return ERR_INVALID_THREAD_PRIORITY;
}
if (processor_id > THREADPROCESSORID_MAX) {
LOG_ERROR(Kernel_SVC, "Invalid processor id: {}", processor_id);
- return ERR_OUT_OF_RANGE_KERNEL;
+ return ERR_INVALID_PROCESSOR_ID;
}
// TODO(yuriks): Other checks, returning 0xD9001BEA
diff --git a/src/core/hle/service/audio/audio.cpp b/src/core/hle/service/audio/audio.cpp
index 6b5e15633..128df7db5 100644
--- a/src/core/hle/service/audio/audio.cpp
+++ b/src/core/hle/service/audio/audio.cpp
@@ -15,6 +15,7 @@
#include "core/hle/service/audio/audren_u.h"
#include "core/hle/service/audio/codecctl.h"
#include "core/hle/service/audio/hwopus.h"
+#include "core/hle/service/service.h"
namespace Service::Audio {
diff --git a/src/core/hle/service/audio/audio.h b/src/core/hle/service/audio/audio.h
index 95e5691f7..f5bd3bf5f 100644
--- a/src/core/hle/service/audio/audio.h
+++ b/src/core/hle/service/audio/audio.h
@@ -4,7 +4,9 @@
#pragma once
-#include "core/hle/service/service.h"
+namespace Service::SM {
+class ServiceManager;
+}
namespace Service::Audio {
diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp
index 05100ca8f..80a002322 100644
--- a/src/core/hle/service/audio/audout_u.cpp
+++ b/src/core/hle/service/audio/audout_u.cpp
@@ -3,15 +3,20 @@
// Refer to the license.txt file included.
#include <array>
+#include <cstring>
#include <vector>
+#include "audio_core/audio_out.h"
#include "audio_core/codec.h"
+#include "common/common_funcs.h"
#include "common/logging/log.h"
+#include "common/swap.h"
#include "core/core.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/event.h"
#include "core/hle/kernel/hle_ipc.h"
#include "core/hle/service/audio/audout_u.h"
+#include "core/memory.h"
namespace Service::Audio {
@@ -25,6 +30,18 @@ enum {
constexpr std::array<char, 10> DefaultDevice{{"DeviceOut"}};
constexpr int DefaultSampleRate{48000};
+struct AudoutParams {
+ s32_le sample_rate;
+ u16_le channel_count;
+ INSERT_PADDING_BYTES(2);
+};
+static_assert(sizeof(AudoutParams) == 0x8, "AudoutParams is an invalid size");
+
+enum class AudioState : u32 {
+ Started,
+ Stopped,
+};
+
class IAudioOut final : public ServiceFramework<IAudioOut> {
public:
IAudioOut(AudoutParams audio_params, AudioCore::AudioOut& audio_core)
diff --git a/src/core/hle/service/audio/audout_u.h b/src/core/hle/service/audio/audout_u.h
index aa52d3855..dcaf64708 100644
--- a/src/core/hle/service/audio/audout_u.h
+++ b/src/core/hle/service/audio/audout_u.h
@@ -4,27 +4,18 @@
#pragma once
-#include "audio_core/audio_out.h"
#include "core/hle/service/service.h"
+namespace AudioCore {
+class AudioOut;
+}
+
namespace Kernel {
class HLERequestContext;
}
namespace Service::Audio {
-struct AudoutParams {
- s32_le sample_rate;
- u16_le channel_count;
- INSERT_PADDING_BYTES(2);
-};
-static_assert(sizeof(AudoutParams) == 0x8, "AudoutParams is an invalid size");
-
-enum class AudioState : u32 {
- Started,
- Stopped,
-};
-
class IAudioOut;
class AudOutU final : public ServiceFramework<AudOutU> {
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp
index 3870bec65..e84c4fa2b 100644
--- a/src/core/hle/service/audio/audren_u.cpp
+++ b/src/core/hle/service/audio/audren_u.cpp
@@ -2,12 +2,14 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include <algorithm>
#include <array>
+#include <memory>
+#include "audio_core/audio_renderer.h"
#include "common/alignment.h"
+#include "common/common_funcs.h"
#include "common/logging/log.h"
-#include "core/core_timing.h"
-#include "core/core_timing_util.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/event.h"
#include "core/hle/kernel/hle_ipc.h"
diff --git a/src/core/hle/service/audio/audren_u.h b/src/core/hle/service/audio/audren_u.h
index 85a995a2f..c6bc3a90a 100644
--- a/src/core/hle/service/audio/audren_u.h
+++ b/src/core/hle/service/audio/audren_u.h
@@ -4,7 +4,6 @@
#pragma once
-#include "audio_core/audio_renderer.h"
#include "core/hle/service/service.h"
namespace Kernel {
diff --git a/src/core/hle/service/audio/hwopus.cpp b/src/core/hle/service/audio/hwopus.cpp
index 341bfda42..668fef145 100644
--- a/src/core/hle/service/audio/hwopus.cpp
+++ b/src/core/hle/service/audio/hwopus.cpp
@@ -3,7 +3,12 @@
// Refer to the license.txt file included.
#include <cstring>
+#include <memory>
+#include <vector>
+
#include <opus.h>
+
+#include "common/common_funcs.h"
#include "common/logging/log.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/hle_ipc.h"
diff --git a/src/core/hle/service/prepo/prepo.cpp b/src/core/hle/service/prepo/prepo.cpp
index 3c43b8d8c..6a9eccfb5 100644
--- a/src/core/hle/service/prepo/prepo.cpp
+++ b/src/core/hle/service/prepo/prepo.cpp
@@ -1,36 +1,47 @@
-#include <cinttypes>
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
#include "common/logging/log.h"
#include "core/hle/ipc_helpers.h"
-#include "core/hle/kernel/event.h"
#include "core/hle/service/prepo/prepo.h"
+#include "core/hle/service/service.h"
namespace Service::PlayReport {
-PlayReport::PlayReport(const char* name) : ServiceFramework(name) {
- static const FunctionInfo functions[] = {
- {10100, nullptr, "SaveReport"},
- {10101, &PlayReport::SaveReportWithUser, "SaveReportWithUser"},
- {10200, nullptr, "RequestImmediateTransmission"},
- {10300, nullptr, "GetTransmissionStatus"},
- {20100, nullptr, "SaveSystemReport"},
- {20200, nullptr, "SetOperationMode"},
- {20101, nullptr, "SaveSystemReportWithUser"},
- {30100, nullptr, "ClearStorage"},
- {40100, nullptr, "IsUserAgreementCheckEnabled"},
- {40101, nullptr, "SetUserAgreementCheckEnabled"},
- {90100, nullptr, "GetStorageUsage"},
- {90200, nullptr, "GetStatistics"},
- {90201, nullptr, "GetThroughputHistory"},
- {90300, nullptr, "GetLastUploadError"},
- };
- RegisterHandlers(functions);
-};
-void PlayReport::SaveReportWithUser(Kernel::HLERequestContext& ctx) {
- // TODO(ogniK): Do we want to add play report?
- LOG_WARNING(Service_PREPO, "(STUBBED) called");
+class PlayReport final : public ServiceFramework<PlayReport> {
+public:
+ explicit PlayReport(const char* name) : ServiceFramework{name} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {10100, nullptr, "SaveReport"},
+ {10101, &PlayReport::SaveReportWithUser, "SaveReportWithUser"},
+ {10200, nullptr, "RequestImmediateTransmission"},
+ {10300, nullptr, "GetTransmissionStatus"},
+ {20100, nullptr, "SaveSystemReport"},
+ {20200, nullptr, "SetOperationMode"},
+ {20101, nullptr, "SaveSystemReportWithUser"},
+ {30100, nullptr, "ClearStorage"},
+ {40100, nullptr, "IsUserAgreementCheckEnabled"},
+ {40101, nullptr, "SetUserAgreementCheckEnabled"},
+ {90100, nullptr, "GetStorageUsage"},
+ {90200, nullptr, "GetStatistics"},
+ {90201, nullptr, "GetThroughputHistory"},
+ {90300, nullptr, "GetLastUploadError"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+
+private:
+ void SaveReportWithUser(Kernel::HLERequestContext& ctx) {
+ // TODO(ogniK): Do we want to add play report?
+ LOG_WARNING(Service_PREPO, "(STUBBED) called");
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(RESULT_SUCCESS);
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_SUCCESS);
+ }
};
void InstallInterfaces(SM::ServiceManager& service_manager) {
diff --git a/src/core/hle/service/prepo/prepo.h b/src/core/hle/service/prepo/prepo.h
index f5a6aba6d..0e7b01331 100644
--- a/src/core/hle/service/prepo/prepo.h
+++ b/src/core/hle/service/prepo/prepo.h
@@ -4,22 +4,12 @@
#pragma once
-#include <memory>
-#include <string>
-#include "core/hle/kernel/event.h"
-#include "core/hle/service/service.h"
+namespace Service::SM {
+class ServiceManager;
+}
namespace Service::PlayReport {
-class PlayReport final : public ServiceFramework<PlayReport> {
-public:
- explicit PlayReport(const char* name);
- ~PlayReport() = default;
-
-private:
- void SaveReportWithUser(Kernel::HLERequestContext& ctx);
-};
-
void InstallInterfaces(SM::ServiceManager& service_manager);
} // namespace Service::PlayReport
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
index 7d3e2f8fc..58f2904ce 100644
--- a/src/video_core/engines/shader_bytecode.h
+++ b/src/video_core/engines/shader_bytecode.h
@@ -433,6 +433,45 @@ union Instruction {
} bfe;
union {
+ BitField<48, 3, u64> pred48;
+
+ union {
+ BitField<20, 20, u64> entry_a;
+ BitField<39, 5, u64> entry_b;
+ BitField<45, 1, u64> neg;
+ BitField<46, 1, u64> uses_cc;
+ } imm;
+
+ union {
+ BitField<20, 14, u64> cb_index;
+ BitField<34, 5, u64> cb_offset;
+ BitField<56, 1, u64> neg;
+ BitField<57, 1, u64> uses_cc;
+ } hi;
+
+ union {
+ BitField<20, 14, u64> cb_index;
+ BitField<34, 5, u64> cb_offset;
+ BitField<39, 5, u64> entry_a;
+ BitField<45, 1, u64> neg;
+ BitField<46, 1, u64> uses_cc;
+ } rz;
+
+ union {
+ BitField<39, 5, u64> entry_a;
+ BitField<45, 1, u64> neg;
+ BitField<46, 1, u64> uses_cc;
+ } r1;
+
+ union {
+ BitField<28, 8, u64> entry_a;
+ BitField<37, 1, u64> neg;
+ BitField<38, 1, u64> uses_cc;
+ } r2;
+
+ } lea;
+
+ union {
BitField<0, 5, FlowCondition> cond;
} flow;
@@ -487,6 +526,18 @@ union Instruction {
} psetp;
union {
+ BitField<12, 3, u64> pred12;
+ BitField<15, 1, u64> neg_pred12;
+ BitField<24, 2, PredOperation> cond;
+ BitField<29, 3, u64> pred29;
+ BitField<32, 1, u64> neg_pred29;
+ BitField<39, 3, u64> pred39;
+ BitField<42, 1, u64> neg_pred39;
+ BitField<44, 1, u64> bf;
+ BitField<45, 2, PredOperation> op;
+ } pset;
+
+ union {
BitField<39, 3, u64> pred39;
BitField<42, 1, u64> neg_pred;
BitField<43, 1, u64> neg_a;
@@ -736,6 +787,11 @@ public:
ISCADD_C, // Scale and Add
ISCADD_R,
ISCADD_IMM,
+ LEA_R1,
+ LEA_R2,
+ LEA_RZ,
+ LEA_IMM,
+ LEA_HI,
POPC_C,
POPC_R,
POPC_IMM,
@@ -794,6 +850,7 @@ public:
ISET_C,
ISET_IMM,
PSETP,
+ PSET,
XMAD_IMM,
XMAD_CR,
XMAD_RC,
@@ -817,6 +874,7 @@ public:
IntegerSet,
IntegerSetPredicate,
PredicateSetPredicate,
+ PredicateSetRegister,
Conversion,
Xmad,
Unknown,
@@ -968,6 +1026,11 @@ private:
INST("0100110010100---", Id::SEL_C, Type::ArithmeticInteger, "SEL_C"),
INST("0101110010100---", Id::SEL_R, Type::ArithmeticInteger, "SEL_R"),
INST("0011100-10100---", Id::SEL_IMM, Type::ArithmeticInteger, "SEL_IMM"),
+ INST("0101101111011---", Id::LEA_R2, Type::ArithmeticInteger, "LEA_R2"),
+ INST("0101101111010---", Id::LEA_R1, Type::ArithmeticInteger, "LEA_R1"),
+ INST("001101101101----", Id::LEA_IMM, Type::ArithmeticInteger, "LEA_IMM"),
+ INST("010010111101----", Id::LEA_RZ, Type::ArithmeticInteger, "LEA_RZ"),
+ INST("00011000--------", Id::LEA_HI, Type::ArithmeticInteger, "LEA_HI"),
INST("0101000010000---", Id::MUFU, Type::Arithmetic, "MUFU"),
INST("0100110010010---", Id::RRO_C, Type::Arithmetic, "RRO_C"),
INST("0101110010010---", Id::RRO_R, Type::Arithmetic, "RRO_R"),
@@ -1022,6 +1085,7 @@ private:
INST("010110110101----", Id::ISET_R, Type::IntegerSet, "ISET_R"),
INST("010010110101----", Id::ISET_C, Type::IntegerSet, "ISET_C"),
INST("0011011-0101----", Id::ISET_IMM, Type::IntegerSet, "ISET_IMM"),
+ INST("0101000010001---", Id::PSET, Type::PredicateSetRegister, "PSET"),
INST("0101000010010---", Id::PSETP, Type::PredicateSetPredicate, "PSETP"),
INST("0011011-00------", Id::XMAD_IMM, Type::Xmad, "XMAD_IMM"),
INST("0100111---------", Id::XMAD_CR, Type::Xmad, "XMAD_CR"),
diff --git a/src/video_core/renderer_base.cpp b/src/video_core/renderer_base.cpp
index be17a2b9c..0df3725c2 100644
--- a/src/video_core/renderer_base.cpp
+++ b/src/video_core/renderer_base.cpp
@@ -19,6 +19,7 @@ void RendererBase::RefreshBaseSettings() {
UpdateCurrentFramebufferLayout();
renderer_settings.use_framelimiter = Settings::values.use_frame_limit;
+ renderer_settings.set_background_color = true;
}
void RendererBase::UpdateCurrentFramebufferLayout() {
diff --git a/src/video_core/renderer_base.h b/src/video_core/renderer_base.h
index 2a357f9d0..2cd0738ff 100644
--- a/src/video_core/renderer_base.h
+++ b/src/video_core/renderer_base.h
@@ -19,6 +19,7 @@ namespace VideoCore {
struct RendererSettings {
std::atomic_bool use_framelimiter{false};
+ std::atomic_bool set_background_color{false};
};
class RendererBase : NonCopyable {
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
index 29d61eccd..fb56decc0 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
@@ -53,8 +53,6 @@ static VAddr TryGetCpuAddr(Tegra::GPUVAddr gpu_addr) {
params.width = Common::AlignUp(config.tic.Width(), GetCompressionFactor(params.pixel_format));
params.height = Common::AlignUp(config.tic.Height(), GetCompressionFactor(params.pixel_format));
params.unaligned_height = config.tic.Height();
- params.cache_width = Common::AlignUp(params.width, 8);
- params.cache_height = Common::AlignUp(params.height, 8);
params.target = SurfaceTargetFromTextureType(config.tic.texture_type);
switch (params.target) {
@@ -89,8 +87,6 @@ static VAddr TryGetCpuAddr(Tegra::GPUVAddr gpu_addr) {
params.width = config.width;
params.height = config.height;
params.unaligned_height = config.height;
- params.cache_width = Common::AlignUp(params.width, 8);
- params.cache_height = Common::AlignUp(params.height, 8);
params.target = SurfaceTarget::Texture2D;
params.depth = 1;
params.size_in_bytes = params.SizeInBytes();
@@ -110,8 +106,6 @@ static VAddr TryGetCpuAddr(Tegra::GPUVAddr gpu_addr) {
params.width = zeta_width;
params.height = zeta_height;
params.unaligned_height = zeta_height;
- params.cache_width = Common::AlignUp(params.width, 8);
- params.cache_height = Common::AlignUp(params.height, 8);
params.target = SurfaceTarget::Texture2D;
params.depth = 1;
params.size_in_bytes = params.SizeInBytes();
@@ -477,30 +471,27 @@ CachedSurface::CachedSurface(const SurfaceParams& params)
// Only pre-create the texture for non-compressed textures.
switch (params.target) {
case SurfaceParams::SurfaceTarget::Texture1D:
- glTexImage1D(SurfaceTargetToGL(params.target), 0, format_tuple.internal_format,
- rect.GetWidth(), 0, format_tuple.format, format_tuple.type, nullptr);
+ glTexStorage1D(SurfaceTargetToGL(params.target), 1, format_tuple.internal_format,
+ rect.GetWidth());
break;
case SurfaceParams::SurfaceTarget::Texture2D:
- glTexImage2D(SurfaceTargetToGL(params.target), 0, format_tuple.internal_format,
- rect.GetWidth(), rect.GetHeight(), 0, format_tuple.format,
- format_tuple.type, nullptr);
+ glTexStorage2D(SurfaceTargetToGL(params.target), 1, format_tuple.internal_format,
+ rect.GetWidth(), rect.GetHeight());
break;
case SurfaceParams::SurfaceTarget::Texture3D:
case SurfaceParams::SurfaceTarget::Texture2DArray:
- glTexImage3D(SurfaceTargetToGL(params.target), 0, format_tuple.internal_format,
- rect.GetWidth(), rect.GetHeight(), params.depth, 0, format_tuple.format,
- format_tuple.type, nullptr);
+ glTexStorage3D(SurfaceTargetToGL(params.target), 1, format_tuple.internal_format,
+ rect.GetWidth(), rect.GetHeight(), params.depth);
break;
default:
LOG_CRITICAL(Render_OpenGL, "Unimplemented surface target={}",
static_cast<u32>(params.target));
UNREACHABLE();
- glTexImage2D(GL_TEXTURE_2D, 0, format_tuple.internal_format, rect.GetWidth(),
- rect.GetHeight(), 0, format_tuple.format, format_tuple.type, nullptr);
+ glTexStorage2D(GL_TEXTURE_2D, 1, format_tuple.internal_format, rect.GetWidth(),
+ rect.GetHeight());
}
}
- glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_MAX_LEVEL, 0);
glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
@@ -817,16 +808,20 @@ Surface RasterizerCacheOpenGL::RecreateSurface(const Surface& surface,
// Get a new surface with the new parameters, and blit the previous surface to it
Surface new_surface{GetUncachedSurface(new_params)};
- // If format is unchanged, we can do a faster blit without reinterpreting pixel data
- if (params.pixel_format == new_params.pixel_format) {
+ if (params.pixel_format == new_params.pixel_format ||
+ !Settings::values.use_accurate_framebuffers) {
+ // If the format is the same, just do a framebuffer blit. This is significantly faster than
+ // using PBOs. The is also likely less accurate, as textures will be converted rather than
+ // reinterpreted.
+
BlitTextures(surface->Texture().handle, params.GetRect(), new_surface->Texture().handle,
params.GetRect(), params.type, read_framebuffer.handle,
draw_framebuffer.handle);
- return new_surface;
- }
+ } else {
+ // When use_accurate_framebuffers setting is enabled, perform a more accurate surface copy,
+ // where pixels are reinterpreted as a new format (without conversion). This code path uses
+ // OpenGL PBOs and is quite slow.
- // When using accurate framebuffers, always copy old data to new surface, regardless of format
- if (Settings::values.use_accurate_framebuffers) {
auto source_format = GetFormatTuple(params.pixel_format, params.component_type);
auto dest_format = GetFormatTuple(new_params.pixel_format, new_params.component_type);
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
index e660998d0..57ea8593b 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
@@ -680,8 +680,8 @@ struct SurfaceParams {
/// Checks if surfaces are compatible for caching
bool IsCompatibleSurface(const SurfaceParams& other) const {
- return std::tie(pixel_format, type, cache_width, cache_height) ==
- std::tie(other.pixel_format, other.type, other.cache_width, other.cache_height);
+ return std::tie(pixel_format, type, width, height) ==
+ std::tie(other.pixel_format, other.type, other.width, other.height);
}
VAddr addr;
@@ -696,10 +696,6 @@ struct SurfaceParams {
u32 unaligned_height;
size_t size_in_bytes;
SurfaceTarget target;
-
- // Parameters used for caching only
- u32 cache_width;
- u32 cache_height;
};
}; // namespace OpenGL
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 64f3f341a..2d56370c7 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -1505,6 +1505,73 @@ private:
1, 1);
break;
}
+ case OpCode::Id::LEA_R2:
+ case OpCode::Id::LEA_R1:
+ case OpCode::Id::LEA_IMM:
+ case OpCode::Id::LEA_RZ:
+ case OpCode::Id::LEA_HI: {
+ std::string op_a;
+ std::string op_b;
+ std::string op_c;
+
+ switch (opcode->GetId()) {
+ case OpCode::Id::LEA_R2: {
+ op_a = regs.GetRegisterAsInteger(instr.gpr20);
+ op_b = regs.GetRegisterAsInteger(instr.gpr39);
+ op_c = std::to_string(instr.lea.r2.entry_a);
+ break;
+ }
+
+ case OpCode::Id::LEA_R1: {
+ const bool neg = instr.lea.r1.neg != 0;
+ op_a = regs.GetRegisterAsInteger(instr.gpr8);
+ if (neg)
+ op_a = "-(" + op_a + ')';
+ op_b = regs.GetRegisterAsInteger(instr.gpr20);
+ op_c = std::to_string(instr.lea.r1.entry_a);
+ break;
+ }
+
+ case OpCode::Id::LEA_IMM: {
+ const bool neg = instr.lea.imm.neg != 0;
+ op_b = regs.GetRegisterAsInteger(instr.gpr8);
+ if (neg)
+ op_b = "-(" + op_b + ')';
+ op_a = std::to_string(instr.lea.imm.entry_a);
+ op_c = std::to_string(instr.lea.imm.entry_b);
+ break;
+ }
+
+ case OpCode::Id::LEA_RZ: {
+ const bool neg = instr.lea.rz.neg != 0;
+ op_b = regs.GetRegisterAsInteger(instr.gpr8);
+ if (neg)
+ op_b = "-(" + op_b + ')';
+ op_a = regs.GetUniform(instr.lea.rz.cb_index, instr.lea.rz.cb_offset,
+ GLSLRegister::Type::Integer);
+ op_c = std::to_string(instr.lea.rz.entry_a);
+
+ break;
+ }
+
+ case OpCode::Id::LEA_HI:
+ default: {
+ op_b = regs.GetRegisterAsInteger(instr.gpr8);
+ op_a = std::to_string(instr.lea.imm.entry_a);
+ op_c = std::to_string(instr.lea.imm.entry_b);
+ LOG_CRITICAL(HW_GPU, "Unhandled LEA subinstruction: {}", opcode->GetName());
+ UNREACHABLE();
+ }
+ }
+ if (instr.lea.pred48 != static_cast<u64>(Pred::UnusedIndex)) {
+ LOG_ERROR(HW_GPU, "Unhandled LEA Predicate");
+ UNREACHABLE();
+ }
+ const std::string value = '(' + op_a + " + (" + op_b + "*(1 << " + op_c + ")))";
+ regs.SetRegisterToInteger(instr.gpr0, true, 0, value, 1, 1);
+
+ break;
+ }
default: {
LOG_CRITICAL(HW_GPU, "Unhandled ArithmeticInteger instruction: {}",
opcode->GetName());
@@ -2119,6 +2186,30 @@ private:
}
break;
}
+ case OpCode::Type::PredicateSetRegister: {
+ const std::string op_a =
+ GetPredicateCondition(instr.pset.pred12, instr.pset.neg_pred12 != 0);
+ const std::string op_b =
+ GetPredicateCondition(instr.pset.pred29, instr.pset.neg_pred29 != 0);
+
+ const std::string second_pred =
+ GetPredicateCondition(instr.pset.pred39, instr.pset.neg_pred39 != 0);
+
+ const std::string combiner = GetPredicateCombiner(instr.pset.op);
+
+ const std::string predicate =
+ '(' + op_a + ") " + GetPredicateCombiner(instr.pset.cond) + " (" + op_b + ')';
+ const std::string result = '(' + predicate + ") " + combiner + " (" + second_pred + ')';
+ if (instr.pset.bf == 0) {
+ const std::string value = '(' + result + ") ? 0xFFFFFFFF : 0";
+ regs.SetRegisterToInteger(instr.gpr0, false, 0, value, 1, 1);
+ } else {
+ const std::string value = '(' + result + ") ? 1.0 : 0.0";
+ regs.SetRegisterToFloat(instr.gpr0, 0, value, 1, 1);
+ }
+
+ break;
+ }
case OpCode::Type::PredicateSetPredicate: {
const std::string op_a =
GetPredicateCondition(instr.psetp.pred12, instr.psetp.neg_pred12 != 0);
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index ccff3e342..96d916b07 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -369,6 +369,12 @@ void RendererOpenGL::DrawScreenTriangles(const ScreenInfo& screen_info, float x,
* Draws the emulated screens to the emulator window.
*/
void RendererOpenGL::DrawScreen() {
+ if (renderer_settings.set_background_color) {
+ // Update background color before drawing
+ glClearColor(Settings::values.bg_red, Settings::values.bg_green, Settings::values.bg_blue,
+ 0.0f);
+ }
+
const auto& layout = render_window.GetFramebufferLayout();
const auto& screen = layout.screen;
diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp
index ee1287028..839d58f59 100644
--- a/src/yuzu/configuration/configure_graphics.cpp
+++ b/src/yuzu/configuration/configure_graphics.cpp
@@ -2,6 +2,7 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include <QColorDialog>
#include "core/core.h"
#include "core/settings.h"
#include "ui_configure_graphics.h"
@@ -16,6 +17,14 @@ ConfigureGraphics::ConfigureGraphics(QWidget* parent)
ui->frame_limit->setEnabled(Settings::values.use_frame_limit);
connect(ui->toggle_frame_limit, &QCheckBox::stateChanged, ui->frame_limit,
&QSpinBox::setEnabled);
+ connect(ui->bg_button, &QPushButton::clicked, this, [this] {
+ const QColor new_bg_color = QColorDialog::getColor(bg_color);
+ if (!new_bg_color.isValid())
+ return;
+ bg_color = new_bg_color;
+ ui->bg_button->setStyleSheet(
+ QString("QPushButton { background-color: %1 }").arg(bg_color.name()));
+ });
}
ConfigureGraphics::~ConfigureGraphics() = default;
@@ -65,6 +74,10 @@ void ConfigureGraphics::setConfiguration() {
ui->toggle_frame_limit->setChecked(Settings::values.use_frame_limit);
ui->frame_limit->setValue(Settings::values.frame_limit);
ui->use_accurate_framebuffers->setChecked(Settings::values.use_accurate_framebuffers);
+ bg_color = QColor::fromRgbF(Settings::values.bg_red, Settings::values.bg_green,
+ Settings::values.bg_blue);
+ ui->bg_button->setStyleSheet(
+ QString("QPushButton { background-color: %1 }").arg(bg_color.name()));
}
void ConfigureGraphics::applyConfiguration() {
@@ -73,4 +86,7 @@ void ConfigureGraphics::applyConfiguration() {
Settings::values.use_frame_limit = ui->toggle_frame_limit->isChecked();
Settings::values.frame_limit = ui->frame_limit->value();
Settings::values.use_accurate_framebuffers = ui->use_accurate_framebuffers->isChecked();
+ Settings::values.bg_red = static_cast<float>(bg_color.redF());
+ Settings::values.bg_green = static_cast<float>(bg_color.greenF());
+ Settings::values.bg_blue = static_cast<float>(bg_color.blueF());
}
diff --git a/src/yuzu/configuration/configure_graphics.h b/src/yuzu/configuration/configure_graphics.h
index 5497a55f7..9bda26fd6 100644
--- a/src/yuzu/configuration/configure_graphics.h
+++ b/src/yuzu/configuration/configure_graphics.h
@@ -25,4 +25,5 @@ private:
private:
std::unique_ptr<Ui::ConfigureGraphics> ui;
+ QColor bg_color;
};
diff --git a/src/yuzu/configuration/configure_graphics.ui b/src/yuzu/configuration/configure_graphics.ui
index 3bc18c26e..8fc00af1b 100644
--- a/src/yuzu/configuration/configure_graphics.ui
+++ b/src/yuzu/configuration/configure_graphics.ui
@@ -96,6 +96,27 @@
</item>
</layout>
</item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_6">
+ <item>
+ <widget class="QLabel" name="bg_label">
+ <property name="text">
+ <string>Background Color:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="bg_button">
+ <property name="maximumSize">
+ <size>
+ <width>40</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
</layout>
</widget>
</item>
diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp
index 8c6e16d47..3b3b551bb 100644
--- a/src/yuzu/game_list.cpp
+++ b/src/yuzu/game_list.cpp
@@ -366,7 +366,7 @@ void GameList::LoadCompatibilityList() {
QJsonDocument json = QJsonDocument::fromJson(string_content.toUtf8());
QJsonArray arr = json.array();
- for (const QJsonValue& value : arr) {
+ for (const QJsonValueRef& value : arr) {
QJsonObject game = value.toObject();
if (game.contains("compatibility") && game["compatibility"].isDouble()) {
@@ -374,9 +374,9 @@ void GameList::LoadCompatibilityList() {
QString directory = game["directory"].toString();
QJsonArray ids = game["releases"].toArray();
- for (const QJsonValue& value : ids) {
- QJsonObject object = value.toObject();
- QString id = object["id"].toString();
+ for (const QJsonValueRef& id_ref : ids) {
+ QJsonObject id_object = id_ref.toObject();
+ QString id = id_object["id"].toString();
compatibility_list.emplace(
id.toUpper().toStdString(),
std::make_pair(QString::number(compatibility), directory));
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index e36914f14..05a4a55e8 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -447,6 +447,8 @@ QStringList GMainWindow::GetUnsupportedGLExtensions() {
unsupported_ext.append("ARB_texture_mirror_clamp_to_edge");
if (!GLAD_GL_ARB_base_instance)
unsupported_ext.append("ARB_base_instance");
+ if (!GLAD_GL_ARB_texture_storage)
+ unsupported_ext.append("ARB_texture_storage");
// Extensions required to support some texture formats.
if (!GLAD_GL_EXT_texture_compression_s3tc)
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp
index 1c4717123..d213929bd 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp
@@ -94,6 +94,8 @@ bool EmuWindow_SDL2::SupportsRequiredGLExtensions() {
unsupported_ext.push_back("ARB_texture_mirror_clamp_to_edge");
if (!GLAD_GL_ARB_base_instance)
unsupported_ext.push_back("ARB_base_instance");
+ if (!GLAD_GL_ARB_texture_storage)
+ unsupported_ext.push_back("ARB_texture_storage");
// Extensions required to support some texture formats.
if (!GLAD_GL_EXT_texture_compression_s3tc)