mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	renderer_vulkan: Add vulkan initialization code (#6620)
* common: Move dynamic library to common * This is so that video_core can use it * logging: Add vulkan log target * common: Allow defered library loading * Also add some comments to the functions * renderer_vulkan: Add vulkan initialization code * renderer_vulkan: Address feedback
This commit is contained in:
		
							parent
							
								
									70225e92f7
								
							
						
					
					
						commit
						d735f5c458
					
				
					 18 changed files with 1576 additions and 54 deletions
				
			
		|  | @ -10,29 +10,11 @@ | |||
| #endif | ||||
| #include "dynamic_library.h" | ||||
| 
 | ||||
| namespace DynamicLibrary { | ||||
| namespace Common { | ||||
| 
 | ||||
| DynamicLibrary::DynamicLibrary(std::string_view name, int major, int minor) { | ||||
|     auto full_name = GetLibraryName(name, major, minor); | ||||
| #if defined(_WIN32) | ||||
|     handle = reinterpret_cast<void*>(LoadLibraryA(full_name.c_str())); | ||||
|     if (!handle) { | ||||
|         DWORD error_message_id = GetLastError(); | ||||
|         LPSTR message_buffer = nullptr; | ||||
|         size_t size = | ||||
|             FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | | ||||
|                                FORMAT_MESSAGE_IGNORE_INSERTS, | ||||
|                            nullptr, error_message_id, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), | ||||
|                            reinterpret_cast<LPSTR>(&message_buffer), 0, nullptr); | ||||
|         std::string message(message_buffer, size); | ||||
|         load_error = message; | ||||
|     } | ||||
| #else | ||||
|     handle = dlopen(full_name.c_str(), RTLD_LAZY); | ||||
|     if (!handle) { | ||||
|         load_error = dlerror(); | ||||
|     } | ||||
| #endif // defined(_WIN32)
 | ||||
|     void(Load(full_name)); | ||||
| } | ||||
| 
 | ||||
| DynamicLibrary::~DynamicLibrary() { | ||||
|  | @ -46,7 +28,32 @@ DynamicLibrary::~DynamicLibrary() { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| void* DynamicLibrary::GetRawSymbol(std::string_view name) { | ||||
| bool DynamicLibrary::Load(std::string_view filename) { | ||||
| #if defined(_WIN32) | ||||
|     handle = reinterpret_cast<void*>(LoadLibraryA(filename.data())); | ||||
|     if (!handle) { | ||||
|         DWORD error_message_id = GetLastError(); | ||||
|         LPSTR message_buffer = nullptr; | ||||
|         size_t size = | ||||
|             FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | | ||||
|                                FORMAT_MESSAGE_IGNORE_INSERTS, | ||||
|                            nullptr, error_message_id, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), | ||||
|                            reinterpret_cast<LPSTR>(&message_buffer), 0, nullptr); | ||||
|         std::string message(message_buffer, size); | ||||
|         load_error = message; | ||||
|         return false; | ||||
|     } | ||||
| #else | ||||
|     handle = dlopen(filename.data(), RTLD_LAZY); | ||||
|     if (!handle) { | ||||
|         load_error = dlerror(); | ||||
|         return false; | ||||
|     } | ||||
| #endif // defined(_WIN32)
 | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| void* DynamicLibrary::GetRawSymbol(std::string_view name) const { | ||||
| #if defined(_WIN32) | ||||
|     return reinterpret_cast<void*>(GetProcAddress(reinterpret_cast<HMODULE>(handle), name.data())); | ||||
| #else | ||||
|  | @ -84,4 +91,4 @@ std::string DynamicLibrary::GetLibraryName(std::string_view name, int major, int | |||
| #endif | ||||
| } | ||||
| 
 | ||||
| } // namespace DynamicLibrary
 | ||||
| } // namespace Common
 | ||||
|  |  | |||
|  | @ -5,35 +5,46 @@ | |||
| #pragma once | ||||
| 
 | ||||
| #include <string> | ||||
| #include "common/common_types.h" | ||||
| 
 | ||||
| namespace DynamicLibrary { | ||||
| namespace Common { | ||||
| 
 | ||||
| class DynamicLibrary { | ||||
| public: | ||||
|     explicit DynamicLibrary(); | ||||
|     explicit DynamicLibrary(std::string_view name, int major = -1, int minor = -1); | ||||
|     ~DynamicLibrary(); | ||||
| 
 | ||||
|     bool IsLoaded() { | ||||
|     /// Returns true if the library is loaded, otherwise false.
 | ||||
|     [[nodiscard]] bool IsLoaded() { | ||||
|         return handle != nullptr; | ||||
|     } | ||||
| 
 | ||||
|     std::string_view GetLoadError() { | ||||
|     /// Loads (or replaces) the handle with the specified library file name.
 | ||||
|     /// Returns true if the library was loaded and can be used.
 | ||||
|     [[nodiscard]] bool Load(std::string_view filename); | ||||
| 
 | ||||
|     /// Returns a string containing the last generated load error, if it occured.
 | ||||
|     [[nodiscard]] std::string_view GetLoadError() const { | ||||
|         return load_error; | ||||
|     } | ||||
| 
 | ||||
|     /// Obtains the address of the specified symbol, automatically casting to the correct type.
 | ||||
|     template <typename T> | ||||
|     T GetSymbol(std::string_view name) { | ||||
|     [[nodiscard]] T GetSymbol(std::string_view name) const { | ||||
|         return reinterpret_cast<T>(GetRawSymbol(name)); | ||||
|     } | ||||
| 
 | ||||
|     static std::string GetLibraryName(std::string_view name, int major = -1, int minor = -1); | ||||
|     /// Returns the specified library name in platform-specific format.
 | ||||
|     /// Major/minor versions will not be included if set to -1.
 | ||||
|     /// If libname already contains the "lib" prefix, it will not be added again.
 | ||||
|     [[nodiscard]] static std::string GetLibraryName(std::string_view name, int major = -1, | ||||
|                                                     int minor = -1); | ||||
| 
 | ||||
| private: | ||||
|     void* GetRawSymbol(std::string_view name); | ||||
|     void* GetRawSymbol(std::string_view name) const; | ||||
| 
 | ||||
|     void* handle; | ||||
|     std::string load_error; | ||||
| }; | ||||
| 
 | ||||
| } // namespace DynamicLibrary
 | ||||
| } // namespace Common
 | ||||
|  |  | |||
|  | @ -2,6 +2,7 @@ | |||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include "common/dynamic_library/dynamic_library.h" | ||||
| #include "common/dynamic_library/fdk-aac.h" | ||||
| #include "common/logging/log.h" | ||||
| 
 | ||||
|  | @ -15,7 +16,7 @@ aacDecoder_GetStreamInfo_func aacDecoder_GetStreamInfo; | |||
| aacDecoder_DecodeFrame_func aacDecoder_DecodeFrame; | ||||
| aacDecoder_Fill_func aacDecoder_Fill; | ||||
| 
 | ||||
| static std::unique_ptr<DynamicLibrary> fdk_aac; | ||||
| static std::unique_ptr<Common::DynamicLibrary> fdk_aac; | ||||
| 
 | ||||
| #define LOAD_SYMBOL(library, name)                                                                 \ | ||||
|     any_failed = any_failed || (name = library->GetSymbol<name##_func>(#name)) == nullptr | ||||
|  | @ -25,7 +26,7 @@ bool LoadFdkAac() { | |||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     fdk_aac = std::make_unique<DynamicLibrary>("fdk-aac", 2); | ||||
|     fdk_aac = std::make_unique<Common::DynamicLibrary>("fdk-aac", 2); | ||||
|     if (!fdk_aac->IsLoaded()) { | ||||
|         LOG_WARNING(Common, "Could not dynamically load libfdk-aac: {}", fdk_aac->GetLoadError()); | ||||
|         fdk_aac.reset(); | ||||
|  |  | |||
|  | @ -8,9 +8,6 @@ extern "C" { | |||
| #include <fdk-aac/aacdecoder_lib.h> | ||||
| } | ||||
| 
 | ||||
| #include "common/common_types.h" | ||||
| #include "common/dynamic_library/dynamic_library.h" | ||||
| 
 | ||||
| namespace DynamicLibrary::FdkAac { | ||||
| 
 | ||||
| typedef INT (*aacDecoder_GetLibInfo_func)(LIB_INFO* info); | ||||
|  |  | |||
|  | @ -2,6 +2,7 @@ | |||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include "common/dynamic_library/dynamic_library.h" | ||||
| #include "common/dynamic_library/ffmpeg.h" | ||||
| #include "common/logging/log.h" | ||||
| 
 | ||||
|  | @ -110,11 +111,11 @@ swr_free_func swr_free; | |||
| swr_init_func swr_init; | ||||
| swresample_version_func swresample_version; | ||||
| 
 | ||||
| static std::unique_ptr<DynamicLibrary> avutil; | ||||
| static std::unique_ptr<DynamicLibrary> avcodec; | ||||
| static std::unique_ptr<DynamicLibrary> avfilter; | ||||
| static std::unique_ptr<DynamicLibrary> avformat; | ||||
| static std::unique_ptr<DynamicLibrary> swresample; | ||||
| static std::unique_ptr<Common::DynamicLibrary> avutil; | ||||
| static std::unique_ptr<Common::DynamicLibrary> avcodec; | ||||
| static std::unique_ptr<Common::DynamicLibrary> avfilter; | ||||
| static std::unique_ptr<Common::DynamicLibrary> avformat; | ||||
| static std::unique_ptr<Common::DynamicLibrary> swresample; | ||||
| 
 | ||||
| #define LOAD_SYMBOL(library, name)                                                                 \ | ||||
|     any_failed = any_failed || (name = library->GetSymbol<name##_func>(#name)) == nullptr | ||||
|  | @ -124,7 +125,7 @@ static bool LoadAVUtil() { | |||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     avutil = std::make_unique<DynamicLibrary>("avutil", LIBAVUTIL_VERSION_MAJOR); | ||||
|     avutil = std::make_unique<Common::DynamicLibrary>("avutil", LIBAVUTIL_VERSION_MAJOR); | ||||
|     if (!avutil->IsLoaded()) { | ||||
|         LOG_WARNING(Common, "Could not dynamically load libavutil: {}", avutil->GetLoadError()); | ||||
|         avutil.reset(); | ||||
|  | @ -194,7 +195,7 @@ static bool LoadAVCodec() { | |||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     avcodec = std::make_unique<DynamicLibrary>("avcodec", LIBAVCODEC_VERSION_MAJOR); | ||||
|     avcodec = std::make_unique<Common::DynamicLibrary>("avcodec", LIBAVCODEC_VERSION_MAJOR); | ||||
|     if (!avcodec->IsLoaded()) { | ||||
|         LOG_WARNING(Common, "Could not dynamically load libavcodec: {}", avcodec->GetLoadError()); | ||||
|         avcodec.reset(); | ||||
|  | @ -251,7 +252,7 @@ static bool LoadAVFilter() { | |||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     avfilter = std::make_unique<DynamicLibrary>("avfilter", LIBAVFILTER_VERSION_MAJOR); | ||||
|     avfilter = std::make_unique<Common::DynamicLibrary>("avfilter", LIBAVFILTER_VERSION_MAJOR); | ||||
|     if (!avfilter->IsLoaded()) { | ||||
|         LOG_WARNING(Common, "Could not dynamically load libavfilter: {}", avfilter->GetLoadError()); | ||||
|         avfilter.reset(); | ||||
|  | @ -296,7 +297,7 @@ static bool LoadAVFormat() { | |||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     avformat = std::make_unique<DynamicLibrary>("avformat", LIBAVFORMAT_VERSION_MAJOR); | ||||
|     avformat = std::make_unique<Common::DynamicLibrary>("avformat", LIBAVFORMAT_VERSION_MAJOR); | ||||
|     if (!avformat->IsLoaded()) { | ||||
|         LOG_WARNING(Common, "Could not dynamically load libavformat: {}", avformat->GetLoadError()); | ||||
|         avformat.reset(); | ||||
|  | @ -344,7 +345,8 @@ static bool LoadSWResample() { | |||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     swresample = std::make_unique<DynamicLibrary>("swresample", LIBSWRESAMPLE_VERSION_MAJOR); | ||||
|     swresample = | ||||
|         std::make_unique<Common::DynamicLibrary>("swresample", LIBSWRESAMPLE_VERSION_MAJOR); | ||||
|     if (!swresample->IsLoaded()) { | ||||
|         LOG_WARNING(Common, "Could not dynamically load libswresample: {}", | ||||
|                     swresample->GetLoadError()); | ||||
|  |  | |||
|  | @ -15,9 +15,6 @@ extern "C" { | |||
| #include <libswresample/swresample.h> | ||||
| } | ||||
| 
 | ||||
| #include "common/common_types.h" | ||||
| #include "common/dynamic_library/dynamic_library.h" | ||||
| 
 | ||||
| namespace DynamicLibrary::FFmpeg { | ||||
| 
 | ||||
| // avutil
 | ||||
|  |  | |||
|  | @ -234,6 +234,7 @@ void DebuggerBackend::Write(const Entry& entry) { | |||
|     CLS(Render)                                                                                    \ | ||||
|     SUB(Render, Software)                                                                          \ | ||||
|     SUB(Render, OpenGL)                                                                            \ | ||||
|     SUB(Render, Vulkan)                                                                            \ | ||||
|     CLS(Audio)                                                                                     \ | ||||
|     SUB(Audio, DSP)                                                                                \ | ||||
|     SUB(Audio, Sink)                                                                               \ | ||||
|  |  | |||
|  | @ -8,6 +8,7 @@ | |||
| #include <array> | ||||
| #include "common/common_types.h" | ||||
| #include "common/logging/formatter.h" | ||||
| 
 | ||||
| namespace Log { | ||||
| 
 | ||||
| // trims up to and including the last of ../, ..\, src/, src\ in a string
 | ||||
|  | @ -103,6 +104,7 @@ enum class Class : ClassType { | |||
|     Render,            ///< Emulator video output and hardware acceleration
 | ||||
|     Render_Software,   ///< Software renderer backend
 | ||||
|     Render_OpenGL,     ///< OpenGL backend
 | ||||
|     Render_Vulkan,     ///< Vulkan backend
 | ||||
|     Audio,             ///< Audio emulation
 | ||||
|     Audio_DSP,         ///< The HLE and LLE implementations of the DSP
 | ||||
|     Audio_Sink,        ///< Emulator audio output backend
 | ||||
|  |  | |||
|  | @ -432,6 +432,7 @@ struct Values { | |||
|         "graphics_api"}; | ||||
|     Setting<bool> use_gles{false, "use_gles"}; | ||||
|     Setting<bool> renderer_debug{false, "renderer_debug"}; | ||||
|     Setting<bool> dump_command_buffers{false, "dump_command_buffers"}; | ||||
|     SwitchableSetting<bool> use_hw_shader{true, "use_hw_shader"}; | ||||
|     SwitchableSetting<bool> use_disk_shader_cache{true, "use_disk_shader_cache"}; | ||||
|     SwitchableSetting<bool> shaders_accurate_mul{true, "shaders_accurate_mul"}; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue