diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/common/settings.cpp | 4 | ||||
| -rw-r--r-- | src/common/settings.h | 8 | ||||
| -rw-r--r-- | src/core/telemetry_session.cpp | 16 | ||||
| -rw-r--r-- | src/video_core/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | src/video_core/command_classes/codecs/codec.cpp | 224 | ||||
| -rw-r--r-- | src/video_core/command_classes/codecs/codec.h | 9 | ||||
| -rw-r--r-- | src/video_core/command_classes/codecs/h264.cpp | 3 | ||||
| -rw-r--r-- | src/video_core/video_core.cpp | 3 | ||||
| -rw-r--r-- | src/yuzu/configuration/config.cpp | 7 | ||||
| -rw-r--r-- | src/yuzu/configuration/config.h | 1 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_graphics.cpp | 42 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_graphics.h | 1 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_graphics.ui | 51 | ||||
| -rw-r--r-- | src/yuzu_cmd/config.cpp | 2 | ||||
| -rw-r--r-- | src/yuzu_cmd/default_ini.h | 6 |
15 files changed, 257 insertions, 121 deletions
diff --git a/src/common/settings.cpp b/src/common/settings.cpp index fd3b639cd..0d2df80a8 100644 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp | |||
| @@ -54,7 +54,7 @@ void LogSettings() { | |||
| 54 | log_setting("Renderer_GPUAccuracyLevel", values.gpu_accuracy.GetValue()); | 54 | log_setting("Renderer_GPUAccuracyLevel", values.gpu_accuracy.GetValue()); |
| 55 | log_setting("Renderer_UseAsynchronousGpuEmulation", | 55 | log_setting("Renderer_UseAsynchronousGpuEmulation", |
| 56 | values.use_asynchronous_gpu_emulation.GetValue()); | 56 | values.use_asynchronous_gpu_emulation.GetValue()); |
| 57 | log_setting("Renderer_UseNvdecEmulation", values.use_nvdec_emulation.GetValue()); | 57 | log_setting("Renderer_NvdecEmulation", values.nvdec_emulation.GetValue()); |
| 58 | log_setting("Renderer_AccelerateASTC", values.accelerate_astc.GetValue()); | 58 | log_setting("Renderer_AccelerateASTC", values.accelerate_astc.GetValue()); |
| 59 | log_setting("Renderer_UseVsync", values.use_vsync.GetValue()); | 59 | log_setting("Renderer_UseVsync", values.use_vsync.GetValue()); |
| 60 | log_setting("Renderer_ShaderBackend", values.shader_backend.GetValue()); | 60 | log_setting("Renderer_ShaderBackend", values.shader_backend.GetValue()); |
| @@ -136,7 +136,7 @@ void RestoreGlobalState(bool is_powered_on) { | |||
| 136 | values.use_disk_shader_cache.SetGlobal(true); | 136 | values.use_disk_shader_cache.SetGlobal(true); |
| 137 | values.gpu_accuracy.SetGlobal(true); | 137 | values.gpu_accuracy.SetGlobal(true); |
| 138 | values.use_asynchronous_gpu_emulation.SetGlobal(true); | 138 | values.use_asynchronous_gpu_emulation.SetGlobal(true); |
| 139 | values.use_nvdec_emulation.SetGlobal(true); | 139 | values.nvdec_emulation.SetGlobal(true); |
| 140 | values.accelerate_astc.SetGlobal(true); | 140 | values.accelerate_astc.SetGlobal(true); |
| 141 | values.use_vsync.SetGlobal(true); | 141 | values.use_vsync.SetGlobal(true); |
| 142 | values.shader_backend.SetGlobal(true); | 142 | values.shader_backend.SetGlobal(true); |
diff --git a/src/common/settings.h b/src/common/settings.h index ec4d381e8..b7195670b 100644 --- a/src/common/settings.h +++ b/src/common/settings.h | |||
| @@ -48,6 +48,12 @@ enum class FullscreenMode : u32 { | |||
| 48 | Exclusive = 1, | 48 | Exclusive = 1, |
| 49 | }; | 49 | }; |
| 50 | 50 | ||
| 51 | enum class NvdecEmulation : u32 { | ||
| 52 | Off = 0, | ||
| 53 | CPU = 1, | ||
| 54 | GPU = 2, | ||
| 55 | }; | ||
| 56 | |||
| 51 | /** The BasicSetting class is a simple resource manager. It defines a label and default value | 57 | /** The BasicSetting class is a simple resource manager. It defines a label and default value |
| 52 | * alongside the actual value of the setting for simpler and less-error prone use with frontend | 58 | * alongside the actual value of the setting for simpler and less-error prone use with frontend |
| 53 | * configurations. Setting a default value and label is required, though subclasses may deviate from | 59 | * configurations. Setting a default value and label is required, though subclasses may deviate from |
| @@ -466,7 +472,7 @@ struct Values { | |||
| 466 | RangedSetting<GPUAccuracy> gpu_accuracy{GPUAccuracy::High, GPUAccuracy::Normal, | 472 | RangedSetting<GPUAccuracy> gpu_accuracy{GPUAccuracy::High, GPUAccuracy::Normal, |
| 467 | GPUAccuracy::Extreme, "gpu_accuracy"}; | 473 | GPUAccuracy::Extreme, "gpu_accuracy"}; |
| 468 | Setting<bool> use_asynchronous_gpu_emulation{true, "use_asynchronous_gpu_emulation"}; | 474 | Setting<bool> use_asynchronous_gpu_emulation{true, "use_asynchronous_gpu_emulation"}; |
| 469 | Setting<bool> use_nvdec_emulation{true, "use_nvdec_emulation"}; | 475 | Setting<NvdecEmulation> nvdec_emulation{NvdecEmulation::GPU, "nvdec_emulation"}; |
| 470 | Setting<bool> accelerate_astc{true, "accelerate_astc"}; | 476 | Setting<bool> accelerate_astc{true, "accelerate_astc"}; |
| 471 | Setting<bool> use_vsync{true, "use_vsync"}; | 477 | Setting<bool> use_vsync{true, "use_vsync"}; |
| 472 | BasicRangedSetting<u16> fps_cap{1000, 1, 1000, "fps_cap"}; | 478 | BasicRangedSetting<u16> fps_cap{1000, 1, 1000, "fps_cap"}; |
diff --git a/src/core/telemetry_session.cpp b/src/core/telemetry_session.cpp index 5a8cfd301..1f1607998 100644 --- a/src/core/telemetry_session.cpp +++ b/src/core/telemetry_session.cpp | |||
| @@ -72,6 +72,18 @@ static const char* TranslateGPUAccuracyLevel(Settings::GPUAccuracy backend) { | |||
| 72 | return "Unknown"; | 72 | return "Unknown"; |
| 73 | } | 73 | } |
| 74 | 74 | ||
| 75 | static const char* TranslateNvdecEmulation(Settings::NvdecEmulation backend) { | ||
| 76 | switch (backend) { | ||
| 77 | case Settings::NvdecEmulation::Off: | ||
| 78 | return "Off"; | ||
| 79 | case Settings::NvdecEmulation::CPU: | ||
| 80 | return "CPU"; | ||
| 81 | case Settings::NvdecEmulation::GPU: | ||
| 82 | return "GPU"; | ||
| 83 | } | ||
| 84 | return "Unknown"; | ||
| 85 | } | ||
| 86 | |||
| 75 | u64 GetTelemetryId() { | 87 | u64 GetTelemetryId() { |
| 76 | u64 telemetry_id{}; | 88 | u64 telemetry_id{}; |
| 77 | const auto filename = Common::FS::GetYuzuPath(Common::FS::YuzuPath::ConfigDir) / "telemetry_id"; | 89 | const auto filename = Common::FS::GetYuzuPath(Common::FS::YuzuPath::ConfigDir) / "telemetry_id"; |
| @@ -229,8 +241,8 @@ void TelemetrySession::AddInitialInfo(Loader::AppLoader& app_loader, | |||
| 229 | TranslateGPUAccuracyLevel(Settings::values.gpu_accuracy.GetValue())); | 241 | TranslateGPUAccuracyLevel(Settings::values.gpu_accuracy.GetValue())); |
| 230 | AddField(field_type, "Renderer_UseAsynchronousGpuEmulation", | 242 | AddField(field_type, "Renderer_UseAsynchronousGpuEmulation", |
| 231 | Settings::values.use_asynchronous_gpu_emulation.GetValue()); | 243 | Settings::values.use_asynchronous_gpu_emulation.GetValue()); |
| 232 | AddField(field_type, "Renderer_UseNvdecEmulation", | 244 | AddField(field_type, "Renderer_NvdecEmulation", |
| 233 | Settings::values.use_nvdec_emulation.GetValue()); | 245 | TranslateNvdecEmulation(Settings::values.nvdec_emulation.GetValue())); |
| 234 | AddField(field_type, "Renderer_AccelerateASTC", Settings::values.accelerate_astc.GetValue()); | 246 | AddField(field_type, "Renderer_AccelerateASTC", Settings::values.accelerate_astc.GetValue()); |
| 235 | AddField(field_type, "Renderer_UseVsync", Settings::values.use_vsync.GetValue()); | 247 | AddField(field_type, "Renderer_UseVsync", Settings::values.use_vsync.GetValue()); |
| 236 | AddField(field_type, "Renderer_ShaderBackend", | 248 | AddField(field_type, "Renderer_ShaderBackend", |
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 2f6cdd216..269db21a5 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt | |||
| @@ -231,6 +231,7 @@ endif() | |||
| 231 | 231 | ||
| 232 | target_include_directories(video_core PRIVATE ${FFmpeg_INCLUDE_DIR}) | 232 | target_include_directories(video_core PRIVATE ${FFmpeg_INCLUDE_DIR}) |
| 233 | target_link_libraries(video_core PRIVATE ${FFmpeg_LIBRARIES}) | 233 | target_link_libraries(video_core PRIVATE ${FFmpeg_LIBRARIES}) |
| 234 | target_link_options(video_core PRIVATE ${FFmpeg_LDFLAGS}) | ||
| 234 | 235 | ||
| 235 | add_dependencies(video_core host_shaders) | 236 | add_dependencies(video_core host_shaders) |
| 236 | target_include_directories(video_core PRIVATE ${HOST_SHADERS_INCLUDE}) | 237 | target_include_directories(video_core PRIVATE ${HOST_SHADERS_INCLUDE}) |
diff --git a/src/video_core/command_classes/codecs/codec.cpp b/src/video_core/command_classes/codecs/codec.cpp index f798a0053..61966cbfe 100644 --- a/src/video_core/command_classes/codecs/codec.cpp +++ b/src/video_core/command_classes/codecs/codec.cpp | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #include <fstream> | 5 | #include <fstream> |
| 6 | #include <vector> | 6 | #include <vector> |
| 7 | #include "common/assert.h" | 7 | #include "common/assert.h" |
| 8 | #include "common/settings.h" | ||
| 8 | #include "video_core/command_classes/codecs/codec.h" | 9 | #include "video_core/command_classes/codecs/codec.h" |
| 9 | #include "video_core/command_classes/codecs/h264.h" | 10 | #include "video_core/command_classes/codecs/h264.h" |
| 10 | #include "video_core/command_classes/codecs/vp9.h" | 11 | #include "video_core/command_classes/codecs/vp9.h" |
| @@ -16,108 +17,146 @@ extern "C" { | |||
| 16 | } | 17 | } |
| 17 | 18 | ||
| 18 | namespace Tegra { | 19 | namespace Tegra { |
| 19 | #if defined(LIBVA_FOUND) | ||
| 20 | // Hardware acceleration code from FFmpeg/doc/examples/hw_decode.c originally under MIT license | ||
| 21 | namespace { | 20 | namespace { |
| 22 | constexpr std::array<const char*, 2> VAAPI_DRIVERS = { | 21 | constexpr AVPixelFormat PREFERRED_GPU_FMT = AV_PIX_FMT_NV12; |
| 23 | "i915", | 22 | constexpr AVPixelFormat PREFERRED_CPU_FMT = AV_PIX_FMT_YUV420P; |
| 24 | "amdgpu", | 23 | |
| 25 | }; | 24 | void AVPacketDeleter(AVPacket* ptr) { |
| 25 | av_packet_free(&ptr); | ||
| 26 | } | ||
| 26 | 27 | ||
| 27 | AVPixelFormat GetHwFormat(AVCodecContext*, const AVPixelFormat* pix_fmts) { | 28 | using AVPacketPtr = std::unique_ptr<AVPacket, decltype(&AVPacketDeleter)>; |
| 29 | |||
| 30 | AVPixelFormat GetGpuFormat(AVCodecContext* av_codec_ctx, const AVPixelFormat* pix_fmts) { | ||
| 28 | for (const AVPixelFormat* p = pix_fmts; *p != AV_PIX_FMT_NONE; ++p) { | 31 | for (const AVPixelFormat* p = pix_fmts; *p != AV_PIX_FMT_NONE; ++p) { |
| 29 | if (*p == AV_PIX_FMT_VAAPI) { | 32 | if (*p == av_codec_ctx->pix_fmt) { |
| 30 | return AV_PIX_FMT_VAAPI; | 33 | return av_codec_ctx->pix_fmt; |
| 31 | } | 34 | } |
| 32 | } | 35 | } |
| 33 | LOG_INFO(Service_NVDRV, "Could not find compatible GPU AV format, falling back to CPU"); | 36 | LOG_INFO(Service_NVDRV, "Could not find compatible GPU AV format, falling back to CPU"); |
| 34 | return *pix_fmts; | 37 | av_buffer_unref(&av_codec_ctx->hw_device_ctx); |
| 38 | av_codec_ctx->pix_fmt = PREFERRED_CPU_FMT; | ||
| 39 | return PREFERRED_CPU_FMT; | ||
| 40 | } | ||
| 41 | } // namespace | ||
| 42 | |||
| 43 | void AVFrameDeleter(AVFrame* ptr) { | ||
| 44 | av_frame_free(&ptr); | ||
| 35 | } | 45 | } |
| 36 | 46 | ||
| 37 | bool CreateVaapiHwdevice(AVBufferRef** av_hw_device) { | 47 | Codec::Codec(GPU& gpu_, const NvdecCommon::NvdecRegisters& regs) |
| 48 | : gpu(gpu_), state{regs}, h264_decoder(std::make_unique<Decoder::H264>(gpu)), | ||
| 49 | vp9_decoder(std::make_unique<Decoder::VP9>(gpu)) {} | ||
| 50 | |||
| 51 | Codec::~Codec() { | ||
| 52 | if (!initialized) { | ||
| 53 | return; | ||
| 54 | } | ||
| 55 | // Free libav memory | ||
| 56 | avcodec_free_context(&av_codec_ctx); | ||
| 57 | av_buffer_unref(&av_gpu_decoder); | ||
| 58 | } | ||
| 59 | |||
| 60 | bool Codec::CreateGpuAvDevice() { | ||
| 61 | #if defined(LIBVA_FOUND) | ||
| 62 | static constexpr std::array<const char*, 3> VAAPI_DRIVERS = { | ||
| 63 | "i915", | ||
| 64 | "iHD", | ||
| 65 | "amdgpu", | ||
| 66 | }; | ||
| 38 | AVDictionary* hwdevice_options = nullptr; | 67 | AVDictionary* hwdevice_options = nullptr; |
| 39 | av_dict_set(&hwdevice_options, "connection_type", "drm", 0); | 68 | av_dict_set(&hwdevice_options, "connection_type", "drm", 0); |
| 40 | for (const auto& driver : VAAPI_DRIVERS) { | 69 | for (const auto& driver : VAAPI_DRIVERS) { |
| 41 | av_dict_set(&hwdevice_options, "kernel_driver", driver, 0); | 70 | av_dict_set(&hwdevice_options, "kernel_driver", driver, 0); |
| 42 | const int hwdevice_error = av_hwdevice_ctx_create(av_hw_device, AV_HWDEVICE_TYPE_VAAPI, | 71 | const int hwdevice_error = av_hwdevice_ctx_create(&av_gpu_decoder, AV_HWDEVICE_TYPE_VAAPI, |
| 43 | nullptr, hwdevice_options, 0); | 72 | nullptr, hwdevice_options, 0); |
| 44 | if (hwdevice_error >= 0) { | 73 | if (hwdevice_error >= 0) { |
| 45 | LOG_INFO(Service_NVDRV, "Using VA-API with {}", driver); | 74 | LOG_INFO(Service_NVDRV, "Using VA-API with {}", driver); |
| 46 | av_dict_free(&hwdevice_options); | 75 | av_dict_free(&hwdevice_options); |
| 76 | av_codec_ctx->pix_fmt = AV_PIX_FMT_VAAPI; | ||
| 47 | return true; | 77 | return true; |
| 48 | } | 78 | } |
| 49 | LOG_DEBUG(Service_NVDRV, "VA-API av_hwdevice_ctx_create failed {}", hwdevice_error); | 79 | LOG_DEBUG(Service_NVDRV, "VA-API av_hwdevice_ctx_create failed {}", hwdevice_error); |
| 50 | } | 80 | } |
| 51 | LOG_DEBUG(Service_NVDRV, "VA-API av_hwdevice_ctx_create failed for all drivers"); | 81 | LOG_DEBUG(Service_NVDRV, "VA-API av_hwdevice_ctx_create failed for all drivers"); |
| 52 | av_dict_free(&hwdevice_options); | 82 | av_dict_free(&hwdevice_options); |
| 53 | return false; | ||
| 54 | } | ||
| 55 | } // namespace | ||
| 56 | #endif | 83 | #endif |
| 57 | 84 | static constexpr auto HW_CONFIG_METHOD = AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX; | |
| 58 | void AVFrameDeleter(AVFrame* ptr) { | 85 | static constexpr std::array GPU_DECODER_TYPES{ |
| 59 | av_frame_free(&ptr); | 86 | AV_HWDEVICE_TYPE_CUDA, |
| 87 | #ifdef _WIN32 | ||
| 88 | AV_HWDEVICE_TYPE_D3D11VA, | ||
| 89 | #else | ||
| 90 | AV_HWDEVICE_TYPE_VDPAU, | ||
| 91 | #endif | ||
| 92 | }; | ||
| 93 | for (const auto& type : GPU_DECODER_TYPES) { | ||
| 94 | const int hwdevice_res = av_hwdevice_ctx_create(&av_gpu_decoder, type, nullptr, nullptr, 0); | ||
| 95 | if (hwdevice_res < 0) { | ||
| 96 | LOG_DEBUG(Service_NVDRV, "{} av_hwdevice_ctx_create failed {}", | ||
| 97 | av_hwdevice_get_type_name(type), hwdevice_res); | ||
| 98 | continue; | ||
| 99 | } | ||
| 100 | for (int i = 0;; i++) { | ||
| 101 | const AVCodecHWConfig* config = avcodec_get_hw_config(av_codec, i); | ||
| 102 | if (!config) { | ||
| 103 | LOG_DEBUG(Service_NVDRV, "{} decoder does not support device type {}.", | ||
| 104 | av_codec->name, av_hwdevice_get_type_name(type)); | ||
| 105 | break; | ||
| 106 | } | ||
| 107 | if (config->methods & HW_CONFIG_METHOD && config->device_type == type) { | ||
| 108 | av_codec_ctx->pix_fmt = config->pix_fmt; | ||
| 109 | LOG_INFO(Service_NVDRV, "Using {} GPU decoder", av_hwdevice_get_type_name(type)); | ||
| 110 | return true; | ||
| 111 | } | ||
| 112 | } | ||
| 113 | } | ||
| 114 | return false; | ||
| 60 | } | 115 | } |
| 61 | 116 | ||
| 62 | Codec::Codec(GPU& gpu_, const NvdecCommon::NvdecRegisters& regs) | 117 | void Codec::InitializeAvCodecContext() { |
| 63 | : gpu(gpu_), state{regs}, h264_decoder(std::make_unique<Decoder::H264>(gpu)), | 118 | av_codec_ctx = avcodec_alloc_context3(av_codec); |
| 64 | vp9_decoder(std::make_unique<Decoder::VP9>(gpu)) {} | 119 | av_opt_set(av_codec_ctx->priv_data, "tune", "zerolatency", 0); |
| 65 | |||
| 66 | Codec::~Codec() { | ||
| 67 | if (!initialized) { | ||
| 68 | return; | ||
| 69 | } | ||
| 70 | // Free libav memory | ||
| 71 | avcodec_send_packet(av_codec_ctx, nullptr); | ||
| 72 | AVFrame* av_frame = av_frame_alloc(); | ||
| 73 | avcodec_receive_frame(av_codec_ctx, av_frame); | ||
| 74 | avcodec_flush_buffers(av_codec_ctx); | ||
| 75 | av_frame_free(&av_frame); | ||
| 76 | avcodec_close(av_codec_ctx); | ||
| 77 | av_buffer_unref(&av_hw_device); | ||
| 78 | } | 120 | } |
| 79 | 121 | ||
| 80 | void Codec::InitializeHwdec() { | 122 | void Codec::InitializeGpuDecoder() { |
| 81 | // Prioritize integrated GPU to mitigate bandwidth bottlenecks | 123 | if (!CreateGpuAvDevice()) { |
| 82 | #if defined(LIBVA_FOUND) | 124 | av_buffer_unref(&av_gpu_decoder); |
| 83 | if (CreateVaapiHwdevice(&av_hw_device)) { | ||
| 84 | const auto hw_device_ctx = av_buffer_ref(av_hw_device); | ||
| 85 | ASSERT_MSG(hw_device_ctx, "av_buffer_ref failed"); | ||
| 86 | av_codec_ctx->hw_device_ctx = hw_device_ctx; | ||
| 87 | av_codec_ctx->get_format = GetHwFormat; | ||
| 88 | return; | 125 | return; |
| 89 | } | 126 | } |
| 90 | #endif | 127 | auto* hw_device_ctx = av_buffer_ref(av_gpu_decoder); |
| 91 | // TODO more GPU accelerated decoders | 128 | ASSERT_MSG(hw_device_ctx, "av_buffer_ref failed"); |
| 129 | av_codec_ctx->hw_device_ctx = hw_device_ctx; | ||
| 130 | av_codec_ctx->get_format = GetGpuFormat; | ||
| 92 | } | 131 | } |
| 93 | 132 | ||
| 94 | void Codec::Initialize() { | 133 | void Codec::Initialize() { |
| 95 | AVCodecID codec; | 134 | const AVCodecID codec = [&] { |
| 96 | switch (current_codec) { | 135 | switch (current_codec) { |
| 97 | case NvdecCommon::VideoCodec::H264: | 136 | case NvdecCommon::VideoCodec::H264: |
| 98 | codec = AV_CODEC_ID_H264; | 137 | return AV_CODEC_ID_H264; |
| 99 | break; | 138 | case NvdecCommon::VideoCodec::Vp9: |
| 100 | case NvdecCommon::VideoCodec::Vp9: | 139 | return AV_CODEC_ID_VP9; |
| 101 | codec = AV_CODEC_ID_VP9; | 140 | default: |
| 102 | break; | 141 | UNIMPLEMENTED_MSG("Unknown codec {}", current_codec); |
| 103 | default: | 142 | return AV_CODEC_ID_NONE; |
| 104 | UNIMPLEMENTED_MSG("Unknown codec {}", current_codec); | 143 | } |
| 144 | }(); | ||
| 145 | av_codec = avcodec_find_decoder(codec); | ||
| 146 | |||
| 147 | InitializeAvCodecContext(); | ||
| 148 | if (Settings::values.nvdec_emulation.GetValue() == Settings::NvdecEmulation::GPU) { | ||
| 149 | InitializeGpuDecoder(); | ||
| 150 | } | ||
| 151 | if (const int res = avcodec_open2(av_codec_ctx, av_codec, nullptr); res < 0) { | ||
| 152 | LOG_ERROR(Service_NVDRV, "avcodec_open2() Failed with result {}", res); | ||
| 153 | avcodec_free_context(&av_codec_ctx); | ||
| 154 | av_buffer_unref(&av_gpu_decoder); | ||
| 105 | return; | 155 | return; |
| 106 | } | 156 | } |
| 107 | av_codec = avcodec_find_decoder(codec); | ||
| 108 | av_codec_ctx = avcodec_alloc_context3(av_codec); | ||
| 109 | av_opt_set(av_codec_ctx->priv_data, "tune", "zerolatency", 0); | ||
| 110 | InitializeHwdec(); | ||
| 111 | if (!av_codec_ctx->hw_device_ctx) { | 157 | if (!av_codec_ctx->hw_device_ctx) { |
| 112 | LOG_INFO(Service_NVDRV, "Using FFmpeg software decoding"); | 158 | LOG_INFO(Service_NVDRV, "Using FFmpeg software decoding"); |
| 113 | } | 159 | } |
| 114 | const auto av_error = avcodec_open2(av_codec_ctx, av_codec, nullptr); | ||
| 115 | if (av_error < 0) { | ||
| 116 | LOG_ERROR(Service_NVDRV, "avcodec_open2() Failed."); | ||
| 117 | avcodec_close(av_codec_ctx); | ||
| 118 | av_buffer_unref(&av_hw_device); | ||
| 119 | return; | ||
| 120 | } | ||
| 121 | initialized = true; | 160 | initialized = true; |
| 122 | } | 161 | } |
| 123 | 162 | ||
| @@ -133,6 +172,9 @@ void Codec::Decode() { | |||
| 133 | if (is_first_frame) { | 172 | if (is_first_frame) { |
| 134 | Initialize(); | 173 | Initialize(); |
| 135 | } | 174 | } |
| 175 | if (!initialized) { | ||
| 176 | return; | ||
| 177 | } | ||
| 136 | bool vp9_hidden_frame = false; | 178 | bool vp9_hidden_frame = false; |
| 137 | std::vector<u8> frame_data; | 179 | std::vector<u8> frame_data; |
| 138 | if (current_codec == NvdecCommon::VideoCodec::H264) { | 180 | if (current_codec == NvdecCommon::VideoCodec::H264) { |
| @@ -141,50 +183,48 @@ void Codec::Decode() { | |||
| 141 | frame_data = vp9_decoder->ComposeFrameHeader(state); | 183 | frame_data = vp9_decoder->ComposeFrameHeader(state); |
| 142 | vp9_hidden_frame = vp9_decoder->WasFrameHidden(); | 184 | vp9_hidden_frame = vp9_decoder->WasFrameHidden(); |
| 143 | } | 185 | } |
| 144 | AVPacket packet{}; | 186 | AVPacketPtr packet{av_packet_alloc(), AVPacketDeleter}; |
| 145 | av_init_packet(&packet); | 187 | if (!packet) { |
| 146 | packet.data = frame_data.data(); | 188 | LOG_ERROR(Service_NVDRV, "av_packet_alloc failed"); |
| 147 | packet.size = static_cast<s32>(frame_data.size()); | 189 | return; |
| 148 | if (const int ret = avcodec_send_packet(av_codec_ctx, &packet); ret) { | 190 | } |
| 149 | LOG_DEBUG(Service_NVDRV, "avcodec_send_packet error {}", ret); | 191 | packet->data = frame_data.data(); |
| 192 | packet->size = static_cast<s32>(frame_data.size()); | ||
| 193 | if (const int res = avcodec_send_packet(av_codec_ctx, packet.get()); res != 0) { | ||
| 194 | LOG_DEBUG(Service_NVDRV, "avcodec_send_packet error {}", res); | ||
| 150 | return; | 195 | return; |
| 151 | } | 196 | } |
| 152 | // Only receive/store visible frames | 197 | // Only receive/store visible frames |
| 153 | if (vp9_hidden_frame) { | 198 | if (vp9_hidden_frame) { |
| 154 | return; | 199 | return; |
| 155 | } | 200 | } |
| 156 | AVFrame* hw_frame = av_frame_alloc(); | 201 | AVFramePtr initial_frame{av_frame_alloc(), AVFrameDeleter}; |
| 157 | AVFrame* sw_frame = hw_frame; | 202 | AVFramePtr final_frame{nullptr, AVFrameDeleter}; |
| 158 | ASSERT_MSG(hw_frame, "av_frame_alloc hw_frame failed"); | 203 | ASSERT_MSG(initial_frame, "av_frame_alloc initial_frame failed"); |
| 159 | if (const int ret = avcodec_receive_frame(av_codec_ctx, hw_frame); ret) { | 204 | if (const int ret = avcodec_receive_frame(av_codec_ctx, initial_frame.get()); ret) { |
| 160 | LOG_DEBUG(Service_NVDRV, "avcodec_receive_frame error {}", ret); | 205 | LOG_DEBUG(Service_NVDRV, "avcodec_receive_frame error {}", ret); |
| 161 | av_frame_free(&hw_frame); | ||
| 162 | return; | 206 | return; |
| 163 | } | 207 | } |
| 164 | if (!hw_frame->width || !hw_frame->height) { | 208 | if (initial_frame->width == 0 || initial_frame->height == 0) { |
| 165 | LOG_WARNING(Service_NVDRV, "Zero width or height in frame"); | 209 | LOG_WARNING(Service_NVDRV, "Zero width or height in frame"); |
| 166 | av_frame_free(&hw_frame); | ||
| 167 | return; | 210 | return; |
| 168 | } | 211 | } |
| 169 | #if defined(LIBVA_FOUND) | 212 | if (av_codec_ctx->hw_device_ctx) { |
| 170 | // Hardware acceleration code from FFmpeg/doc/examples/hw_decode.c under MIT license | 213 | final_frame = AVFramePtr{av_frame_alloc(), AVFrameDeleter}; |
| 171 | if (hw_frame->format == AV_PIX_FMT_VAAPI) { | 214 | ASSERT_MSG(final_frame, "av_frame_alloc final_frame failed"); |
| 172 | sw_frame = av_frame_alloc(); | ||
| 173 | ASSERT_MSG(sw_frame, "av_frame_alloc sw_frame failed"); | ||
| 174 | // Can't use AV_PIX_FMT_YUV420P and share code with software decoding in vic.cpp | 215 | // Can't use AV_PIX_FMT_YUV420P and share code with software decoding in vic.cpp |
| 175 | // because Intel drivers crash unless using AV_PIX_FMT_NV12 | 216 | // because Intel drivers crash unless using AV_PIX_FMT_NV12 |
| 176 | sw_frame->format = AV_PIX_FMT_NV12; | 217 | final_frame->format = PREFERRED_GPU_FMT; |
| 177 | const int transfer_data_ret = av_hwframe_transfer_data(sw_frame, hw_frame, 0); | 218 | const int ret = av_hwframe_transfer_data(final_frame.get(), initial_frame.get(), 0); |
| 178 | ASSERT_MSG(!transfer_data_ret, "av_hwframe_transfer_data error {}", transfer_data_ret); | 219 | ASSERT_MSG(!ret, "av_hwframe_transfer_data error {}", ret); |
| 179 | av_frame_free(&hw_frame); | 220 | } else { |
| 221 | final_frame = std::move(initial_frame); | ||
| 180 | } | 222 | } |
| 181 | #endif | 223 | if (final_frame->format != PREFERRED_CPU_FMT && final_frame->format != PREFERRED_GPU_FMT) { |
| 182 | if (sw_frame->format != AV_PIX_FMT_YUV420P && sw_frame->format != AV_PIX_FMT_NV12) { | 224 | UNIMPLEMENTED_MSG("Unexpected video format: {}", final_frame->format); |
| 183 | UNIMPLEMENTED_MSG("Unexpected video format from host graphics: {}", sw_frame->format); | ||
| 184 | av_frame_free(&sw_frame); | ||
| 185 | return; | 225 | return; |
| 186 | } | 226 | } |
| 187 | av_frames.push(AVFramePtr{sw_frame, AVFrameDeleter}); | 227 | av_frames.push(std::move(final_frame)); |
| 188 | if (av_frames.size() > 10) { | 228 | if (av_frames.size() > 10) { |
| 189 | LOG_TRACE(Service_NVDRV, "av_frames.push overflow dropped frame"); | 229 | LOG_TRACE(Service_NVDRV, "av_frames.push overflow dropped frame"); |
| 190 | av_frames.pop(); | 230 | av_frames.pop(); |
diff --git a/src/video_core/command_classes/codecs/codec.h b/src/video_core/command_classes/codecs/codec.h index 71936203f..1508d36c2 100644 --- a/src/video_core/command_classes/codecs/codec.h +++ b/src/video_core/command_classes/codecs/codec.h | |||
| @@ -50,18 +50,23 @@ public: | |||
| 50 | 50 | ||
| 51 | /// Returns the value of current_codec | 51 | /// Returns the value of current_codec |
| 52 | [[nodiscard]] NvdecCommon::VideoCodec GetCurrentCodec() const; | 52 | [[nodiscard]] NvdecCommon::VideoCodec GetCurrentCodec() const; |
| 53 | |||
| 53 | /// Return name of the current codec | 54 | /// Return name of the current codec |
| 54 | [[nodiscard]] std::string_view GetCurrentCodecName() const; | 55 | [[nodiscard]] std::string_view GetCurrentCodecName() const; |
| 55 | 56 | ||
| 56 | private: | 57 | private: |
| 57 | void InitializeHwdec(); | 58 | void InitializeAvCodecContext(); |
| 59 | |||
| 60 | void InitializeGpuDecoder(); | ||
| 61 | |||
| 62 | bool CreateGpuAvDevice(); | ||
| 58 | 63 | ||
| 59 | bool initialized{}; | 64 | bool initialized{}; |
| 60 | NvdecCommon::VideoCodec current_codec{NvdecCommon::VideoCodec::None}; | 65 | NvdecCommon::VideoCodec current_codec{NvdecCommon::VideoCodec::None}; |
| 61 | 66 | ||
| 62 | AVCodec* av_codec{nullptr}; | 67 | AVCodec* av_codec{nullptr}; |
| 63 | AVBufferRef* av_hw_device{nullptr}; | ||
| 64 | AVCodecContext* av_codec_ctx{nullptr}; | 68 | AVCodecContext* av_codec_ctx{nullptr}; |
| 69 | AVBufferRef* av_gpu_decoder{nullptr}; | ||
| 65 | 70 | ||
| 66 | GPU& gpu; | 71 | GPU& gpu; |
| 67 | const NvdecCommon::NvdecRegisters& state; | 72 | const NvdecCommon::NvdecRegisters& state; |
diff --git a/src/video_core/command_classes/codecs/h264.cpp b/src/video_core/command_classes/codecs/h264.cpp index 5fb6d45ee..51ee14c13 100644 --- a/src/video_core/command_classes/codecs/h264.cpp +++ b/src/video_core/command_classes/codecs/h264.cpp | |||
| @@ -95,7 +95,8 @@ const std::vector<u8>& H264::ComposeFrameHeader(const NvdecCommon::NvdecRegister | |||
| 95 | const s32 pic_height = context.h264_parameter_set.frame_height_in_map_units / | 95 | const s32 pic_height = context.h264_parameter_set.frame_height_in_map_units / |
| 96 | (context.h264_parameter_set.frame_mbs_only_flag ? 1 : 2); | 96 | (context.h264_parameter_set.frame_mbs_only_flag ? 1 : 2); |
| 97 | 97 | ||
| 98 | writer.WriteUe(16); | 98 | // TODO (ameerj): Where do we get this number, it seems to be particular for each stream |
| 99 | writer.WriteUe(6); // Max number of reference frames | ||
| 99 | writer.WriteBit(false); | 100 | writer.WriteBit(false); |
| 100 | writer.WriteUe(context.h264_parameter_set.pic_width_in_mbs - 1); | 101 | writer.WriteUe(context.h264_parameter_set.pic_width_in_mbs - 1); |
| 101 | writer.WriteUe(pic_height - 1); | 102 | writer.WriteUe(pic_height - 1); |
diff --git a/src/video_core/video_core.cpp b/src/video_core/video_core.cpp index 3b575db4d..cae543a51 100644 --- a/src/video_core/video_core.cpp +++ b/src/video_core/video_core.cpp | |||
| @@ -37,7 +37,8 @@ std::unique_ptr<VideoCore::RendererBase> CreateRenderer( | |||
| 37 | namespace VideoCore { | 37 | namespace VideoCore { |
| 38 | 38 | ||
| 39 | std::unique_ptr<Tegra::GPU> CreateGPU(Core::Frontend::EmuWindow& emu_window, Core::System& system) { | 39 | std::unique_ptr<Tegra::GPU> CreateGPU(Core::Frontend::EmuWindow& emu_window, Core::System& system) { |
| 40 | const bool use_nvdec = Settings::values.use_nvdec_emulation.GetValue(); | 40 | const auto nvdec_value = Settings::values.nvdec_emulation.GetValue(); |
| 41 | const bool use_nvdec = nvdec_value != Settings::NvdecEmulation::Off; | ||
| 41 | const bool use_async = Settings::values.use_asynchronous_gpu_emulation.GetValue(); | 42 | const bool use_async = Settings::values.use_asynchronous_gpu_emulation.GetValue(); |
| 42 | auto gpu = std::make_unique<Tegra::GPU>(system, use_async, use_nvdec); | 43 | auto gpu = std::make_unique<Tegra::GPU>(system, use_async, use_nvdec); |
| 43 | auto context = emu_window.CreateSharedContext(); | 44 | auto context = emu_window.CreateSharedContext(); |
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 85d292bcc..8744d8e5d 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp | |||
| @@ -812,7 +812,7 @@ void Config::ReadRendererValues() { | |||
| 812 | ReadGlobalSetting(Settings::values.use_disk_shader_cache); | 812 | ReadGlobalSetting(Settings::values.use_disk_shader_cache); |
| 813 | ReadGlobalSetting(Settings::values.gpu_accuracy); | 813 | ReadGlobalSetting(Settings::values.gpu_accuracy); |
| 814 | ReadGlobalSetting(Settings::values.use_asynchronous_gpu_emulation); | 814 | ReadGlobalSetting(Settings::values.use_asynchronous_gpu_emulation); |
| 815 | ReadGlobalSetting(Settings::values.use_nvdec_emulation); | 815 | ReadGlobalSetting(Settings::values.nvdec_emulation); |
| 816 | ReadGlobalSetting(Settings::values.accelerate_astc); | 816 | ReadGlobalSetting(Settings::values.accelerate_astc); |
| 817 | ReadGlobalSetting(Settings::values.use_vsync); | 817 | ReadGlobalSetting(Settings::values.use_vsync); |
| 818 | ReadGlobalSetting(Settings::values.shader_backend); | 818 | ReadGlobalSetting(Settings::values.shader_backend); |
| @@ -1349,7 +1349,10 @@ void Config::SaveRendererValues() { | |||
| 1349 | static_cast<u32>(Settings::values.gpu_accuracy.GetDefault()), | 1349 | static_cast<u32>(Settings::values.gpu_accuracy.GetDefault()), |
| 1350 | Settings::values.gpu_accuracy.UsingGlobal()); | 1350 | Settings::values.gpu_accuracy.UsingGlobal()); |
| 1351 | WriteGlobalSetting(Settings::values.use_asynchronous_gpu_emulation); | 1351 | WriteGlobalSetting(Settings::values.use_asynchronous_gpu_emulation); |
| 1352 | WriteGlobalSetting(Settings::values.use_nvdec_emulation); | 1352 | WriteSetting(QString::fromStdString(Settings::values.nvdec_emulation.GetLabel()), |
| 1353 | static_cast<u32>(Settings::values.nvdec_emulation.GetValue(global)), | ||
| 1354 | static_cast<u32>(Settings::values.nvdec_emulation.GetDefault()), | ||
| 1355 | Settings::values.nvdec_emulation.UsingGlobal()); | ||
| 1353 | WriteGlobalSetting(Settings::values.accelerate_astc); | 1356 | WriteGlobalSetting(Settings::values.accelerate_astc); |
| 1354 | WriteGlobalSetting(Settings::values.use_vsync); | 1357 | WriteGlobalSetting(Settings::values.use_vsync); |
| 1355 | WriteSetting(QString::fromStdString(Settings::values.shader_backend.GetLabel()), | 1358 | WriteSetting(QString::fromStdString(Settings::values.shader_backend.GetLabel()), |
diff --git a/src/yuzu/configuration/config.h b/src/yuzu/configuration/config.h index 9555f4498..4733227b6 100644 --- a/src/yuzu/configuration/config.h +++ b/src/yuzu/configuration/config.h | |||
| @@ -182,5 +182,6 @@ private: | |||
| 182 | Q_DECLARE_METATYPE(Settings::CPUAccuracy); | 182 | Q_DECLARE_METATYPE(Settings::CPUAccuracy); |
| 183 | Q_DECLARE_METATYPE(Settings::GPUAccuracy); | 183 | Q_DECLARE_METATYPE(Settings::GPUAccuracy); |
| 184 | Q_DECLARE_METATYPE(Settings::FullscreenMode); | 184 | Q_DECLARE_METATYPE(Settings::FullscreenMode); |
| 185 | Q_DECLARE_METATYPE(Settings::NvdecEmulation); | ||
| 185 | Q_DECLARE_METATYPE(Settings::RendererBackend); | 186 | Q_DECLARE_METATYPE(Settings::RendererBackend); |
| 186 | Q_DECLARE_METATYPE(Settings::ShaderBackend); | 187 | Q_DECLARE_METATYPE(Settings::ShaderBackend); |
diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp index 37e896258..c594164be 100644 --- a/src/yuzu/configuration/configure_graphics.cpp +++ b/src/yuzu/configuration/configure_graphics.cpp | |||
| @@ -88,24 +88,30 @@ void ConfigureGraphics::SetConfiguration() { | |||
| 88 | ui->api_widget->setEnabled(runtime_lock); | 88 | ui->api_widget->setEnabled(runtime_lock); |
| 89 | ui->use_asynchronous_gpu_emulation->setEnabled(runtime_lock); | 89 | ui->use_asynchronous_gpu_emulation->setEnabled(runtime_lock); |
| 90 | ui->use_disk_shader_cache->setEnabled(runtime_lock); | 90 | ui->use_disk_shader_cache->setEnabled(runtime_lock); |
| 91 | ui->use_nvdec_emulation->setEnabled(runtime_lock); | 91 | ui->nvdec_emulation_widget->setEnabled(runtime_lock); |
| 92 | ui->accelerate_astc->setEnabled(runtime_lock); | 92 | ui->accelerate_astc->setEnabled(runtime_lock); |
| 93 | ui->use_disk_shader_cache->setChecked(Settings::values.use_disk_shader_cache.GetValue()); | 93 | ui->use_disk_shader_cache->setChecked(Settings::values.use_disk_shader_cache.GetValue()); |
| 94 | ui->use_asynchronous_gpu_emulation->setChecked( | 94 | ui->use_asynchronous_gpu_emulation->setChecked( |
| 95 | Settings::values.use_asynchronous_gpu_emulation.GetValue()); | 95 | Settings::values.use_asynchronous_gpu_emulation.GetValue()); |
| 96 | ui->use_nvdec_emulation->setChecked(Settings::values.use_nvdec_emulation.GetValue()); | ||
| 97 | ui->accelerate_astc->setChecked(Settings::values.accelerate_astc.GetValue()); | 96 | ui->accelerate_astc->setChecked(Settings::values.accelerate_astc.GetValue()); |
| 98 | 97 | ||
| 99 | if (Settings::IsConfiguringGlobal()) { | 98 | if (Settings::IsConfiguringGlobal()) { |
| 100 | ui->api->setCurrentIndex(static_cast<int>(Settings::values.renderer_backend.GetValue())); | 99 | ui->api->setCurrentIndex(static_cast<int>(Settings::values.renderer_backend.GetValue())); |
| 101 | ui->fullscreen_mode_combobox->setCurrentIndex( | 100 | ui->fullscreen_mode_combobox->setCurrentIndex( |
| 102 | static_cast<int>(Settings::values.fullscreen_mode.GetValue())); | 101 | static_cast<int>(Settings::values.fullscreen_mode.GetValue())); |
| 102 | ui->nvdec_emulation->setCurrentIndex( | ||
| 103 | static_cast<int>(Settings::values.nvdec_emulation.GetValue())); | ||
| 103 | ui->aspect_ratio_combobox->setCurrentIndex(Settings::values.aspect_ratio.GetValue()); | 104 | ui->aspect_ratio_combobox->setCurrentIndex(Settings::values.aspect_ratio.GetValue()); |
| 104 | } else { | 105 | } else { |
| 105 | ConfigurationShared::SetPerGameSetting(ui->api, &Settings::values.renderer_backend); | 106 | ConfigurationShared::SetPerGameSetting(ui->api, &Settings::values.renderer_backend); |
| 106 | ConfigurationShared::SetHighlight(ui->api_widget, | 107 | ConfigurationShared::SetHighlight(ui->api_widget, |
| 107 | !Settings::values.renderer_backend.UsingGlobal()); | 108 | !Settings::values.renderer_backend.UsingGlobal()); |
| 108 | 109 | ||
| 110 | ConfigurationShared::SetPerGameSetting(ui->nvdec_emulation, | ||
| 111 | &Settings::values.nvdec_emulation); | ||
| 112 | ConfigurationShared::SetHighlight(ui->nvdec_emulation_widget, | ||
| 113 | !Settings::values.nvdec_emulation.UsingGlobal()); | ||
| 114 | |||
| 109 | ConfigurationShared::SetPerGameSetting(ui->fullscreen_mode_combobox, | 115 | ConfigurationShared::SetPerGameSetting(ui->fullscreen_mode_combobox, |
| 110 | &Settings::values.fullscreen_mode); | 116 | &Settings::values.fullscreen_mode); |
| 111 | ConfigurationShared::SetHighlight(ui->fullscreen_mode_label, | 117 | ConfigurationShared::SetHighlight(ui->fullscreen_mode_label, |
| @@ -137,8 +143,6 @@ void ConfigureGraphics::ApplyConfiguration() { | |||
| 137 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_asynchronous_gpu_emulation, | 143 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_asynchronous_gpu_emulation, |
| 138 | ui->use_asynchronous_gpu_emulation, | 144 | ui->use_asynchronous_gpu_emulation, |
| 139 | use_asynchronous_gpu_emulation); | 145 | use_asynchronous_gpu_emulation); |
| 140 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_nvdec_emulation, | ||
| 141 | ui->use_nvdec_emulation, use_nvdec_emulation); | ||
| 142 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.accelerate_astc, ui->accelerate_astc, | 146 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.accelerate_astc, ui->accelerate_astc, |
| 143 | accelerate_astc); | 147 | accelerate_astc); |
| 144 | 148 | ||
| @@ -147,6 +151,9 @@ void ConfigureGraphics::ApplyConfiguration() { | |||
| 147 | if (Settings::values.renderer_backend.UsingGlobal()) { | 151 | if (Settings::values.renderer_backend.UsingGlobal()) { |
| 148 | Settings::values.renderer_backend.SetValue(GetCurrentGraphicsBackend()); | 152 | Settings::values.renderer_backend.SetValue(GetCurrentGraphicsBackend()); |
| 149 | } | 153 | } |
| 154 | if (Settings::values.nvdec_emulation.UsingGlobal()) { | ||
| 155 | Settings::values.nvdec_emulation.SetValue(GetCurrentNvdecEmulation()); | ||
| 156 | } | ||
| 150 | if (Settings::values.shader_backend.UsingGlobal()) { | 157 | if (Settings::values.shader_backend.UsingGlobal()) { |
| 151 | Settings::values.shader_backend.SetValue(shader_backend); | 158 | Settings::values.shader_backend.SetValue(shader_backend); |
| 152 | } | 159 | } |
| @@ -180,6 +187,13 @@ void ConfigureGraphics::ApplyConfiguration() { | |||
| 180 | } | 187 | } |
| 181 | } | 188 | } |
| 182 | 189 | ||
| 190 | if (ui->nvdec_emulation->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { | ||
| 191 | Settings::values.nvdec_emulation.SetGlobal(true); | ||
| 192 | } else { | ||
| 193 | Settings::values.nvdec_emulation.SetGlobal(false); | ||
| 194 | Settings::values.nvdec_emulation.SetValue(GetCurrentNvdecEmulation()); | ||
| 195 | } | ||
| 196 | |||
| 183 | if (ui->bg_combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { | 197 | if (ui->bg_combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { |
| 184 | Settings::values.bg_red.SetGlobal(true); | 198 | Settings::values.bg_red.SetGlobal(true); |
| 185 | Settings::values.bg_green.SetGlobal(true); | 199 | Settings::values.bg_green.SetGlobal(true); |
| @@ -278,6 +292,20 @@ Settings::RendererBackend ConfigureGraphics::GetCurrentGraphicsBackend() const { | |||
| 278 | ConfigurationShared::USE_GLOBAL_OFFSET); | 292 | ConfigurationShared::USE_GLOBAL_OFFSET); |
| 279 | } | 293 | } |
| 280 | 294 | ||
| 295 | Settings::NvdecEmulation ConfigureGraphics::GetCurrentNvdecEmulation() const { | ||
| 296 | if (Settings::IsConfiguringGlobal()) { | ||
| 297 | return static_cast<Settings::NvdecEmulation>(ui->nvdec_emulation->currentIndex()); | ||
| 298 | } | ||
| 299 | |||
| 300 | if (ui->nvdec_emulation->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { | ||
| 301 | Settings::values.nvdec_emulation.SetGlobal(true); | ||
| 302 | return Settings::values.nvdec_emulation.GetValue(); | ||
| 303 | } | ||
| 304 | Settings::values.nvdec_emulation.SetGlobal(false); | ||
| 305 | return static_cast<Settings::NvdecEmulation>(ui->nvdec_emulation->currentIndex() - | ||
| 306 | ConfigurationShared::USE_GLOBAL_OFFSET); | ||
| 307 | } | ||
| 308 | |||
| 281 | void ConfigureGraphics::SetupPerGameUI() { | 309 | void ConfigureGraphics::SetupPerGameUI() { |
| 282 | if (Settings::IsConfiguringGlobal()) { | 310 | if (Settings::IsConfiguringGlobal()) { |
| 283 | ui->api->setEnabled(Settings::values.renderer_backend.UsingGlobal()); | 311 | ui->api->setEnabled(Settings::values.renderer_backend.UsingGlobal()); |
| @@ -286,7 +314,7 @@ void ConfigureGraphics::SetupPerGameUI() { | |||
| 286 | ui->aspect_ratio_combobox->setEnabled(Settings::values.aspect_ratio.UsingGlobal()); | 314 | ui->aspect_ratio_combobox->setEnabled(Settings::values.aspect_ratio.UsingGlobal()); |
| 287 | ui->use_asynchronous_gpu_emulation->setEnabled( | 315 | ui->use_asynchronous_gpu_emulation->setEnabled( |
| 288 | Settings::values.use_asynchronous_gpu_emulation.UsingGlobal()); | 316 | Settings::values.use_asynchronous_gpu_emulation.UsingGlobal()); |
| 289 | ui->use_nvdec_emulation->setEnabled(Settings::values.use_nvdec_emulation.UsingGlobal()); | 317 | ui->nvdec_emulation->setEnabled(Settings::values.nvdec_emulation.UsingGlobal()); |
| 290 | ui->accelerate_astc->setEnabled(Settings::values.accelerate_astc.UsingGlobal()); | 318 | ui->accelerate_astc->setEnabled(Settings::values.accelerate_astc.UsingGlobal()); |
| 291 | ui->use_disk_shader_cache->setEnabled(Settings::values.use_disk_shader_cache.UsingGlobal()); | 319 | ui->use_disk_shader_cache->setEnabled(Settings::values.use_disk_shader_cache.UsingGlobal()); |
| 292 | ui->bg_button->setEnabled(Settings::values.bg_red.UsingGlobal()); | 320 | ui->bg_button->setEnabled(Settings::values.bg_red.UsingGlobal()); |
| @@ -301,8 +329,6 @@ void ConfigureGraphics::SetupPerGameUI() { | |||
| 301 | 329 | ||
| 302 | ConfigurationShared::SetColoredTristate( | 330 | ConfigurationShared::SetColoredTristate( |
| 303 | ui->use_disk_shader_cache, Settings::values.use_disk_shader_cache, use_disk_shader_cache); | 331 | ui->use_disk_shader_cache, Settings::values.use_disk_shader_cache, use_disk_shader_cache); |
| 304 | ConfigurationShared::SetColoredTristate( | ||
| 305 | ui->use_nvdec_emulation, Settings::values.use_nvdec_emulation, use_nvdec_emulation); | ||
| 306 | ConfigurationShared::SetColoredTristate(ui->accelerate_astc, Settings::values.accelerate_astc, | 332 | ConfigurationShared::SetColoredTristate(ui->accelerate_astc, Settings::values.accelerate_astc, |
| 307 | accelerate_astc); | 333 | accelerate_astc); |
| 308 | ConfigurationShared::SetColoredTristate(ui->use_asynchronous_gpu_emulation, | 334 | ConfigurationShared::SetColoredTristate(ui->use_asynchronous_gpu_emulation, |
| @@ -316,4 +342,6 @@ void ConfigureGraphics::SetupPerGameUI() { | |||
| 316 | static_cast<int>(Settings::values.fullscreen_mode.GetValue(true))); | 342 | static_cast<int>(Settings::values.fullscreen_mode.GetValue(true))); |
| 317 | ConfigurationShared::InsertGlobalItem( | 343 | ConfigurationShared::InsertGlobalItem( |
| 318 | ui->api, static_cast<int>(Settings::values.renderer_backend.GetValue(true))); | 344 | ui->api, static_cast<int>(Settings::values.renderer_backend.GetValue(true))); |
| 345 | ConfigurationShared::InsertGlobalItem( | ||
| 346 | ui->nvdec_emulation, static_cast<int>(Settings::values.nvdec_emulation.GetValue(true))); | ||
| 319 | } | 347 | } |
diff --git a/src/yuzu/configuration/configure_graphics.h b/src/yuzu/configuration/configure_graphics.h index c866b911b..7d7ac329d 100644 --- a/src/yuzu/configuration/configure_graphics.h +++ b/src/yuzu/configuration/configure_graphics.h | |||
| @@ -43,6 +43,7 @@ private: | |||
| 43 | void SetupPerGameUI(); | 43 | void SetupPerGameUI(); |
| 44 | 44 | ||
| 45 | Settings::RendererBackend GetCurrentGraphicsBackend() const; | 45 | Settings::RendererBackend GetCurrentGraphicsBackend() const; |
| 46 | Settings::NvdecEmulation GetCurrentNvdecEmulation() const; | ||
| 46 | 47 | ||
| 47 | std::unique_ptr<Ui::ConfigureGraphics> ui; | 48 | std::unique_ptr<Ui::ConfigureGraphics> ui; |
| 48 | QColor bg_color; | 49 | QColor bg_color; |
diff --git a/src/yuzu/configuration/configure_graphics.ui b/src/yuzu/configuration/configure_graphics.ui index 43f1887d1..1a12cfa4d 100644 --- a/src/yuzu/configuration/configure_graphics.ui +++ b/src/yuzu/configuration/configure_graphics.ui | |||
| @@ -168,13 +168,6 @@ | |||
| 168 | </widget> | 168 | </widget> |
| 169 | </item> | 169 | </item> |
| 170 | <item> | 170 | <item> |
| 171 | <widget class="QCheckBox" name="use_nvdec_emulation"> | ||
| 172 | <property name="text"> | ||
| 173 | <string>Use NVDEC emulation</string> | ||
| 174 | </property> | ||
| 175 | </widget> | ||
| 176 | </item> | ||
| 177 | <item> | ||
| 178 | <widget class="QCheckBox" name="accelerate_astc"> | 171 | <widget class="QCheckBox" name="accelerate_astc"> |
| 179 | <property name="text"> | 172 | <property name="text"> |
| 180 | <string>Accelerate ASTC texture decoding</string> | 173 | <string>Accelerate ASTC texture decoding</string> |
| @@ -182,6 +175,50 @@ | |||
| 182 | </widget> | 175 | </widget> |
| 183 | </item> | 176 | </item> |
| 184 | <item> | 177 | <item> |
| 178 | <widget class="QWidget" name="nvdec_emulation_widget" native="true"> | ||
| 179 | <layout class="QHBoxLayout" name="nvdec_emulation_layout"> | ||
| 180 | <property name="leftMargin"> | ||
| 181 | <number>0</number> | ||
| 182 | </property> | ||
| 183 | <property name="topMargin"> | ||
| 184 | <number>0</number> | ||
| 185 | </property> | ||
| 186 | <property name="rightMargin"> | ||
| 187 | <number>0</number> | ||
| 188 | </property> | ||
| 189 | <property name="bottomMargin"> | ||
| 190 | <number>0</number> | ||
| 191 | </property> | ||
| 192 | <item> | ||
| 193 | <widget class="QLabel" name="nvdec_emulation_label"> | ||
| 194 | <property name="text"> | ||
| 195 | <string>NVDEC emulation:</string> | ||
| 196 | </property> | ||
| 197 | </widget> | ||
| 198 | </item> | ||
| 199 | <item> | ||
| 200 | <widget class="QComboBox" name="nvdec_emulation"> | ||
| 201 | <item> | ||
| 202 | <property name="text"> | ||
| 203 | <string>Disabled</string> | ||
| 204 | </property> | ||
| 205 | </item> | ||
| 206 | <item> | ||
| 207 | <property name="text"> | ||
| 208 | <string>CPU Decoding</string> | ||
| 209 | </property> | ||
| 210 | </item> | ||
| 211 | <item> | ||
| 212 | <property name="text"> | ||
| 213 | <string>GPU Decoding</string> | ||
| 214 | </property> | ||
| 215 | </item> | ||
| 216 | </widget> | ||
| 217 | </item> | ||
| 218 | </layout> | ||
| 219 | </widget> | ||
| 220 | </item> | ||
| 221 | <item> | ||
| 185 | <widget class="QWidget" name="fullscreen_mode_layout" native="true"> | 222 | <widget class="QWidget" name="fullscreen_mode_layout" native="true"> |
| 186 | <layout class="QHBoxLayout" name="horizontalLayout_1"> | 223 | <layout class="QHBoxLayout" name="horizontalLayout_1"> |
| 187 | <property name="leftMargin"> | 224 | <property name="leftMargin"> |
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp index 757dd1ea0..891f7be6f 100644 --- a/src/yuzu_cmd/config.cpp +++ b/src/yuzu_cmd/config.cpp | |||
| @@ -465,7 +465,7 @@ void Config::ReadValues() { | |||
| 465 | ReadSetting("Renderer", Settings::values.disable_fps_limit); | 465 | ReadSetting("Renderer", Settings::values.disable_fps_limit); |
| 466 | ReadSetting("Renderer", Settings::values.shader_backend); | 466 | ReadSetting("Renderer", Settings::values.shader_backend); |
| 467 | ReadSetting("Renderer", Settings::values.use_asynchronous_shaders); | 467 | ReadSetting("Renderer", Settings::values.use_asynchronous_shaders); |
| 468 | ReadSetting("Renderer", Settings::values.use_nvdec_emulation); | 468 | ReadSetting("Renderer", Settings::values.nvdec_emulation); |
| 469 | ReadSetting("Renderer", Settings::values.accelerate_astc); | 469 | ReadSetting("Renderer", Settings::values.accelerate_astc); |
| 470 | ReadSetting("Renderer", Settings::values.use_fast_gpu_time); | 470 | ReadSetting("Renderer", Settings::values.use_fast_gpu_time); |
| 471 | 471 | ||
diff --git a/src/yuzu_cmd/default_ini.h b/src/yuzu_cmd/default_ini.h index e02eceb99..72f3213fb 100644 --- a/src/yuzu_cmd/default_ini.h +++ b/src/yuzu_cmd/default_ini.h | |||
| @@ -261,9 +261,9 @@ shader_backend = | |||
| 261 | # 0 (default): Off, 1: On | 261 | # 0 (default): Off, 1: On |
| 262 | use_asynchronous_shaders = | 262 | use_asynchronous_shaders = |
| 263 | 263 | ||
| 264 | # Enable NVDEC emulation. | 264 | # NVDEC emulation. |
| 265 | # 0: Off, 1 (default): On | 265 | # 0: Disabled, 1: CPU Decoding, 2 (default): GPU Decoding |
| 266 | use_nvdec_emulation = | 266 | nvdec_emulation = |
| 267 | 267 | ||
| 268 | # Accelerate ASTC texture decoding. | 268 | # Accelerate ASTC texture decoding. |
| 269 | # 0: Off, 1 (default): On | 269 | # 0: Off, 1 (default): On |