mirror of
				https://github.com/N64Recomp/N64ModernRuntime.git
				synced 2025-10-30 08:02:29 +00:00 
			
		
		
		
	Remove RT64 dependency (#35)
				
					
				
			* `RendererContext` abstract class * Delete rt64_layer * Implement renderer creation callback * Make `GraphicsConfig` an abstract class * Remove rt64 * Add renderer callback to `ultramodern::set_callbacks` * Fix rebase * Change setup_result's visibility to protected * Declare abstract `is_equal` method instead of operators * Various fixes * Fix issues * trigger_config_action * Move GraphicsConfig back to ultramodern * Change `update_config` to return if any changes were applied * Rename renderer_wrapper to renderer_context * Remove SDL2 and other libraries * Allow registering get_graphics_api_name * Move WindowHandle to renderer namespace * Comments explaining which callbacks are required * Fix CI * Update readme * `ULTRAMODERN_QUICK_EXIT` macro * Remove --config from readme * Add `add_compile_definitions(NOMINMAX)`
This commit is contained in:
		
							parent
							
								
									b0fa96b613
								
							
						
					
					
						commit
						b4dbddb555
					
				
					 29 changed files with 26007 additions and 672 deletions
				
			
		
							
								
								
									
										20
									
								
								.github/workflows/validate.yml
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										20
									
								
								.github/workflows/validate.yml
									
										
									
									
										vendored
									
									
								
							|  | @ -8,6 +8,7 @@ on: | ||||||
| concurrency: | concurrency: | ||||||
|   group: ${{ github.workflow }}-${{ github.ref }} |   group: ${{ github.workflow }}-${{ github.ref }} | ||||||
|   cancel-in-progress: true |   cancel-in-progress: true | ||||||
|  | 
 | ||||||
| jobs: | jobs: | ||||||
|   build-linux: |   build-linux: | ||||||
|     runs-on: ${{ matrix.arch == 'x64' && 'ubuntu-22.04' || 'blaze/ubuntu-22.04' }} |     runs-on: ${{ matrix.arch == 'x64' && 'ubuntu-22.04' || 'blaze/ubuntu-22.04' }} | ||||||
|  | @ -30,26 +31,12 @@ jobs: | ||||||
|       - name: Install Linux Dependencies |       - name: Install Linux Dependencies | ||||||
|         run: | |         run: | | ||||||
|           sudo apt-get update |           sudo apt-get update | ||||||
|           sudo apt-get install -y ninja-build libsdl2-dev libgtk-3-dev lld llvm clang-15 |           sudo apt-get install -y ninja-build lld llvm clang-15 | ||||||
|            |  | ||||||
|           # Install SDL2 |  | ||||||
|           echo ::group::install SDL2 |  | ||||||
| 
 | 
 | ||||||
|           # Enable ccache |  | ||||||
|           export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" |  | ||||||
| 
 |  | ||||||
|           wget https://www.libsdl.org/release/SDL2-2.26.1.tar.gz |  | ||||||
|           tar -xzf SDL2-2.26.1.tar.gz |  | ||||||
|           cd SDL2-2.26.1 |  | ||||||
|           ./configure |  | ||||||
|           make -j 10 |  | ||||||
|           sudo make install |  | ||||||
|           sudo cp -av /usr/local/lib/libSDL* /lib/x86_64-linux-gnu/ |  | ||||||
|           echo ::endgroup:: |  | ||||||
|       - name: Generate CMake Project |       - name: Generate CMake Project | ||||||
|         run: | |         run: | | ||||||
|           # enable ccache |           # enable ccache | ||||||
|           export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"           |           export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" | ||||||
|           cmake -DCMAKE_BUILD_TYPE=${{ matrix.type }} -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER=clang++-15 -DCMAKE_C_COMPILER=clang-15 -DCMAKE_MAKE_PROGRAM=ninja -G Ninja -S . -B cmake-build |           cmake -DCMAKE_BUILD_TYPE=${{ matrix.type }} -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER=clang++-15 -DCMAKE_C_COMPILER=clang-15 -DCMAKE_MAKE_PROGRAM=ninja -G Ninja -S . -B cmake-build | ||||||
|       - name: Build ultramodern |       - name: Build ultramodern | ||||||
|         run: | |         run: | | ||||||
|  | @ -61,6 +48,7 @@ jobs: | ||||||
|           # enable ccache |           # enable ccache | ||||||
|           export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" |           export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" | ||||||
|           cmake --build cmake-build --config ${{ matrix.type }} --target librecomp -j $(nproc) |           cmake --build cmake-build --config ${{ matrix.type }} --target librecomp -j $(nproc) | ||||||
|  | 
 | ||||||
|   build-windows: |   build-windows: | ||||||
|     runs-on: windows-latest |     runs-on: windows-latest | ||||||
|     strategy: |     strategy: | ||||||
|  |  | ||||||
							
								
								
									
										6
									
								
								.gitmodules
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								.gitmodules
									
										
									
									
										vendored
									
									
								
							|  | @ -1,3 +1,3 @@ | ||||||
| [submodule "rt64"] | [submodule "thirdparty/xxHash"] | ||||||
| 	path = rt64 | 	path = thirdparty/xxHash | ||||||
| 	url = https://github.com/rt64/rt64.git | 	url = git@github.com:Cyan4973/xxHash.git | ||||||
|  |  | ||||||
							
								
								
									
										21
									
								
								README.md
									
										
									
									
									
								
							
							
						
						
									
										21
									
								
								README.md
									
										
									
									
									
								
							|  | @ -5,9 +5,10 @@ This repo is a WIP as files are moved out of Zelda64Recomp and genericized. It c | ||||||
| 
 | 
 | ||||||
| This repo contains two libraries: Ultramodern and Librecomp. | This repo contains two libraries: Ultramodern and Librecomp. | ||||||
| 
 | 
 | ||||||
| ### Ultramodern | ## Ultramodern | ||||||
| 
 | 
 | ||||||
| Ultramodern is a reimplementation of much of the core functionality of libultra. It can be used with either statically recompiled projects that use N64Recomp or direct source ports. It implements the following libultra functionality: | Ultramodern is a reimplementation of much of the core functionality of libultra. It can be used with either statically recompiled projects that use N64Recomp or direct source ports. It implements the following libultra functionality: | ||||||
|  | 
 | ||||||
| * Threads | * Threads | ||||||
| * Controllers | * Controllers | ||||||
| * Audio | * Audio | ||||||
|  | @ -18,11 +19,23 @@ Ultramodern is a reimplementation of much of the core functionality of libultra. | ||||||
| 
 | 
 | ||||||
| Platform-specific I/O is handled via callbacks that are provided by the project using ultramodern. This includes reading from controllers and playing back audio samples. | Platform-specific I/O is handled via callbacks that are provided by the project using ultramodern. This includes reading from controllers and playing back audio samples. | ||||||
| 
 | 
 | ||||||
| Currently, ultramodern depends directly on [RT64](https://github.com/rt64/rt64) for rendering. It may be decoupled in the future to allow using other renderers for targeting different platforms. | ultramodern expects the user to provide and register a graphics renderer. The recommended one is [RT64](https://github.com/rt64/rt64). | ||||||
| 
 | 
 | ||||||
| ### Librecomp | ## Librecomp | ||||||
| 
 | 
 | ||||||
| Librecomp is a library meant to be used to bridge the gap between code generated by N64Recomp and ultramodern. It provides wrappers to allow recompiled code to call ultramodern. Librecomp also provides some of the remaining libultra functionality that ultramodern doesn't provide, which includes: | Librecomp is a library meant to be used to bridge the gap between code generated by N64Recomp and ultramodern. It provides wrappers to allow recompiled code to call ultramodern. Librecomp also provides some of the remaining libultra functionality that ultramodern doesn't provide, which includes: | ||||||
|  | 
 | ||||||
| * Overlay handling | * Overlay handling | ||||||
| * PI DMA (ROM reads) | * PI DMA (ROM reads) | ||||||
| * EEPROM, SRAM and Flashram saving (these may be partially moved to ultramodern in the future) | * EEPROM, SRAM and Flashram saving (these may be partially moved to ultramodern in the future) | ||||||
|  | 
 | ||||||
|  | ## Building | ||||||
|  | 
 | ||||||
|  | The recommended usage of these libraries is to include them in your project's CMakeLists.txt file via add_subdirectory. This project requires C++20 support and was developed using Clang 15, older versions of clang may not work. Recent enough versions of MSVC and GCC should work as well, but are not regularly tested. | ||||||
|  | 
 | ||||||
|  | These libraries can be built in a standalone environment (ie, developing new features for the libraries of this project) via the following: | ||||||
|  | 
 | ||||||
|  | ```bash | ||||||
|  | cmake -B build -G Ninja -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang -DCMAKE_BUILD_TYPE=Debug | ||||||
|  | cmake --build build | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | @ -1,5 +1,9 @@ | ||||||
| cmake_minimum_required(VERSION 3.20) | cmake_minimum_required(VERSION 3.20) | ||||||
|  | 
 | ||||||
| project(librecomp) | project(librecomp) | ||||||
|  | set(CMAKE_CXX_STANDARD 20) | ||||||
|  | set(CMAKE_CXX_STANDARD_REQUIRED True) | ||||||
|  | set(CMAKE_CXX_EXTENSIONS OFF) | ||||||
| 
 | 
 | ||||||
| # Define the library | # Define the library | ||||||
| add_library(librecomp STATIC | add_library(librecomp STATIC | ||||||
|  | @ -26,13 +30,21 @@ add_library(librecomp STATIC | ||||||
| target_include_directories(librecomp PUBLIC | target_include_directories(librecomp PUBLIC | ||||||
|     "${CMAKE_CURRENT_SOURCE_DIR}/include" |     "${CMAKE_CURRENT_SOURCE_DIR}/include" | ||||||
|     "${PROJECT_SOURCE_DIR}/../ultramodern/include" |     "${PROJECT_SOURCE_DIR}/../ultramodern/include" | ||||||
|  |     "${PROJECT_SOURCE_DIR}/../thirdparty" | ||||||
|     "${PROJECT_SOURCE_DIR}/../thirdparty/concurrentqueue" |     "${PROJECT_SOURCE_DIR}/../thirdparty/concurrentqueue" | ||||||
| ) | ) | ||||||
| target_include_directories(librecomp PRIVATE | target_include_directories(librecomp PRIVATE | ||||||
|     "${PROJECT_SOURCE_DIR}/../rt64/src/contrib" |  | ||||||
|     "${CMAKE_CURRENT_SOURCE_DIR}/include/librecomp" |     "${CMAKE_CURRENT_SOURCE_DIR}/include/librecomp" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| target_compile_options(librecomp PRIVATE -Wno-deprecated-declarations) | target_compile_options(librecomp PRIVATE | ||||||
|  | #    -Wall | ||||||
|  | #    -Wextra | ||||||
|  |     -Wno-unused-parameter | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | if (WIN32) | ||||||
|  |     add_compile_definitions(NOMINMAX) | ||||||
|  | endif() | ||||||
| 
 | 
 | ||||||
| target_link_libraries(librecomp PRIVATE ultramodern) | target_link_libraries(librecomp PRIVATE ultramodern) | ||||||
|  |  | ||||||
|  | @ -41,7 +41,25 @@ namespace recomp { | ||||||
| 	void set_rom_contents(std::vector<uint8_t>&& new_rom); | 	void set_rom_contents(std::vector<uint8_t>&& new_rom); | ||||||
| 	void do_rom_read(uint8_t* rdram, gpr ram_address, uint32_t physical_addr, size_t num_bytes); | 	void do_rom_read(uint8_t* rdram, gpr ram_address, uint32_t physical_addr, size_t num_bytes); | ||||||
| 	void do_rom_pio(uint8_t* rdram, gpr ram_address, uint32_t physical_addr); | 	void do_rom_pio(uint8_t* rdram, gpr ram_address, uint32_t physical_addr); | ||||||
| 	void start(ultramodern::WindowHandle window_handle, const recomp::rsp::callbacks_t& rsp_callbacks, const ultramodern::audio_callbacks_t& audio_callbacks, const ultramodern::input::callbacks_t& input_callbacks, const ultramodern::gfx_callbacks_t& gfx_callbacks, const ultramodern::events::callbacks_t& thread_callbacks, const ultramodern::error_handling::callbacks_t& error_handling_callbacks_); | 
 | ||||||
|  | 	/**
 | ||||||
|  | 	 * The following arguments contain mandatory callbacks that need to be registered (i.e., can't be `nullptr`): | ||||||
|  | 	 * - `rsp_callbacks` | ||||||
|  | 	 * - `renderer_callbacks` | ||||||
|  | 	 * | ||||||
|  | 	 * It must be called only once and it must be called before `ultramodern::preinit`. | ||||||
|  | 	 */ | ||||||
|  |     void start( | ||||||
|  |         ultramodern::renderer::WindowHandle window_handle, | ||||||
|  |         const recomp::rsp::callbacks_t& rsp_callbacks, | ||||||
|  |         const ultramodern::renderer::callbacks_t& renderer_callbacks, | ||||||
|  |         const ultramodern::audio_callbacks_t& audio_callbacks, | ||||||
|  |         const ultramodern::input::callbacks_t& input_callbacks, | ||||||
|  |         const ultramodern::gfx_callbacks_t& gfx_callbacks, | ||||||
|  |         const ultramodern::events::callbacks_t& events_callbacks, | ||||||
|  |         const ultramodern::error_handling::callbacks_t& error_handling_callbacks_ | ||||||
|  |     ); | ||||||
|  | 
 | ||||||
| 	void start_game(const std::u8string& game_id); | 	void start_game(const std::u8string& game_id); | ||||||
| 	std::u8string current_game_id(); | 	std::u8string current_game_id(); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,5 +1,6 @@ | ||||||
| #include "recomp.h" | #include "librecomp/recomp.h" | ||||||
| #include <ultramodern/ultra64.h> | 
 | ||||||
|  | #include "ultramodern/ultra64.h" | ||||||
| 
 | 
 | ||||||
| void save_write(RDRAM_ARG PTR(void) rdram_address, uint32_t offset, uint32_t count); | void save_write(RDRAM_ARG PTR(void) rdram_address, uint32_t offset, uint32_t count); | ||||||
| void save_read(RDRAM_ARG PTR(void) rdram_address, uint32_t offset, uint32_t count); | void save_read(RDRAM_ARG PTR(void) rdram_address, uint32_t offset, uint32_t count); | ||||||
|  |  | ||||||
|  | @ -390,7 +390,16 @@ void ultramodern::quit() { | ||||||
|     current_game.reset(); |     current_game.reset(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void recomp::start(ultramodern::WindowHandle window_handle, const recomp::rsp::callbacks_t& rsp_callbacks, const ultramodern::audio_callbacks_t& audio_callbacks, const ultramodern::input::callbacks_t& input_callbacks, const ultramodern::gfx_callbacks_t& gfx_callbacks_, const ultramodern::events::callbacks_t& thread_callbacks_, const ultramodern::error_handling::callbacks_t& error_handling_callbacks_) { | void recomp::start( | ||||||
|  |     ultramodern::renderer::WindowHandle window_handle, | ||||||
|  |     const recomp::rsp::callbacks_t& rsp_callbacks, | ||||||
|  |     const ultramodern::renderer::callbacks_t& renderer_callbacks, | ||||||
|  |     const ultramodern::audio_callbacks_t& audio_callbacks, | ||||||
|  |     const ultramodern::input::callbacks_t& input_callbacks, | ||||||
|  |     const ultramodern::gfx_callbacks_t& gfx_callbacks_, | ||||||
|  |     const ultramodern::events::callbacks_t& events_callbacks, | ||||||
|  |     const ultramodern::error_handling::callbacks_t& error_handling_callbacks_ | ||||||
|  | ) { | ||||||
|     recomp::check_all_stored_roms(); |     recomp::check_all_stored_roms(); | ||||||
| 
 | 
 | ||||||
|     recomp::rsp::set_callbacks(rsp_callbacks); |     recomp::rsp::set_callbacks(rsp_callbacks); | ||||||
|  | @ -400,7 +409,7 @@ void recomp::start(ultramodern::WindowHandle window_handle, const recomp::rsp::c | ||||||
|         .run_task = recomp::rsp::run_task, |         .run_task = recomp::rsp::run_task, | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     ultramodern::set_callbacks(ultramodern_rsp_callbacks, audio_callbacks, input_callbacks, gfx_callbacks_, thread_callbacks_, error_handling_callbacks_); |     ultramodern::set_callbacks(ultramodern_rsp_callbacks, renderer_callbacks, audio_callbacks, input_callbacks, gfx_callbacks_, events_callbacks, error_handling_callbacks_); | ||||||
| 
 | 
 | ||||||
|     ultramodern::gfx_callbacks_t gfx_callbacks = gfx_callbacks_; |     ultramodern::gfx_callbacks_t gfx_callbacks = gfx_callbacks_; | ||||||
| 
 | 
 | ||||||
|  | @ -410,7 +419,7 @@ void recomp::start(ultramodern::WindowHandle window_handle, const recomp::rsp::c | ||||||
|         gfx_data = gfx_callbacks.create_gfx(); |         gfx_data = gfx_callbacks.create_gfx(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (window_handle == ultramodern::WindowHandle{}) { |     if (window_handle == ultramodern::renderer::WindowHandle{}) { | ||||||
|         if (gfx_callbacks.create_window) { |         if (gfx_callbacks.create_window) { | ||||||
|             window_handle = gfx_callbacks.create_window(gfx_data); |             window_handle = gfx_callbacks.create_window(gfx_data); | ||||||
|         } |         } | ||||||
|  | @ -423,7 +432,7 @@ void recomp::start(ultramodern::WindowHandle window_handle, const recomp::rsp::c | ||||||
|     std::unique_ptr<uint8_t[]> rdram_buffer = std::make_unique<uint8_t[]>(ultramodern::rdram_size); |     std::unique_ptr<uint8_t[]> rdram_buffer = std::make_unique<uint8_t[]>(ultramodern::rdram_size); | ||||||
|     std::memset(rdram_buffer.get(), 0, ultramodern::rdram_size); |     std::memset(rdram_buffer.get(), 0, ultramodern::rdram_size); | ||||||
| 
 | 
 | ||||||
|     std::thread game_thread{[](ultramodern::WindowHandle window_handle, uint8_t* rdram) { |     std::thread game_thread{[](ultramodern::renderer::WindowHandle window_handle, uint8_t* rdram) { | ||||||
|         debug_printf("[Recomp] Starting\n"); |         debug_printf("[Recomp] Starting\n"); | ||||||
| 
 | 
 | ||||||
|         ultramodern::set_native_thread_name("Game Start Thread"); |         ultramodern::set_native_thread_name("Game Start Thread"); | ||||||
|  |  | ||||||
							
								
								
									
										1
									
								
								rt64
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								rt64
									
										
									
									
									
								
							|  | @ -1 +0,0 @@ | ||||||
| Subproject commit 1adcbea31a04f2403da729eb5dfed3950dd7ec52 |  | ||||||
							
								
								
									
										25533
									
								
								thirdparty/json/json.hpp
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										25533
									
								
								thirdparty/json/json.hpp
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										1
									
								
								thirdparty/xxHash
									
										
									
									
										vendored
									
									
										Submodule
									
								
							
							
						
						
									
										1
									
								
								thirdparty/xxHash
									
										
									
									
										vendored
									
									
										Submodule
									
								
							|  | @ -0,0 +1 @@ | ||||||
|  | Subproject commit ac3a25da3d957d9ef3e4114d9f8332d34ce83a46 | ||||||
|  | @ -5,10 +5,6 @@ set(CMAKE_CXX_STANDARD 20) | ||||||
| set(CMAKE_CXX_STANDARD_REQUIRED True) | set(CMAKE_CXX_STANDARD_REQUIRED True) | ||||||
| set(CMAKE_CXX_EXTENSIONS OFF) | set(CMAKE_CXX_EXTENSIONS OFF) | ||||||
| 
 | 
 | ||||||
| # Warnings |  | ||||||
| # TODO: uncoment this when we fix the warnings |  | ||||||
| # set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra") |  | ||||||
| 
 |  | ||||||
| add_library(ultramodern STATIC | add_library(ultramodern STATIC | ||||||
|     "${CMAKE_CURRENT_SOURCE_DIR}/src/audio.cpp" |     "${CMAKE_CURRENT_SOURCE_DIR}/src/audio.cpp" | ||||||
|     "${CMAKE_CURRENT_SOURCE_DIR}/src/error_handling.cpp" |     "${CMAKE_CURRENT_SOURCE_DIR}/src/error_handling.cpp" | ||||||
|  | @ -16,8 +12,8 @@ add_library(ultramodern STATIC | ||||||
|     "${CMAKE_CURRENT_SOURCE_DIR}/src/input.cpp" |     "${CMAKE_CURRENT_SOURCE_DIR}/src/input.cpp" | ||||||
|     "${CMAKE_CURRENT_SOURCE_DIR}/src/mesgqueue.cpp" |     "${CMAKE_CURRENT_SOURCE_DIR}/src/mesgqueue.cpp" | ||||||
|     "${CMAKE_CURRENT_SOURCE_DIR}/src/misc_ultra.cpp" |     "${CMAKE_CURRENT_SOURCE_DIR}/src/misc_ultra.cpp" | ||||||
|  |     "${CMAKE_CURRENT_SOURCE_DIR}/src/renderer_context.cpp" | ||||||
|     "${CMAKE_CURRENT_SOURCE_DIR}/src/rsp.cpp" |     "${CMAKE_CURRENT_SOURCE_DIR}/src/rsp.cpp" | ||||||
|     "${CMAKE_CURRENT_SOURCE_DIR}/src/rt64_layer.cpp" |  | ||||||
|     "${CMAKE_CURRENT_SOURCE_DIR}/src/scheduling.cpp" |     "${CMAKE_CURRENT_SOURCE_DIR}/src/scheduling.cpp" | ||||||
|     "${CMAKE_CURRENT_SOURCE_DIR}/src/task_win32.cpp" |     "${CMAKE_CURRENT_SOURCE_DIR}/src/task_win32.cpp" | ||||||
|     "${CMAKE_CURRENT_SOURCE_DIR}/src/threadqueue.cpp" |     "${CMAKE_CURRENT_SOURCE_DIR}/src/threadqueue.cpp" | ||||||
|  | @ -28,57 +24,17 @@ add_library(ultramodern STATIC | ||||||
| 
 | 
 | ||||||
| target_include_directories(ultramodern PUBLIC | target_include_directories(ultramodern PUBLIC | ||||||
|     "${CMAKE_CURRENT_SOURCE_DIR}/include/" |     "${CMAKE_CURRENT_SOURCE_DIR}/include/" | ||||||
|  |     "${PROJECT_SOURCE_DIR}/../thirdparty" | ||||||
|     "${PROJECT_SOURCE_DIR}/../thirdparty/concurrentqueue" |     "${PROJECT_SOURCE_DIR}/../thirdparty/concurrentqueue" | ||||||
|     "${PROJECT_SOURCE_DIR}/../thirdparty/sse2neon" |     "${PROJECT_SOURCE_DIR}/../thirdparty/sse2neon" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| target_include_directories(ultramodern PRIVATE | target_compile_options(ultramodern PRIVATE | ||||||
|     "${CMAKE_CURRENT_SOURCE_DIR}/include/ultramodern" | #    -Wall | ||||||
| ) | #    -Wextra | ||||||
| 
 |     -Wno-unused-parameter | ||||||
| # TODO: remove when rt64 is no longer a hard dependency |  | ||||||
| target_include_directories(ultramodern PRIVATE |  | ||||||
|     "${PROJECT_SOURCE_DIR}/../rt64/src" |  | ||||||
|     "${PROJECT_SOURCE_DIR}/../rt64/src/contrib" |  | ||||||
|     "${PROJECT_SOURCE_DIR}/../rt64/src/contrib/hlslpp/include" |  | ||||||
|     "${PROJECT_SOURCE_DIR}/../rt64/src/contrib/dxc/inc" |  | ||||||
|     "${PROJECT_SOURCE_DIR}/../rt64/src/rhi" |  | ||||||
|     "${PROJECT_SOURCE_DIR}/../rt64/src/render" |  | ||||||
|     "${PROJECT_SOURCE_DIR}/../rt64/src/contrib/nativefiledialog-extended/src/include" |  | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| if (WIN32) | if (WIN32) | ||||||
|     include(FetchContent) |  | ||||||
|     # Fetch SDL2 on windows |  | ||||||
|     FetchContent_Declare( |  | ||||||
|         sdl2 |  | ||||||
|         URL https://github.com/libsdl-org/SDL/releases/download/release-2.28.5/SDL2-devel-2.28.5-VC.zip |  | ||||||
|         URL_HASH MD5=d8173db078e54040c666f411c5a6afff |  | ||||||
|     ) |  | ||||||
|     FetchContent_MakeAvailable(sdl2) |  | ||||||
|     target_include_directories(ultramodern PRIVATE |  | ||||||
|         ${sdl2_SOURCE_DIR}/include |  | ||||||
|     ) |  | ||||||
|     target_link_directories(ultramodern PRIVATE |  | ||||||
|         ${sdl2_SOURCE_DIR}/lib/x64 |  | ||||||
|     ) |  | ||||||
|     add_compile_definitions(NOMINMAX) |     add_compile_definitions(NOMINMAX) | ||||||
| elseif (APPLE) |  | ||||||
|     find_package(SDL2 REQUIRED) |  | ||||||
|     target_include_directories(ultramodern PRIVATE ${SDL2_INCLUDE_DIRS}) |  | ||||||
| else() |  | ||||||
|     find_package(SDL2 REQUIRED) |  | ||||||
|     find_package(X11 REQUIRED) |  | ||||||
| 
 |  | ||||||
|     message(STATUS "SDL2_FOUND = ${SDL2_FOUND}") |  | ||||||
|     message(STATUS "SDL2_INCLUDE_DIRS = ${SDL2_INCLUDE_DIRS}") |  | ||||||
| 
 |  | ||||||
|     target_include_directories(ultramodern PRIVATE ${SDL2_INCLUDE_DIRS}) |  | ||||||
| 
 |  | ||||||
|     message(STATUS "X11_FOUND = ${X11_FOUND}") |  | ||||||
|     message(STATUS "X11_INCLUDE_DIR = ${X11_INCLUDE_DIR}") |  | ||||||
|     message(STATUS "X11_LIBRARIES = ${X11_LIBRARIES}") |  | ||||||
| 
 |  | ||||||
|     target_include_directories(ultramodern PRIVATE ${X11_INCLUDE_DIR}) |  | ||||||
|     target_link_libraries(ultramodern PRIVATE ${X11_LIBRARIES}) |  | ||||||
| endif() | endif() | ||||||
|  |  | ||||||
|  | @ -1,88 +1,134 @@ | ||||||
| #ifndef __CONFIG_HPP__ | #ifndef __CONFIG_HPP__ | ||||||
| #define __CONFIG_HPP__ | #define __CONFIG_HPP__ | ||||||
| 
 | 
 | ||||||
| // TODO remove this direct dependency on RT64.
 | #include <string> | ||||||
| #include "common/rt64_user_configuration.h" | #include <optional> | ||||||
|  | 
 | ||||||
|  | #include "json/json.hpp" | ||||||
| 
 | 
 | ||||||
| namespace ultramodern { | namespace ultramodern { | ||||||
| 	enum class Resolution { |     namespace renderer { | ||||||
| 		Original, |         enum class Resolution { | ||||||
| 		Original2x, |             Original, | ||||||
| 		Auto, |             Original2x, | ||||||
| 		OptionCount |             Auto, | ||||||
| 	}; |             OptionCount | ||||||
| 	enum class WindowMode { |         }; | ||||||
| 		Windowed, |         enum class WindowMode { | ||||||
| 		Fullscreen, |             Windowed, | ||||||
| 		OptionCount |             Fullscreen, | ||||||
| 	}; |             OptionCount | ||||||
| 	enum class HUDRatioMode { |         }; | ||||||
| 		Original, |         enum class HUDRatioMode { | ||||||
| 		Clamp16x9, |             Original, | ||||||
| 		Full, |             Clamp16x9, | ||||||
| 		OptionCount |             Full, | ||||||
| 	}; |             OptionCount | ||||||
| 	enum class GraphicsApi { |         }; | ||||||
| 		Auto, |         enum class GraphicsApi { | ||||||
| 		D3D12, |             Auto, | ||||||
| 		Vulkan, |             D3D12, | ||||||
| 		OptionCount |             Vulkan, | ||||||
| 	}; |             OptionCount | ||||||
| 	enum class HighPrecisionFramebuffer { |         }; | ||||||
| 		Auto, |         enum class AspectRatio { | ||||||
| 		On, |             Original, | ||||||
| 		Off, |             Expand, | ||||||
| 		OptionCount |             Manual, | ||||||
| 	}; |             OptionCount | ||||||
|  |         }; | ||||||
|  |         enum class Antialiasing { | ||||||
|  |             None, | ||||||
|  |             MSAA2X, | ||||||
|  |             MSAA4X, | ||||||
|  |             MSAA8X, | ||||||
|  |             OptionCount | ||||||
|  |         }; | ||||||
|  |         enum class RefreshRate { | ||||||
|  |             Original, | ||||||
|  |             Display, | ||||||
|  |             Manual, | ||||||
|  |             OptionCount | ||||||
|  |         }; | ||||||
|  |         enum class HighPrecisionFramebuffer { | ||||||
|  |             Auto, | ||||||
|  |             On, | ||||||
|  |             Off, | ||||||
|  |             OptionCount | ||||||
|  |         }; | ||||||
| 
 | 
 | ||||||
| 	struct GraphicsConfig { |         class GraphicsConfig { | ||||||
| 		Resolution res_option; |         public: | ||||||
| 		WindowMode wm_option; |             bool developer_mode; | ||||||
| 		HUDRatioMode hr_option; |             Resolution res_option; | ||||||
| 		GraphicsApi api_option; |             WindowMode wm_option; | ||||||
| 		// TODO make custom enums that map to the RT64 ones to remove the direct dependency on RT64 in this file.
 |             HUDRatioMode hr_option; | ||||||
| 		RT64::UserConfiguration::AspectRatio ar_option; |             GraphicsApi api_option; | ||||||
| 		RT64::UserConfiguration::Antialiasing msaa_option; |             AspectRatio ar_option; | ||||||
| 		RT64::UserConfiguration::RefreshRate rr_option; |             Antialiasing msaa_option; | ||||||
| 		HighPrecisionFramebuffer hpfb_option; |             RefreshRate rr_option; | ||||||
| 		int rr_manual_value; |             HighPrecisionFramebuffer hpfb_option; | ||||||
| 		int ds_option; |             int rr_manual_value; | ||||||
| 		bool developer_mode; |             int ds_option; | ||||||
| 
 | 
 | ||||||
| 		auto operator<=>(const GraphicsConfig& rhs) const = default; |             virtual ~GraphicsConfig() = default; | ||||||
| 	}; |  | ||||||
| 
 | 
 | ||||||
| 	void set_graphics_config(const GraphicsConfig& config); |             std::string get_graphics_api_name() const; | ||||||
| 	GraphicsConfig get_graphics_config(); |  | ||||||
| 
 | 
 | ||||||
| 	NLOHMANN_JSON_SERIALIZE_ENUM(ultramodern::Resolution, { |             auto operator<=>(const GraphicsConfig& rhs) const = default; | ||||||
| 		{ultramodern::Resolution::Original, "Original"}, |         }; | ||||||
| 		{ultramodern::Resolution::Original2x, "Original2x"}, |  | ||||||
| 		{ultramodern::Resolution::Auto, "Auto"}, |  | ||||||
| 	}); |  | ||||||
| 
 | 
 | ||||||
| 	NLOHMANN_JSON_SERIALIZE_ENUM(ultramodern::WindowMode, { |         const GraphicsConfig& get_graphics_config(); | ||||||
| 		{ultramodern::WindowMode::Windowed, "Windowed"}, |         void set_graphics_config(const GraphicsConfig& new_config); | ||||||
| 		{ultramodern::WindowMode::Fullscreen, "Fullscreen"} |  | ||||||
| 	}); |  | ||||||
| 
 | 
 | ||||||
| 	NLOHMANN_JSON_SERIALIZE_ENUM(ultramodern::HUDRatioMode, { |         NLOHMANN_JSON_SERIALIZE_ENUM(ultramodern::renderer::Resolution, { | ||||||
| 		{ultramodern::HUDRatioMode::Original, "Original"}, |             {ultramodern::renderer::Resolution::Original, "Original"}, | ||||||
| 		{ultramodern::HUDRatioMode::Clamp16x9, "Clamp16x9"}, |             {ultramodern::renderer::Resolution::Original2x, "Original2x"}, | ||||||
| 		{ultramodern::HUDRatioMode::Full, "Full"}, |             {ultramodern::renderer::Resolution::Auto, "Auto"}, | ||||||
| 	}); |         }); | ||||||
| 
 | 
 | ||||||
| 	NLOHMANN_JSON_SERIALIZE_ENUM(ultramodern::GraphicsApi, { |         NLOHMANN_JSON_SERIALIZE_ENUM(ultramodern::renderer::WindowMode, { | ||||||
| 		{ultramodern::GraphicsApi::Auto, "Auto"}, |             {ultramodern::renderer::WindowMode::Windowed, "Windowed"}, | ||||||
| 		{ultramodern::GraphicsApi::D3D12, "D3D12"}, |             {ultramodern::renderer::WindowMode::Fullscreen, "Fullscreen"} | ||||||
| 		{ultramodern::GraphicsApi::Vulkan, "Vulkan"}, |         }); | ||||||
| 	}); |  | ||||||
| 
 | 
 | ||||||
| 	NLOHMANN_JSON_SERIALIZE_ENUM(ultramodern::HighPrecisionFramebuffer, { |         NLOHMANN_JSON_SERIALIZE_ENUM(ultramodern::renderer::HUDRatioMode, { | ||||||
| 		{ultramodern::HighPrecisionFramebuffer::Auto, "Auto"}, |             {ultramodern::renderer::HUDRatioMode::Original, "Original"}, | ||||||
| 		{ultramodern::HighPrecisionFramebuffer::On, "On"}, |             {ultramodern::renderer::HUDRatioMode::Clamp16x9, "Clamp16x9"}, | ||||||
| 		{ultramodern::HighPrecisionFramebuffer::Off, "Off"}, |             {ultramodern::renderer::HUDRatioMode::Full, "Full"}, | ||||||
| 	}); |         }); | ||||||
| }; | 
 | ||||||
|  |         NLOHMANN_JSON_SERIALIZE_ENUM(ultramodern::renderer::GraphicsApi, { | ||||||
|  |             {ultramodern::renderer::GraphicsApi::Auto, "Auto"}, | ||||||
|  |             {ultramodern::renderer::GraphicsApi::D3D12, "D3D12"}, | ||||||
|  |             {ultramodern::renderer::GraphicsApi::Vulkan, "Vulkan"}, | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         NLOHMANN_JSON_SERIALIZE_ENUM(ultramodern::renderer::AspectRatio, { | ||||||
|  |             {ultramodern::renderer::AspectRatio::Original, "Original"}, | ||||||
|  |             {ultramodern::renderer::AspectRatio::Expand, "Expand"}, | ||||||
|  |             {ultramodern::renderer::AspectRatio::Manual, "Manual"}, | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         NLOHMANN_JSON_SERIALIZE_ENUM(ultramodern::renderer::Antialiasing, { | ||||||
|  |             {ultramodern::renderer::Antialiasing::None, "None"}, | ||||||
|  |             {ultramodern::renderer::Antialiasing::MSAA2X, "MSAA2X"}, | ||||||
|  |             {ultramodern::renderer::Antialiasing::MSAA4X, "MSAA4X"}, | ||||||
|  |             {ultramodern::renderer::Antialiasing::MSAA8X, "MSAA8X"}, | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         NLOHMANN_JSON_SERIALIZE_ENUM(ultramodern::renderer::RefreshRate, { | ||||||
|  |             {ultramodern::renderer::RefreshRate::Original, "Original"}, | ||||||
|  |             {ultramodern::renderer::RefreshRate::Display, "Display"}, | ||||||
|  |             {ultramodern::renderer::RefreshRate::Manual, "Manual"}, | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         NLOHMANN_JSON_SERIALIZE_ENUM(ultramodern::renderer::HighPrecisionFramebuffer, { | ||||||
|  |             {ultramodern::renderer::HighPrecisionFramebuffer::Auto, "Auto"}, | ||||||
|  |             {ultramodern::renderer::HighPrecisionFramebuffer::On, "On"}, | ||||||
|  |             {ultramodern::renderer::HighPrecisionFramebuffer::Off, "Off"}, | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | @ -1,6 +1,10 @@ | ||||||
| #ifndef __ERROR_HANDLING_HPP__ | #ifndef __ERROR_HANDLING_HPP__ | ||||||
| #define __ERROR_HANDLING_HPP__ | #define __ERROR_HANDLING_HPP__ | ||||||
| 
 | 
 | ||||||
|  | #include <cstdlib> | ||||||
|  | 
 | ||||||
|  | #define ULTRAMODERN_QUICK_EXIT() ultramodern::error_handling::quick_exit(__FILE__, __LINE__, __func__) | ||||||
|  | 
 | ||||||
| namespace ultramodern { | namespace ultramodern { | ||||||
|     namespace error_handling { |     namespace error_handling { | ||||||
|         struct callbacks_t { |         struct callbacks_t { | ||||||
|  | @ -17,6 +21,8 @@ namespace ultramodern { | ||||||
|         void set_callbacks(const callbacks_t& callbacks); |         void set_callbacks(const callbacks_t& callbacks); | ||||||
| 
 | 
 | ||||||
|         void message_box(const char* msg); |         void message_box(const char* msg); | ||||||
|  | 
 | ||||||
|  |         [[noreturn]] void quick_exit(const char* filename, int line, const char *func, int exit_status = EXIT_FAILURE); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										106
									
								
								ultramodern/include/ultramodern/renderer_context.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								ultramodern/include/ultramodern/renderer_context.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,106 @@ | ||||||
|  | #ifndef __RENDERER_WRAPPER_HPP__ | ||||||
|  | #define __RENDERER_WRAPPER_HPP__ | ||||||
|  | 
 | ||||||
|  | #include <cstdint> | ||||||
|  | #include <memory> | ||||||
|  | #include <optional> | ||||||
|  | #include <span> | ||||||
|  | 
 | ||||||
|  | #if defined(_WIN32) | ||||||
|  | #   define WIN32_LEAN_AND_MEAN | ||||||
|  | #   include <Windows.h> | ||||||
|  | #elif defined(__ANDROID__) | ||||||
|  | #   include "android/native_window.h" | ||||||
|  | #elif defined(__linux__) | ||||||
|  | #   include "X11/Xlib.h" | ||||||
|  | #   undef None | ||||||
|  | #   undef Status | ||||||
|  | #   undef LockMask | ||||||
|  | #   undef Always | ||||||
|  | #   undef Success | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #include "ultra64.h" | ||||||
|  | #include "config.hpp" | ||||||
|  | 
 | ||||||
|  | namespace ultramodern { | ||||||
|  |     namespace renderer { | ||||||
|  | 
 | ||||||
|  | #if defined(_WIN32) | ||||||
|  |         // Native HWND handle to the target window.
 | ||||||
|  |         struct WindowHandle { | ||||||
|  |             HWND window; | ||||||
|  |             DWORD thread_id = (DWORD)-1; | ||||||
|  |             auto operator<=>(const WindowHandle&) const = default; | ||||||
|  |         }; | ||||||
|  | #elif defined(__ANDROID__) | ||||||
|  |         using WindowHandle = ANativeWindow*; | ||||||
|  | #elif defined(__linux__) | ||||||
|  |         struct WindowHandle { | ||||||
|  |             Display* display; | ||||||
|  |             Window window; | ||||||
|  |             auto operator<=>(const WindowHandle&) const = default; | ||||||
|  |         }; | ||||||
|  | #elif defined(__APPLE__) | ||||||
|  |         struct WindowHandle { | ||||||
|  |             void* window; | ||||||
|  |             void* view; | ||||||
|  |             auto operator<=>(const WindowHandle&) const = default; | ||||||
|  |         }; | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  |         enum class SetupResult { | ||||||
|  |             Success, | ||||||
|  |             DynamicLibrariesNotFound, | ||||||
|  |             InvalidGraphicsAPI, | ||||||
|  |             GraphicsAPINotFound, | ||||||
|  |             GraphicsDeviceNotFound | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         class RendererContext { | ||||||
|  |             public: | ||||||
|  |                 virtual ~RendererContext() = default; | ||||||
|  | 
 | ||||||
|  |                 virtual bool valid() = 0; | ||||||
|  |                 virtual SetupResult get_setup_result() const { return setup_result; } | ||||||
|  | 
 | ||||||
|  |                 virtual bool update_config(const GraphicsConfig& old_config, const GraphicsConfig& new_config) = 0; | ||||||
|  | 
 | ||||||
|  |                 virtual void enable_instant_present() = 0; | ||||||
|  |                 virtual void send_dl(const OSTask* task) = 0; | ||||||
|  |                 virtual void update_screen(uint32_t vi_origin) = 0; | ||||||
|  |                 virtual void shutdown() = 0; | ||||||
|  |                 virtual uint32_t get_display_framerate() const = 0; | ||||||
|  |                 virtual float get_resolution_scale() const = 0; | ||||||
|  |                 virtual void load_shader_cache(std::span<const char> cache_binary) = 0; | ||||||
|  | 
 | ||||||
|  |             protected: | ||||||
|  |                 SetupResult setup_result; | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         struct callbacks_t { | ||||||
|  |             using create_render_context_t = std::unique_ptr<RendererContext>(uint8_t* rdram, WindowHandle window_handle, bool developer_mode); | ||||||
|  |             using get_graphics_api_name_t = std::string(const GraphicsConfig& config); | ||||||
|  | 
 | ||||||
|  |             /**
 | ||||||
|  |              * Instances a subclass of RendererContext that is used to render the game. | ||||||
|  |              * | ||||||
|  |              * This callback is mandatory for using the library. | ||||||
|  |              */ | ||||||
|  |             create_render_context_t *create_render_context; | ||||||
|  | 
 | ||||||
|  |             /**
 | ||||||
|  |              * This callback is optional. If not provided a library default will be used. | ||||||
|  |              */ | ||||||
|  |             get_graphics_api_name_t *get_graphics_api_name; | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         void set_callbacks(const callbacks_t& callbacks); | ||||||
|  | 
 | ||||||
|  |         std::unique_ptr<RendererContext> create_render_context(uint8_t* rdram, WindowHandle window_handle, bool developer_mode); | ||||||
|  | 
 | ||||||
|  |         std::string get_graphics_api_name(const GraphicsConfig& config); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
|  | @ -1,50 +0,0 @@ | ||||||
| #ifndef __RT64_LAYER_H__ |  | ||||||
| #define __RT64_LAYER_H__ |  | ||||||
| 
 |  | ||||||
| #include "ultramodern.hpp" |  | ||||||
| #include "config.hpp" |  | ||||||
| 
 |  | ||||||
| namespace RT64 { |  | ||||||
|     struct Application; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| namespace ultramodern { |  | ||||||
|     enum class RT64SetupResult { |  | ||||||
|         Success, |  | ||||||
|         DynamicLibrariesNotFound, |  | ||||||
|         InvalidGraphicsAPI, |  | ||||||
|         GraphicsAPINotFound, |  | ||||||
|         GraphicsDeviceNotFound |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     struct WindowHandle; |  | ||||||
|     struct RT64Context { |  | ||||||
|         public: |  | ||||||
|             ~RT64Context(); |  | ||||||
|             RT64Context(uint8_t* rdram, WindowHandle window_handle, bool developer_mode); |  | ||||||
|             bool valid() { return static_cast<bool>(app); } |  | ||||||
|             RT64SetupResult get_setup_result() { return setup_result; } |  | ||||||
| 
 |  | ||||||
|             void update_config(const GraphicsConfig& old_config, const GraphicsConfig& new_config); |  | ||||||
|             void enable_instant_present(); |  | ||||||
|             void send_dl(const OSTask* task); |  | ||||||
|             void update_screen(uint32_t vi_origin); |  | ||||||
|             void shutdown(); |  | ||||||
|             void set_dummy_vi(); |  | ||||||
|             uint32_t get_display_framerate(); |  | ||||||
|             float get_resolution_scale(); |  | ||||||
|             void load_shader_cache(std::span<const char> cache_binary); |  | ||||||
|         private: |  | ||||||
|             RT64SetupResult setup_result; |  | ||||||
|             std::unique_ptr<RT64::Application> app; |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     RT64::UserConfiguration::Antialiasing RT64MaxMSAA(); |  | ||||||
|     bool RT64SamplePositionsSupported(); |  | ||||||
|     bool RT64HighPrecisionFBEnabled(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void set_rt64_hooks(); |  | ||||||
| 
 |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
|  | @ -11,24 +11,11 @@ | ||||||
| #include "lightweightsemaphore.h" | #include "lightweightsemaphore.h" | ||||||
| #include "ultra64.h" | #include "ultra64.h" | ||||||
| 
 | 
 | ||||||
| #if defined(_WIN32) |  | ||||||
| #   define WIN32_LEAN_AND_MEAN |  | ||||||
| #   include <Windows.h> |  | ||||||
| #elif defined(__ANDROID__) |  | ||||||
| #   include "android/native_window.h" |  | ||||||
| #elif defined(__linux__) |  | ||||||
| #   include "X11/Xlib.h" |  | ||||||
| #   undef None |  | ||||||
| #   undef Status |  | ||||||
| #   undef LockMask |  | ||||||
| #   undef Always |  | ||||||
| #   undef Success |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| #include "ultramodern/error_handling.hpp" | #include "ultramodern/error_handling.hpp" | ||||||
| #include "ultramodern/events.hpp" | #include "ultramodern/events.hpp" | ||||||
| #include "ultramodern/input.hpp" | #include "ultramodern/input.hpp" | ||||||
| #include "ultramodern/rsp.hpp" | #include "ultramodern/rsp.hpp" | ||||||
|  | #include "ultramodern/renderer_context.hpp" | ||||||
| 
 | 
 | ||||||
| struct UltraThreadContext { | struct UltraThreadContext { | ||||||
|     std::thread host_thread; |     std::thread host_thread; | ||||||
|  | @ -38,29 +25,6 @@ struct UltraThreadContext { | ||||||
| 
 | 
 | ||||||
| namespace ultramodern { | namespace ultramodern { | ||||||
| 
 | 
 | ||||||
| #if defined(_WIN32) |  | ||||||
|     // Native HWND handle to the target window.
 |  | ||||||
|     struct WindowHandle { |  | ||||||
|         HWND window; |  | ||||||
|         DWORD thread_id = (DWORD)-1; |  | ||||||
|         auto operator<=>(const WindowHandle&) const = default; |  | ||||||
|     }; |  | ||||||
| #elif defined(__ANDROID__) |  | ||||||
|     using WindowHandle = ANativeWindow*; |  | ||||||
| #elif defined(__linux__) |  | ||||||
|     struct WindowHandle { |  | ||||||
|         Display* display; |  | ||||||
|         Window window; |  | ||||||
|         auto operator<=>(const WindowHandle&) const = default; |  | ||||||
|     }; |  | ||||||
| #elif defined(__APPLE__) |  | ||||||
|     struct WindowHandle { |  | ||||||
|         void* window; |  | ||||||
|         void* view; |  | ||||||
|         auto operator<=>(const WindowHandle&) const = default; |  | ||||||
|     }; |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| // We need a place in rdram to hold the PI handles, so pick an address in extended rdram
 | // We need a place in rdram to hold the PI handles, so pick an address in extended rdram
 | ||||||
| constexpr uint32_t rdram_size = 1024 * 1024 * 16; // 16MB to give extra room for anything custom
 | constexpr uint32_t rdram_size = 1024 * 1024 * 16; // 16MB to give extra room for anything custom
 | ||||||
| constexpr int32_t cart_handle = 0x80800000; | constexpr int32_t cart_handle = 0x80800000; | ||||||
|  | @ -69,9 +33,9 @@ constexpr int32_t flash_handle = (int32_t)(drive_handle + sizeof(OSPiHandle)); | ||||||
| constexpr uint32_t save_size = 1024 * 1024 / 8; // Maximum save size, 1Mbit for flash
 | constexpr uint32_t save_size = 1024 * 1024 / 8; // Maximum save size, 1Mbit for flash
 | ||||||
| 
 | 
 | ||||||
| // Initialization.
 | // Initialization.
 | ||||||
| void preinit(RDRAM_ARG WindowHandle window_handle); | void preinit(RDRAM_ARG renderer::WindowHandle window_handle); | ||||||
| void init_saving(RDRAM_ARG1); | void init_saving(RDRAM_ARG1); | ||||||
| void init_events(RDRAM_ARG WindowHandle window_handle); | void init_events(RDRAM_ARG renderer::WindowHandle window_handle); | ||||||
| void init_timers(RDRAM_ARG1); | void init_timers(RDRAM_ARG1); | ||||||
| void init_thread_cleanup(); | void init_thread_cleanup(); | ||||||
| 
 | 
 | ||||||
|  | @ -127,6 +91,7 @@ uint32_t get_target_framerate(uint32_t original); | ||||||
| uint32_t get_display_refresh_rate(); | uint32_t get_display_refresh_rate(); | ||||||
| float get_resolution_scale(); | float get_resolution_scale(); | ||||||
| void load_shader_cache(std::span<const char> cache_data); | void load_shader_cache(std::span<const char> cache_data); | ||||||
|  | void trigger_config_action(); | ||||||
| 
 | 
 | ||||||
| // Audio
 | // Audio
 | ||||||
| void init_audio(); | void init_audio(); | ||||||
|  | @ -147,7 +112,7 @@ struct audio_callbacks_t { | ||||||
| struct gfx_callbacks_t { | struct gfx_callbacks_t { | ||||||
|     using gfx_data_t = void*; |     using gfx_data_t = void*; | ||||||
|     using create_gfx_t = gfx_data_t(); |     using create_gfx_t = gfx_data_t(); | ||||||
|     using create_window_t = WindowHandle(gfx_data_t); |     using create_window_t = renderer::WindowHandle(gfx_data_t); | ||||||
|     using update_gfx_t = void(gfx_data_t); |     using update_gfx_t = void(gfx_data_t); | ||||||
| 
 | 
 | ||||||
|     create_gfx_t* create_gfx; |     create_gfx_t* create_gfx; | ||||||
|  | @ -166,9 +131,21 @@ void set_audio_callbacks(const audio_callbacks_t& callbacks); | ||||||
| /**
 | /**
 | ||||||
|  * Register all the callbacks used by `ultramodern`, most of them being optional. |  * Register all the callbacks used by `ultramodern`, most of them being optional. | ||||||
|  * |  * | ||||||
|  |  * The following arguments contain mandatory callbacks that need to be registered (i.e., can't be `nullptr`): | ||||||
|  |  * - `rsp_callbacks` | ||||||
|  |  * - `renderer_callbacks` | ||||||
|  |  * | ||||||
|  * It must be called only once and it must be called before `ultramodern::preinit`. |  * It must be called only once and it must be called before `ultramodern::preinit`. | ||||||
|  */ |  */ | ||||||
| void set_callbacks(const rsp::callbacks_t& rsp_callbacks, const audio_callbacks_t& audio_callbacks, const input::callbacks_t& input_callbacks, const gfx_callbacks_t& gfx_callbacks, const events::callbacks_t& events_callbacks, const error_handling::callbacks_t& error_handling_callbacks); | void set_callbacks( | ||||||
|  |     const rsp::callbacks_t& rsp_callbacks, | ||||||
|  |     const renderer::callbacks_t& renderer_callbacks, | ||||||
|  |     const audio_callbacks_t& audio_callbacks, | ||||||
|  |     const input::callbacks_t& input_callbacks, | ||||||
|  |     const gfx_callbacks_t& gfx_callbacks, | ||||||
|  |     const events::callbacks_t& events_callbacks, | ||||||
|  |     const error_handling::callbacks_t& error_handling_callbacks | ||||||
|  | ); | ||||||
| } // namespace ultramodern
 | } // namespace ultramodern
 | ||||||
| 
 | 
 | ||||||
| #define MIN(a, b) ((a) < (b) ? (a) : (b)) | #define MIN(a, b) ((a) < (b) ? (a) : (b)) | ||||||
|  |  | ||||||
|  | @ -1,5 +1,5 @@ | ||||||
| #include "ultra64.h" | #include "ultramodern/ultra64.h" | ||||||
| #include "ultramodern.hpp" | #include "ultramodern/ultramodern.hpp" | ||||||
| #include <cassert> | #include <cassert> | ||||||
| 
 | 
 | ||||||
| static uint32_t sample_rate = 48000; | static uint32_t sample_rate = 48000; | ||||||
|  |  | ||||||
|  | @ -17,3 +17,13 @@ void ultramodern::error_handling::message_box(const char* msg) { | ||||||
|         error_handling_callbacks.message_box(msg); |         error_handling_callbacks.message_box(msg); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | void ultramodern::error_handling::quick_exit(const char* filename, int line, const char *func, int exit_status) { | ||||||
|  |     fprintf(stderr, "Exiting with exit status '%i'. Function %s, at file %s:%i, ", exit_status, func, filename, line); | ||||||
|  | 
 | ||||||
|  | #ifdef __APPLE__ | ||||||
|  |     std::_Exit(exit_status); | ||||||
|  | #else | ||||||
|  |     std::quick_exit(exit_status); | ||||||
|  | #endif | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -11,11 +11,11 @@ | ||||||
| 
 | 
 | ||||||
| #include "blockingconcurrentqueue.h" | #include "blockingconcurrentqueue.h" | ||||||
| 
 | 
 | ||||||
| #include "ultra64.h" | #include "ultramodern/ultra64.h" | ||||||
| #include "ultramodern/ultramodern.hpp" | #include "ultramodern/ultramodern.hpp" | ||||||
| #include "config.hpp" | 
 | ||||||
| #include "rt64_layer.hpp" |  | ||||||
| #include "ultramodern/rsp.hpp" | #include "ultramodern/rsp.hpp" | ||||||
|  | #include "ultramodern/renderer_context.hpp" | ||||||
| 
 | 
 | ||||||
| static ultramodern::events::callbacks_t events_callbacks{}; | static ultramodern::events::callbacks_t events_callbacks{}; | ||||||
| 
 | 
 | ||||||
|  | @ -213,15 +213,9 @@ void task_thread_func(uint8_t* rdram, moodycamel::LightweightSemaphore* thread_r | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|         if (!ultramodern::rsp::run_task(PASS_RDRAM task)) { |         if (!ultramodern::rsp::run_task(PASS_RDRAM task)) { | ||||||
|             fprintf(stderr, "Failed to execute task type: %" PRIu32 "\n", task->t.type); |             fprintf(stderr, "Failed to execute task type: %" PRIu32 "\n", task->t.type); | ||||||
|             assert(false); |             ULTRAMODERN_QUICK_EXIT(); | ||||||
| #       ifdef __APPLE__ |  | ||||||
|             std::_Exit(EXIT_FAILURE); |  | ||||||
| #       else |  | ||||||
|             std::quick_exit(EXIT_FAILURE); |  | ||||||
| #       endif |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         // Tell the game that the RSP has completed
 |         // Tell the game that the RSP has completed
 | ||||||
|  | @ -229,30 +223,19 @@ void task_thread_func(uint8_t* rdram, moodycamel::LightweightSemaphore* thread_r | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static std::atomic<ultramodern::GraphicsConfig> cur_config{}; |  | ||||||
| 
 |  | ||||||
| void ultramodern::set_graphics_config(const ultramodern::GraphicsConfig& config) { |  | ||||||
|     cur_config = config; |  | ||||||
|     events_context.action_queue.enqueue(UpdateConfigAction{}); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| ultramodern::GraphicsConfig ultramodern::get_graphics_config() { |  | ||||||
|     return cur_config; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| std::atomic_uint32_t display_refresh_rate = 60; | std::atomic_uint32_t display_refresh_rate = 60; | ||||||
| std::atomic<float> resolution_scale = 1.0f; | std::atomic<float> resolution_scale = 1.0f; | ||||||
| 
 | 
 | ||||||
| uint32_t ultramodern::get_target_framerate(uint32_t original) { | uint32_t ultramodern::get_target_framerate(uint32_t original) { | ||||||
|     ultramodern::GraphicsConfig graphics_config = ultramodern::get_graphics_config(); |     auto& config = ultramodern::renderer::get_graphics_config(); | ||||||
| 
 | 
 | ||||||
|     switch (graphics_config.rr_option) { |     switch (config.rr_option) { | ||||||
|         case RT64::UserConfiguration::RefreshRate::Original: |         case ultramodern::renderer::RefreshRate::Original: | ||||||
|         default: |         default: | ||||||
|             return original; |             return original; | ||||||
|         case RT64::UserConfiguration::RefreshRate::Manual: |         case ultramodern::renderer::RefreshRate::Manual: | ||||||
|             return graphics_config.rr_manual_value; |             return config.rr_manual_value; | ||||||
|         case RT64::UserConfiguration::RefreshRate::Display: |         case ultramodern::renderer::RefreshRate::Display: | ||||||
|             return display_refresh_rate.load(); |             return display_refresh_rate.load(); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | @ -269,22 +252,25 @@ void ultramodern::load_shader_cache(std::span<const char> cache_data) { | ||||||
|     events_context.action_queue.enqueue(LoadShaderCacheAction{cache_data}); |     events_context.action_queue.enqueue(LoadShaderCacheAction{cache_data}); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| std::atomic<ultramodern::RT64SetupResult> rt64_setup_result = ultramodern::RT64SetupResult::Success; | void ultramodern::trigger_config_action() { | ||||||
|  |     events_context.action_queue.enqueue(UpdateConfigAction{}); | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| void gfx_thread_func(uint8_t* rdram, moodycamel::LightweightSemaphore* thread_ready, ultramodern::WindowHandle window_handle) { | std::atomic<ultramodern::renderer::SetupResult> renderer_setup_result = ultramodern::renderer::SetupResult::Success; | ||||||
|  | 
 | ||||||
|  | void gfx_thread_func(uint8_t* rdram, moodycamel::LightweightSemaphore* thread_ready, ultramodern::renderer::WindowHandle window_handle) { | ||||||
|     bool enabled_instant_present = false; |     bool enabled_instant_present = false; | ||||||
|     using namespace std::chrono_literals; |     using namespace std::chrono_literals; | ||||||
| 
 | 
 | ||||||
|     ultramodern::set_native_thread_name("Gfx Thread"); |     ultramodern::set_native_thread_name("Gfx Thread"); | ||||||
|     ultramodern::set_native_thread_priority(ultramodern::ThreadPriority::Normal); |     ultramodern::set_native_thread_priority(ultramodern::ThreadPriority::Normal); | ||||||
| 
 | 
 | ||||||
|     ultramodern::GraphicsConfig old_config = ultramodern::get_graphics_config(); |     auto old_config = ultramodern::renderer::get_graphics_config(); | ||||||
| 
 | 
 | ||||||
|     ultramodern::RT64Context rt64{rdram, window_handle, cur_config.load().developer_mode}; |     auto renderer_context = ultramodern::renderer::create_render_context(rdram, window_handle, ultramodern::renderer::get_graphics_config().developer_mode); | ||||||
| 
 | 
 | ||||||
|     if (!rt64.valid()) { |     if (!renderer_context->valid()) { | ||||||
|         // TODO move recomp code out of ultramodern.
 |         renderer_setup_result.store(renderer_context->get_setup_result()); | ||||||
|         rt64_setup_result.store(rt64.get_setup_result()); |  | ||||||
|         // Notify the caller thread that this thread is ready.
 |         // Notify the caller thread that this thread is ready.
 | ||||||
|         thread_ready->signal(); |         thread_ready->signal(); | ||||||
|         return; |         return; | ||||||
|  | @ -307,7 +293,7 @@ void gfx_thread_func(uint8_t* rdram, moodycamel::LightweightSemaphore* thread_re | ||||||
|             if (const auto* task_action = std::get_if<SpTaskAction>(&action)) { |             if (const auto* task_action = std::get_if<SpTaskAction>(&action)) { | ||||||
|                 // Turn on instant present if the game has been started and it hasn't been turned on yet.
 |                 // Turn on instant present if the game has been started and it hasn't been turned on yet.
 | ||||||
|                 if (ultramodern::is_game_started() && !enabled_instant_present) { |                 if (ultramodern::is_game_started() && !enabled_instant_present) { | ||||||
|                     rt64.enable_instant_present(); |                     renderer_context->enable_instant_present(); | ||||||
|                     enabled_instant_present = true; |                     enabled_instant_present = true; | ||||||
|                 } |                 } | ||||||
|                 // Tell the game that the RSP completed instantly. This will allow it to queue other task types, but it won't
 |                 // Tell the game that the RSP completed instantly. This will allow it to queue other task types, but it won't
 | ||||||
|  | @ -317,32 +303,31 @@ void gfx_thread_func(uint8_t* rdram, moodycamel::LightweightSemaphore* thread_re | ||||||
|                 sp_complete(); |                 sp_complete(); | ||||||
|                 ultramodern::measure_input_latency(); |                 ultramodern::measure_input_latency(); | ||||||
| 
 | 
 | ||||||
|                 auto rt64_start = std::chrono::high_resolution_clock::now(); |                 auto renderer_start = std::chrono::high_resolution_clock::now(); | ||||||
|                 rt64.send_dl(&task_action->task); |                 renderer_context->send_dl(&task_action->task); | ||||||
|                 auto rt64_end = std::chrono::high_resolution_clock::now(); |                 auto renderer_end = std::chrono::high_resolution_clock::now(); | ||||||
|                 dp_complete(); |                 dp_complete(); | ||||||
|                 // printf("RT64 ProcessDList time: %d us\n", static_cast<u32>(std::chrono::duration_cast<std::chrono::microseconds>(rt64_end - rt64_start).count()));
 |                 // printf("Renderer ProcessDList time: %d us\n", static_cast<u32>(std::chrono::duration_cast<std::chrono::microseconds>(renderer_end - renderer_start).count()));
 | ||||||
|             } |             } | ||||||
|             else if (const auto* swap_action = std::get_if<SwapBuffersAction>(&action)) { |             else if (const auto* swap_action = std::get_if<SwapBuffersAction>(&action)) { | ||||||
|                 events_context.vi.current_buffer = events_context.vi.next_buffer; |                 events_context.vi.current_buffer = events_context.vi.next_buffer; | ||||||
|                 rt64.update_screen(swap_action->origin); |                 renderer_context->update_screen(swap_action->origin); | ||||||
|                 display_refresh_rate = rt64.get_display_framerate(); |                 display_refresh_rate = renderer_context->get_display_framerate(); | ||||||
|                 resolution_scale = rt64.get_resolution_scale(); |                 resolution_scale = renderer_context->get_resolution_scale(); | ||||||
|             } |             } | ||||||
|             else if (const auto* config_action = std::get_if<UpdateConfigAction>(&action)) { |             else if (const auto* config_action = std::get_if<UpdateConfigAction>(&action)) { | ||||||
|                 ultramodern::GraphicsConfig new_config = cur_config; |                 auto new_config = ultramodern::renderer::get_graphics_config(); | ||||||
|                 if (old_config != new_config) { |                 if (renderer_context->update_config(old_config, new_config)) { | ||||||
|                     rt64.update_config(old_config, new_config); |  | ||||||
|                     old_config = new_config; |                     old_config = new_config; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             else if (const auto* load_shader_cache_action = std::get_if<LoadShaderCacheAction>(&action)) { |             else if (const auto* load_shader_cache_action = std::get_if<LoadShaderCacheAction>(&action)) { | ||||||
|                 rt64.load_shader_cache(load_shader_cache_action->data); |                 renderer_context->load_shader_cache(load_shader_cache_action->data); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     rt64.shutdown(); |     renderer_context->shutdown(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| extern unsigned int VI_STATUS_REG; | extern unsigned int VI_STATUS_REG; | ||||||
|  | @ -512,30 +497,7 @@ void ultramodern::send_si_message(RDRAM_ARG1) { | ||||||
|     osSendMesg(PASS_RDRAM events_context.si.mq, events_context.si.msg, OS_MESG_NOBLOCK); |     osSendMesg(PASS_RDRAM events_context.si.mq, events_context.si.msg, OS_MESG_NOBLOCK); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| std::string get_graphics_api_name(ultramodern::GraphicsApi api) { | void ultramodern::init_events(RDRAM_ARG ultramodern::renderer::WindowHandle window_handle) { | ||||||
|     if (api == ultramodern::GraphicsApi::Auto) { |  | ||||||
| #if defined(_WIN32) |  | ||||||
|         api = ultramodern::GraphicsApi::D3D12; |  | ||||||
| #elif defined(__gnu_linux__) |  | ||||||
|         api = ultramodern::GraphicsApi::Vulkan; |  | ||||||
| #elif defined(__APPLE__) |  | ||||||
|         api = ultramodern::GraphicsApi::Vulkan; |  | ||||||
| #else |  | ||||||
|         static_assert(false && "Unimplemented") |  | ||||||
| #endif |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     switch (api) { |  | ||||||
|         case ultramodern::GraphicsApi::D3D12: |  | ||||||
|             return "D3D12"; |  | ||||||
|         case ultramodern::GraphicsApi::Vulkan: |  | ||||||
|             return "Vulkan"; |  | ||||||
|         default: |  | ||||||
|             return "[Unknown graphics API]"; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void ultramodern::init_events(RDRAM_ARG ultramodern::WindowHandle window_handle) { |  | ||||||
|     moodycamel::LightweightSemaphore gfx_thread_ready; |     moodycamel::LightweightSemaphore gfx_thread_ready; | ||||||
|     moodycamel::LightweightSemaphore task_thread_ready; |     moodycamel::LightweightSemaphore task_thread_ready; | ||||||
|     events_context.rdram = rdram; |     events_context.rdram = rdram; | ||||||
|  | @ -547,30 +509,32 @@ void ultramodern::init_events(RDRAM_ARG ultramodern::WindowHandle window_handle) | ||||||
|     gfx_thread_ready.wait(); |     gfx_thread_ready.wait(); | ||||||
|     task_thread_ready.wait(); |     task_thread_ready.wait(); | ||||||
| 
 | 
 | ||||||
|     ultramodern::RT64SetupResult setup_result = rt64_setup_result.load(); |     ultramodern::renderer::SetupResult setup_result = renderer_setup_result.load(); | ||||||
|     if (rt64_setup_result != ultramodern::RT64SetupResult::Success) { |     if (renderer_setup_result != ultramodern::renderer::SetupResult::Success) { | ||||||
|         auto show_rt64_error = [](const std::string& msg) { |         auto show_renderer_error = [](const std::string& msg) { | ||||||
|             std::string error_msg = "An error has been encountered on startup: " + msg; |             std::string error_msg = "An error has been encountered on startup: " + msg; | ||||||
| 
 | 
 | ||||||
|             ultramodern::error_handling::message_box(error_msg.c_str()); |             ultramodern::error_handling::message_box(error_msg.c_str()); | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         const std::string driver_os_suffix = "\nPlease make sure your GPU drivers and your OS are up to date."; |         const std::string driver_os_suffix = "\nPlease make sure your GPU drivers and your OS are up to date."; | ||||||
|         switch (rt64_setup_result) { |         switch (renderer_setup_result) { | ||||||
|             case ultramodern::RT64SetupResult::DynamicLibrariesNotFound: |             case ultramodern::renderer::SetupResult::Success: | ||||||
|                 show_rt64_error("Failed to load dynamic libraries. Make sure the DLLs are next to the recomp executable."); |  | ||||||
|                 break; |                 break; | ||||||
|             case ultramodern::RT64SetupResult::InvalidGraphicsAPI: |             case ultramodern::renderer::SetupResult::DynamicLibrariesNotFound: | ||||||
|                 show_rt64_error(get_graphics_api_name(cur_config.load().api_option) + " is not supported on this platform. Please select a different graphics API."); |                 show_renderer_error("Failed to load dynamic libraries. Make sure the DLLs are next to the recomp executable."); | ||||||
|                 break; |                 break; | ||||||
|             case ultramodern::RT64SetupResult::GraphicsAPINotFound: |             case ultramodern::renderer::SetupResult::InvalidGraphicsAPI: | ||||||
|                 show_rt64_error("Unable to initialize " + get_graphics_api_name(cur_config.load().api_option) + "." + driver_os_suffix); |                 show_renderer_error(ultramodern::renderer::get_graphics_api_name(ultramodern::renderer::get_graphics_config()) + " is not supported on this platform. Please select a different graphics API."); | ||||||
|                 break; |                 break; | ||||||
|             case ultramodern::RT64SetupResult::GraphicsDeviceNotFound: |             case ultramodern::renderer::SetupResult::GraphicsAPINotFound: | ||||||
|                 show_rt64_error("Unable to find compatible graphics device." + driver_os_suffix); |                 show_renderer_error("Unable to initialize " + ultramodern::renderer::get_graphics_api_name(ultramodern::renderer::get_graphics_config()) + "." + driver_os_suffix); | ||||||
|  |                 break; | ||||||
|  |             case ultramodern::renderer::SetupResult::GraphicsDeviceNotFound: | ||||||
|  |                 show_renderer_error("Unable to find compatible graphics device." + driver_os_suffix); | ||||||
|                 break; |                 break; | ||||||
|         } |         } | ||||||
|         throw std::runtime_error("Failed to initialize RT64"); |         throw std::runtime_error("Failed to initialize the renderer"); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     events_context.vi.thread = std::thread{ vi_thread_func }; |     events_context.vi.thread = std::thread{ vi_thread_func }; | ||||||
|  |  | ||||||
|  | @ -2,8 +2,8 @@ | ||||||
| 
 | 
 | ||||||
| #include "blockingconcurrentqueue.h" | #include "blockingconcurrentqueue.h" | ||||||
| 
 | 
 | ||||||
| #include "ultra64.h" | #include "ultramodern/ultra64.h" | ||||||
| #include "ultramodern.hpp" | #include "ultramodern/ultramodern.hpp" | ||||||
| 
 | 
 | ||||||
| struct QueuedMessage { | struct QueuedMessage { | ||||||
|     PTR(OSMesgQueue) mq; |     PTR(OSMesgQueue) mq; | ||||||
|  |  | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| #include "ultra64.h" | #include "ultramodern/ultra64.h" | ||||||
| 
 | 
 | ||||||
| #define K0BASE        0x80000000 | #define K0BASE        0x80000000 | ||||||
| #define K1BASE        0xA0000000 | #define K1BASE        0xA0000000 | ||||||
|  |  | ||||||
							
								
								
									
										69
									
								
								ultramodern/src/renderer_context.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								ultramodern/src/renderer_context.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,69 @@ | ||||||
|  | #include <cassert> | ||||||
|  | #include <mutex> | ||||||
|  | 
 | ||||||
|  | #include "ultramodern/renderer_context.hpp" | ||||||
|  | #include "ultramodern/ultramodern.hpp" | ||||||
|  | 
 | ||||||
|  | static ultramodern::renderer::callbacks_t render_callbacks{}; | ||||||
|  | 
 | ||||||
|  | void ultramodern::renderer::set_callbacks(const callbacks_t& callbacks) { | ||||||
|  |     render_callbacks = callbacks; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | std::unique_ptr<ultramodern::renderer::RendererContext> ultramodern::renderer::create_render_context(uint8_t* rdram, WindowHandle window_handle, bool developer_mode) { | ||||||
|  |     if (render_callbacks.create_render_context == nullptr) { | ||||||
|  |         error_handling::message_box("[Error] The mandatory render callback `create_render_context` was not registered"); | ||||||
|  |         ULTRAMODERN_QUICK_EXIT(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return render_callbacks.create_render_context(rdram, window_handle, developer_mode); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | std::string ultramodern::renderer::get_graphics_api_name(const GraphicsConfig& config) { | ||||||
|  |     if (render_callbacks.get_graphics_api_name != nullptr) { | ||||||
|  |         return render_callbacks.get_graphics_api_name(config); | ||||||
|  |     } | ||||||
|  |     return config.get_graphics_api_name(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | static ultramodern::renderer::GraphicsConfig graphic_config{}; | ||||||
|  | static std::mutex graphic_config_mutex; | ||||||
|  | 
 | ||||||
|  | void ultramodern::renderer::set_graphics_config(const GraphicsConfig& config) { | ||||||
|  |     std::lock_guard<std::mutex> lock(graphic_config_mutex); | ||||||
|  |     graphic_config = config; | ||||||
|  |     ultramodern::trigger_config_action(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const ultramodern::renderer::GraphicsConfig& ultramodern::renderer::get_graphics_config() { | ||||||
|  |     std::lock_guard<std::mutex> lock(graphic_config_mutex); | ||||||
|  |     return graphic_config; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | std::string ultramodern::renderer::GraphicsConfig::get_graphics_api_name() const { | ||||||
|  |     ultramodern::renderer::GraphicsApi api = api_option; | ||||||
|  | 
 | ||||||
|  |     if (api == ultramodern::renderer::GraphicsApi::Auto) { | ||||||
|  | #if defined(_WIN32) | ||||||
|  |         api = ultramodern::renderer::GraphicsApi::D3D12; | ||||||
|  | #elif defined(__gnu_linux__) | ||||||
|  |         api = ultramodern::renderer::GraphicsApi::Vulkan; | ||||||
|  | #elif defined(__APPLE__) | ||||||
|  |         // TODO: Add MoltenVK option for Mac?
 | ||||||
|  |         api = ultramodern::renderer::GraphicsApi::Vulkan; | ||||||
|  | #else | ||||||
|  |         static_assert(false && "Unimplemented") | ||||||
|  | #endif | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     switch (api) { | ||||||
|  |         case ultramodern::renderer::GraphicsApi::D3D12: | ||||||
|  |             return "D3D12"; | ||||||
|  |         case ultramodern::renderer::GraphicsApi::Vulkan: | ||||||
|  |             return "Vulkan"; | ||||||
|  |         default: | ||||||
|  |             return "[Unknown graphics API]"; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -1,325 +0,0 @@ | ||||||
| #include <memory> |  | ||||||
| #include <cstring> |  | ||||||
| 
 |  | ||||||
| #define HLSL_CPU |  | ||||||
| #include "hle/rt64_application.h" |  | ||||||
| #include "rt64_layer.hpp" |  | ||||||
| #include "rt64_render_hooks.h" |  | ||||||
| 
 |  | ||||||
| ultramodern::RT64Context::~RT64Context() = default; |  | ||||||
| 
 |  | ||||||
| static RT64::UserConfiguration::Antialiasing device_max_msaa = RT64::UserConfiguration::Antialiasing::None; |  | ||||||
| static bool sample_positions_supported = false; |  | ||||||
| static bool high_precision_fb_enabled = false; |  | ||||||
| 
 |  | ||||||
| static uint8_t DMEM[0x1000]; |  | ||||||
| static uint8_t IMEM[0x1000]; |  | ||||||
| 
 |  | ||||||
| unsigned int MI_INTR_REG = 0; |  | ||||||
| 
 |  | ||||||
| unsigned int DPC_START_REG = 0; |  | ||||||
| unsigned int DPC_END_REG = 0; |  | ||||||
| unsigned int DPC_CURRENT_REG = 0; |  | ||||||
| unsigned int DPC_STATUS_REG = 0; |  | ||||||
| unsigned int DPC_CLOCK_REG = 0; |  | ||||||
| unsigned int DPC_BUFBUSY_REG = 0; |  | ||||||
| unsigned int DPC_PIPEBUSY_REG = 0; |  | ||||||
| unsigned int DPC_TMEM_REG = 0; |  | ||||||
| 
 |  | ||||||
| unsigned int VI_STATUS_REG = 0; |  | ||||||
| unsigned int VI_ORIGIN_REG = 0; |  | ||||||
| unsigned int VI_WIDTH_REG = 0; |  | ||||||
| unsigned int VI_INTR_REG = 0; |  | ||||||
| unsigned int VI_V_CURRENT_LINE_REG = 0; |  | ||||||
| unsigned int VI_TIMING_REG = 0; |  | ||||||
| unsigned int VI_V_SYNC_REG = 0; |  | ||||||
| unsigned int VI_H_SYNC_REG = 0; |  | ||||||
| unsigned int VI_LEAP_REG = 0; |  | ||||||
| unsigned int VI_H_START_REG = 0; |  | ||||||
| unsigned int VI_V_START_REG = 0; |  | ||||||
| unsigned int VI_V_BURST_REG = 0; |  | ||||||
| unsigned int VI_X_SCALE_REG = 0; |  | ||||||
| unsigned int VI_Y_SCALE_REG = 0; |  | ||||||
| 
 |  | ||||||
| void dummy_check_interrupts() { |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| RT64::UserConfiguration::Antialiasing compute_max_supported_aa(RT64::RenderSampleCounts bits) { |  | ||||||
|     if (bits & RT64::RenderSampleCount::Bits::COUNT_2) { |  | ||||||
|         if (bits & RT64::RenderSampleCount::Bits::COUNT_4) { |  | ||||||
|             if (bits & RT64::RenderSampleCount::Bits::COUNT_8) { |  | ||||||
|                 return RT64::UserConfiguration::Antialiasing::MSAA8X; |  | ||||||
|             } |  | ||||||
|             return RT64::UserConfiguration::Antialiasing::MSAA4X; |  | ||||||
|         } |  | ||||||
|         return RT64::UserConfiguration::Antialiasing::MSAA2X; |  | ||||||
|     }; |  | ||||||
|     return RT64::UserConfiguration::Antialiasing::None; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| RT64::UserConfiguration::InternalColorFormat to_rt64(ultramodern::HighPrecisionFramebuffer option) { |  | ||||||
|     switch (option) { |  | ||||||
|         case ultramodern::HighPrecisionFramebuffer::Off: |  | ||||||
|             return RT64::UserConfiguration::InternalColorFormat::Standard; |  | ||||||
|         case ultramodern::HighPrecisionFramebuffer::On: |  | ||||||
|             return RT64::UserConfiguration::InternalColorFormat::High; |  | ||||||
|         case ultramodern::HighPrecisionFramebuffer::Auto: |  | ||||||
|             return RT64::UserConfiguration::InternalColorFormat::Automatic; |  | ||||||
|         default: |  | ||||||
|             return RT64::UserConfiguration::InternalColorFormat::OptionCount; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void set_application_user_config(RT64::Application* application, const ultramodern::GraphicsConfig& config) { |  | ||||||
|     switch (config.res_option) { |  | ||||||
|         default: |  | ||||||
|         case ultramodern::Resolution::Auto: |  | ||||||
|             application->userConfig.resolution = RT64::UserConfiguration::Resolution::WindowIntegerScale; |  | ||||||
|             application->userConfig.downsampleMultiplier = 1; |  | ||||||
|             break; |  | ||||||
|         case ultramodern::Resolution::Original: |  | ||||||
|             application->userConfig.resolution = RT64::UserConfiguration::Resolution::Manual; |  | ||||||
|             application->userConfig.resolutionMultiplier = config.ds_option; |  | ||||||
|             application->userConfig.downsampleMultiplier = config.ds_option; |  | ||||||
|             break; |  | ||||||
|         case ultramodern::Resolution::Original2x: |  | ||||||
|             application->userConfig.resolution = RT64::UserConfiguration::Resolution::Manual; |  | ||||||
|             application->userConfig.resolutionMultiplier = 2.0 * config.ds_option; |  | ||||||
|             application->userConfig.downsampleMultiplier = config.ds_option; |  | ||||||
|             break; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     switch (config.hr_option) { |  | ||||||
|         default: |  | ||||||
|         case ultramodern::HUDRatioMode::Original: |  | ||||||
|             application->userConfig.extAspectRatio = RT64::UserConfiguration::AspectRatio::Original; |  | ||||||
|             break; |  | ||||||
|         case ultramodern::HUDRatioMode::Clamp16x9: |  | ||||||
|             application->userConfig.extAspectRatio = RT64::UserConfiguration::AspectRatio::Manual; |  | ||||||
|             application->userConfig.extAspectTarget = 16.0/9.0; |  | ||||||
|             break; |  | ||||||
|         case ultramodern::HUDRatioMode::Full: |  | ||||||
|             application->userConfig.extAspectRatio = RT64::UserConfiguration::AspectRatio::Expand; |  | ||||||
|             break; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     application->userConfig.aspectRatio = config.ar_option; |  | ||||||
|     application->userConfig.antialiasing = config.msaa_option; |  | ||||||
|     application->userConfig.refreshRate = config.rr_option; |  | ||||||
|     application->userConfig.refreshRateTarget = config.rr_manual_value; |  | ||||||
|     application->userConfig.internalColorFormat = to_rt64(config.hpfb_option); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| ultramodern::RT64SetupResult map_setup_result(RT64::Application::SetupResult rt64_result) { |  | ||||||
|     switch (rt64_result) { |  | ||||||
|         case RT64::Application::SetupResult::Success: |  | ||||||
|             return ultramodern::RT64SetupResult::Success; |  | ||||||
|         case RT64::Application::SetupResult::DynamicLibrariesNotFound: |  | ||||||
|             return ultramodern::RT64SetupResult::DynamicLibrariesNotFound; |  | ||||||
|         case RT64::Application::SetupResult::InvalidGraphicsAPI: |  | ||||||
|             return ultramodern::RT64SetupResult::InvalidGraphicsAPI; |  | ||||||
|         case RT64::Application::SetupResult::GraphicsAPINotFound: |  | ||||||
|             return ultramodern::RT64SetupResult::GraphicsAPINotFound; |  | ||||||
|         case RT64::Application::SetupResult::GraphicsDeviceNotFound: |  | ||||||
|             return ultramodern::RT64SetupResult::GraphicsDeviceNotFound; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     fprintf(stderr, "Unhandled `RT64::Application::SetupResult` ?\n"); |  | ||||||
|     assert(false); |  | ||||||
|     std::exit(EXIT_FAILURE); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| ultramodern::RT64Context::RT64Context(uint8_t* rdram, ultramodern::WindowHandle window_handle, bool debug) { |  | ||||||
|     static unsigned char dummy_rom_header[0x40]; |  | ||||||
|     set_rt64_hooks(); |  | ||||||
| 
 |  | ||||||
|     // Set up the RT64 application core fields.
 |  | ||||||
|     RT64::Application::Core appCore{}; |  | ||||||
| #if defined(_WIN32) |  | ||||||
|     appCore.window = window_handle.window; |  | ||||||
| #elif defined(__ANDROID__) |  | ||||||
|     assert(false && "Unimplemented"); |  | ||||||
| #elif defined(__linux__) |  | ||||||
|     appCore.window.display = window_handle.display; |  | ||||||
|     appCore.window.window = window_handle.window; |  | ||||||
| #elif defined(__APPLE__) |  | ||||||
|     appCore.window.window = window_handle.window; |  | ||||||
|     appCore.window.view = window_handle.view; |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
|     appCore.checkInterrupts = dummy_check_interrupts; |  | ||||||
| 
 |  | ||||||
|     appCore.HEADER = dummy_rom_header; |  | ||||||
|     appCore.RDRAM = rdram; |  | ||||||
|     appCore.DMEM = DMEM; |  | ||||||
|     appCore.IMEM = IMEM; |  | ||||||
| 
 |  | ||||||
|     appCore.MI_INTR_REG = &MI_INTR_REG; |  | ||||||
| 
 |  | ||||||
|     appCore.DPC_START_REG = &DPC_START_REG; |  | ||||||
|     appCore.DPC_END_REG = &DPC_END_REG; |  | ||||||
|     appCore.DPC_CURRENT_REG = &DPC_CURRENT_REG; |  | ||||||
|     appCore.DPC_STATUS_REG = &DPC_STATUS_REG; |  | ||||||
|     appCore.DPC_CLOCK_REG = &DPC_CLOCK_REG; |  | ||||||
|     appCore.DPC_BUFBUSY_REG = &DPC_BUFBUSY_REG; |  | ||||||
|     appCore.DPC_PIPEBUSY_REG = &DPC_PIPEBUSY_REG; |  | ||||||
|     appCore.DPC_TMEM_REG = &DPC_TMEM_REG; |  | ||||||
| 
 |  | ||||||
|     appCore.VI_STATUS_REG = &VI_STATUS_REG; |  | ||||||
|     appCore.VI_ORIGIN_REG = &VI_ORIGIN_REG; |  | ||||||
|     appCore.VI_WIDTH_REG = &VI_WIDTH_REG; |  | ||||||
|     appCore.VI_INTR_REG = &VI_INTR_REG; |  | ||||||
|     appCore.VI_V_CURRENT_LINE_REG = &VI_V_CURRENT_LINE_REG; |  | ||||||
|     appCore.VI_TIMING_REG = &VI_TIMING_REG; |  | ||||||
|     appCore.VI_V_SYNC_REG = &VI_V_SYNC_REG; |  | ||||||
|     appCore.VI_H_SYNC_REG = &VI_H_SYNC_REG; |  | ||||||
|     appCore.VI_LEAP_REG = &VI_LEAP_REG; |  | ||||||
|     appCore.VI_H_START_REG = &VI_H_START_REG; |  | ||||||
|     appCore.VI_V_START_REG = &VI_V_START_REG; |  | ||||||
|     appCore.VI_V_BURST_REG = &VI_V_BURST_REG; |  | ||||||
|     appCore.VI_X_SCALE_REG = &VI_X_SCALE_REG; |  | ||||||
|     appCore.VI_Y_SCALE_REG = &VI_Y_SCALE_REG; |  | ||||||
| 
 |  | ||||||
|     // Set up the RT64 application configuration fields.
 |  | ||||||
|     RT64::ApplicationConfiguration appConfig; |  | ||||||
|     appConfig.useConfigurationFile = false; |  | ||||||
| 
 |  | ||||||
|     // Create the RT64 application.
 |  | ||||||
|     app = std::make_unique<RT64::Application>(appCore, appConfig); |  | ||||||
| 
 |  | ||||||
|     // Set initial user config settings based on the current settings.
 |  | ||||||
|     ultramodern::GraphicsConfig cur_config = ultramodern::get_graphics_config(); |  | ||||||
|     set_application_user_config(app.get(), cur_config); |  | ||||||
|     app->userConfig.developerMode = debug; |  | ||||||
|     // Force gbi depth branches to prevent LODs from kicking in.
 |  | ||||||
|     app->enhancementConfig.f3dex.forceBranch = true; |  | ||||||
|     // Scale LODs based on the output resolution.
 |  | ||||||
|     app->enhancementConfig.textureLOD.scale = true; |  | ||||||
|     // Pick an API if the user has set an override.
 |  | ||||||
|     switch (cur_config.api_option) { |  | ||||||
|         case ultramodern::GraphicsApi::D3D12: |  | ||||||
|             app->userConfig.graphicsAPI = RT64::UserConfiguration::GraphicsAPI::D3D12; |  | ||||||
|             break; |  | ||||||
|         case ultramodern::GraphicsApi::Vulkan: |  | ||||||
|             app->userConfig.graphicsAPI = RT64::UserConfiguration::GraphicsAPI::Vulkan; |  | ||||||
|             break; |  | ||||||
|         default: |  | ||||||
|         case ultramodern::GraphicsApi::Auto: |  | ||||||
|             // Don't override if auto is selected.
 |  | ||||||
|             break; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // Set up the RT64 application.
 |  | ||||||
|     uint32_t thread_id = 0; |  | ||||||
| #ifdef _WIN32 |  | ||||||
|     thread_id = window_handle.thread_id; |  | ||||||
| #endif |  | ||||||
|     setup_result = map_setup_result(app->setup(thread_id)); |  | ||||||
|     if (setup_result != ultramodern::RT64SetupResult::Success) { |  | ||||||
|         app = nullptr; |  | ||||||
|         return; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // Set the application's fullscreen state.
 |  | ||||||
|     app->setFullScreen(cur_config.wm_option == ultramodern::WindowMode::Fullscreen); |  | ||||||
| 
 |  | ||||||
|     // Check if the selected device actually supports MSAA sample positions and MSAA for for the formats that will be used
 |  | ||||||
|     // and downgrade the configuration accordingly.
 |  | ||||||
|     if (app->device->getCapabilities().sampleLocations) { |  | ||||||
|         RT64::RenderSampleCounts color_sample_counts = app->device->getSampleCountsSupported(RT64::RenderFormat::R8G8B8A8_UNORM); |  | ||||||
|         RT64::RenderSampleCounts depth_sample_counts = app->device->getSampleCountsSupported(RT64::RenderFormat::D32_FLOAT); |  | ||||||
|         RT64::RenderSampleCounts common_sample_counts = color_sample_counts & depth_sample_counts; |  | ||||||
|         device_max_msaa = compute_max_supported_aa(common_sample_counts); |  | ||||||
|         sample_positions_supported = true; |  | ||||||
|     } |  | ||||||
|     else { |  | ||||||
|         device_max_msaa = RT64::UserConfiguration::Antialiasing::None; |  | ||||||
|         sample_positions_supported = false; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     high_precision_fb_enabled = app->shaderLibrary->usesHDR; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void ultramodern::RT64Context::send_dl(const OSTask* task) { |  | ||||||
|     app->state->rsp->reset(); |  | ||||||
|     app->interpreter->loadUCodeGBI(task->t.ucode & 0x3FFFFFF, task->t.ucode_data & 0x3FFFFFF, true); |  | ||||||
|     app->processDisplayLists(app->core.RDRAM, task->t.data_ptr & 0x3FFFFFF, 0, true); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void ultramodern::RT64Context::update_screen(uint32_t vi_origin) { |  | ||||||
|     VI_ORIGIN_REG = vi_origin; |  | ||||||
| 
 |  | ||||||
|     app->updateScreen(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void ultramodern::RT64Context::shutdown() { |  | ||||||
|     if (app != nullptr) { |  | ||||||
|         app->end(); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void ultramodern::RT64Context::update_config(const ultramodern::GraphicsConfig& old_config, const ultramodern::GraphicsConfig& new_config) { |  | ||||||
|     if (new_config.wm_option != old_config.wm_option) { |  | ||||||
|         app->setFullScreen(new_config.wm_option == ultramodern::WindowMode::Fullscreen); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     set_application_user_config(app.get(), new_config); |  | ||||||
| 
 |  | ||||||
|     app->updateUserConfig(true); |  | ||||||
| 
 |  | ||||||
|     if (new_config.msaa_option != old_config.msaa_option) { |  | ||||||
|         app->updateMultisampling(); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void ultramodern::RT64Context::enable_instant_present() { |  | ||||||
|     // Enable the present early presentation mode for minimal latency.
 |  | ||||||
|     app->enhancementConfig.presentation.mode = RT64::EnhancementConfiguration::Presentation::Mode::PresentEarly; |  | ||||||
| 
 |  | ||||||
|     app->updateEnhancementConfig(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| uint32_t ultramodern::RT64Context::get_display_framerate() { |  | ||||||
|     return app->presentQueue->ext.sharedResources->swapChainRate; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| float ultramodern::RT64Context::get_resolution_scale() { |  | ||||||
|     constexpr int ReferenceHeight = 240; |  | ||||||
|     switch (app->userConfig.resolution) { |  | ||||||
|         case RT64::UserConfiguration::Resolution::WindowIntegerScale: |  | ||||||
|             if (app->sharedQueueResources->swapChainHeight > 0) { |  | ||||||
|                 return std::max(float((app->sharedQueueResources->swapChainHeight + ReferenceHeight - 1) / ReferenceHeight), 1.0f); |  | ||||||
|             } |  | ||||||
|             else { |  | ||||||
|                 return 1.0f; |  | ||||||
|             } |  | ||||||
|         case RT64::UserConfiguration::Resolution::Manual: |  | ||||||
|             return float(app->userConfig.resolutionMultiplier); |  | ||||||
|         case RT64::UserConfiguration::Resolution::Original: |  | ||||||
|         default: |  | ||||||
|             return 1.0f; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void ultramodern::RT64Context::load_shader_cache(std::span<const char> cache_binary) { |  | ||||||
|     // TODO figure out how to avoid a copy here.
 |  | ||||||
|     std::istringstream cache_stream{std::string{cache_binary.data(), cache_binary.size()}}; |  | ||||||
| 
 |  | ||||||
|     if (!app->rasterShaderCache->loadOfflineList(cache_stream)) { |  | ||||||
|        printf("Failed to preload shader cache!\n"); |  | ||||||
|        assert(false); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| RT64::UserConfiguration::Antialiasing ultramodern::RT64MaxMSAA() { |  | ||||||
|     return device_max_msaa; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool ultramodern::RT64SamplePositionsSupported() { |  | ||||||
|     return sample_positions_supported; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool ultramodern::RT64HighPrecisionFBEnabled() { |  | ||||||
|     return high_precision_fb_enabled; |  | ||||||
| } |  | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| #include "ultramodern.hpp" | #include "ultramodern/ultramodern.hpp" | ||||||
| 
 | 
 | ||||||
| void ultramodern::schedule_running_thread(RDRAM_ARG PTR(OSThread) t_) { | void ultramodern::schedule_running_thread(RDRAM_ARG PTR(OSThread) t_) { | ||||||
|     debug_printf("[Scheduling] Adding thread %d to the running queue\n", TO_PTR(OSThread, t_)->id); |     debug_printf("[Scheduling] Adding thread %d to the running queue\n", TO_PTR(OSThread, t_)->id); | ||||||
|  |  | ||||||
|  | @ -2,8 +2,8 @@ | ||||||
| 
 | 
 | ||||||
| #include <Windows.h> | #include <Windows.h> | ||||||
| 
 | 
 | ||||||
| #include "ultra64.h" | #include "ultramodern/ultra64.h" | ||||||
| #include "ultramodern.hpp" | #include "ultramodern/ultramodern.hpp" | ||||||
| 
 | 
 | ||||||
| extern "C" unsigned int sleep(unsigned int seconds) { | extern "C" unsigned int sleep(unsigned int seconds) { | ||||||
|     Sleep(seconds * 1000); |     Sleep(seconds * 1000); | ||||||
|  |  | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| #include <cassert> | #include <cassert> | ||||||
| 
 | 
 | ||||||
| #include "ultramodern.hpp" | #include "ultramodern/ultramodern.hpp" | ||||||
| 
 | 
 | ||||||
| static PTR(OSThread) running_queue_impl = NULLPTR; | static PTR(OSThread) running_queue_impl = NULLPTR; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -3,8 +3,8 @@ | ||||||
| #include <cassert> | #include <cassert> | ||||||
| #include <string> | #include <string> | ||||||
| 
 | 
 | ||||||
| #include "ultra64.h" | #include "ultramodern/ultra64.h" | ||||||
| #include "ultramodern.hpp" | #include "ultramodern/ultramodern.hpp" | ||||||
| #include "blockingconcurrentqueue.h" | #include "blockingconcurrentqueue.h" | ||||||
| 
 | 
 | ||||||
| // Native APIs only used to set thread names for easier debugging
 | // Native APIs only used to set thread names for easier debugging
 | ||||||
|  |  | ||||||
|  | @ -3,8 +3,8 @@ | ||||||
| #include <set> | #include <set> | ||||||
| #include "blockingconcurrentqueue.h" | #include "blockingconcurrentqueue.h" | ||||||
| 
 | 
 | ||||||
| #include "ultra64.h" | #include "ultramodern/ultra64.h" | ||||||
| #include "ultramodern.hpp" | #include "ultramodern/ultramodern.hpp" | ||||||
| 
 | 
 | ||||||
| #ifdef _WIN32 | #ifdef _WIN32 | ||||||
| #define WIN32_LEAN_AND_MEAN | #define WIN32_LEAN_AND_MEAN | ||||||
|  |  | ||||||
|  | @ -1,8 +1,9 @@ | ||||||
| #include "ultra64.h" | #include "ultramodern/ultra64.h" | ||||||
| #include "ultramodern.hpp" | #include "ultramodern/ultramodern.hpp" | ||||||
| 
 | 
 | ||||||
| void ultramodern::set_callbacks( | void ultramodern::set_callbacks( | ||||||
|     const rsp::callbacks_t& rsp_callbacks, |     const rsp::callbacks_t& rsp_callbacks, | ||||||
|  |     const renderer::callbacks_t& renderer_callbacks, | ||||||
|     const audio_callbacks_t& audio_callbacks, |     const audio_callbacks_t& audio_callbacks, | ||||||
|     const input::callbacks_t& input_callbacks, |     const input::callbacks_t& input_callbacks, | ||||||
|     const gfx_callbacks_t& gfx_callbacks, |     const gfx_callbacks_t& gfx_callbacks, | ||||||
|  | @ -10,6 +11,7 @@ void ultramodern::set_callbacks( | ||||||
|     const error_handling::callbacks_t& error_handling_callbacks |     const error_handling::callbacks_t& error_handling_callbacks | ||||||
| ) { | ) { | ||||||
|     ultramodern::rsp::set_callbacks(rsp_callbacks); |     ultramodern::rsp::set_callbacks(rsp_callbacks); | ||||||
|  |     ultramodern::renderer::set_callbacks(renderer_callbacks); | ||||||
|     ultramodern::set_audio_callbacks(audio_callbacks); |     ultramodern::set_audio_callbacks(audio_callbacks); | ||||||
|     ultramodern::input::set_callbacks(input_callbacks); |     ultramodern::input::set_callbacks(input_callbacks); | ||||||
|     (void)gfx_callbacks; // nothing yet
 |     (void)gfx_callbacks; // nothing yet
 | ||||||
|  | @ -17,7 +19,7 @@ void ultramodern::set_callbacks( | ||||||
|     ultramodern::error_handling::set_callbacks(error_handling_callbacks); |     ultramodern::error_handling::set_callbacks(error_handling_callbacks); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ultramodern::preinit(RDRAM_ARG ultramodern::WindowHandle window_handle) { | void ultramodern::preinit(RDRAM_ARG ultramodern::renderer::WindowHandle window_handle) { | ||||||
|     ultramodern::set_main_thread(); |     ultramodern::set_main_thread(); | ||||||
|     ultramodern::init_events(PASS_RDRAM window_handle); |     ultramodern::init_events(PASS_RDRAM window_handle); | ||||||
|     ultramodern::init_timers(PASS_RDRAM1); |     ultramodern::init_timers(PASS_RDRAM1); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Anghelo Carvajal
						Anghelo Carvajal