Update RT64 and refactor RT64 handling
This commit is contained in:
parent
c9f5786eec
commit
b334c677b9
|
@ -1,9 +1,6 @@
|
|||
[submodule "lib/RmlUi"]
|
||||
path = lib/RmlUi
|
||||
url = https://github.com/mikke89/RmlUi/
|
||||
[submodule "lib/nativefiledialog-extended"]
|
||||
path = lib/nativefiledialog-extended
|
||||
url = https://github.com/btzy/nativefiledialog-extended
|
||||
[submodule "lib/rt64"]
|
||||
path = lib/rt64
|
||||
url = https://github.com/rt64/rt64
|
||||
|
|
|
@ -22,6 +22,7 @@ set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
|||
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/lib/")
|
||||
|
||||
set(RT64_STATIC TRUE)
|
||||
add_subdirectory(${CMAKE_SOURCE_DIR}/lib/rt64 ${CMAKE_BINARY_DIR}/rt64)
|
||||
|
||||
# set(BUILD_SHARED_LIBS_SAVED "${BUILD_SHARED_LIBS}")
|
||||
|
@ -31,11 +32,8 @@ add_subdirectory(${CMAKE_SOURCE_DIR}/lib/lunasvg)
|
|||
# set(BUILD_SHARED_LIBS "${BUILD_SHARED_LIBS_SAVED}")
|
||||
SET(ENABLE_SVG_PLUGIN OFF CACHE BOOL "" FORCE)
|
||||
add_subdirectory(${CMAKE_SOURCE_DIR}/lib/RmlUi)
|
||||
add_subdirectory(${CMAKE_SOURCE_DIR}/lib/nativefiledialog-extended)
|
||||
|
||||
target_include_directories(rt64 PRIVATE ${CMAKE_BINARY_DIR}/rt64/src)
|
||||
get_target_property(RT64_BASENAME rt64 OUTPUT_NAME)
|
||||
set(RT64_DLL ${RT64_BASENAME}${CMAKE_SHARED_LIBRARY_SUFFIX})
|
||||
|
||||
# RecompiledFuncs - Library containing the primary recompiler output
|
||||
add_library(RecompiledFuncs STATIC)
|
||||
|
@ -111,6 +109,7 @@ set (SOURCES
|
|||
${CMAKE_SOURCE_DIR}/ultramodern/threads.cpp
|
||||
${CMAKE_SOURCE_DIR}/ultramodern/timer.cpp
|
||||
${CMAKE_SOURCE_DIR}/ultramodern/ultrainit.cpp
|
||||
${CMAKE_SOURCE_DIR}/ultramodern/rt64_layer.cpp
|
||||
|
||||
${CMAKE_SOURCE_DIR}/src/recomp/ai.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/recomp/cont.cpp
|
||||
|
@ -127,7 +126,6 @@ set (SOURCES
|
|||
${CMAKE_SOURCE_DIR}/src/recomp/ultra_translation.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/recomp/print.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/recomp/recomp.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/recomp/rt64_layer.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/recomp/sp.cpp
|
||||
${CMAKE_SOURCE_DIR}/src/recomp/vi.cpp
|
||||
|
||||
|
@ -175,7 +173,7 @@ target_include_directories(Zelda64Recompiled PRIVATE
|
|||
${CMAKE_SOURCE_DIR}/lib/rt64/src/rhi
|
||||
${CMAKE_SOURCE_DIR}/lib/rt64/src/render
|
||||
${CMAKE_SOURCE_DIR}/lib/freetype-windows-binaries/include
|
||||
${CMAKE_SOURCE_DIR}/lib/lib/nativefiledialog-extended/src/include
|
||||
${CMAKE_SOURCE_DIR}/lib/rt64/src/contrib/nativefiledialog-extended/src/include
|
||||
${CMAKE_BINARY_DIR}/shaders
|
||||
)
|
||||
|
||||
|
@ -214,7 +212,7 @@ if (WIN32)
|
|||
PROPERTIES
|
||||
LINK_FLAGS_DEBUG "/SUBSYSTEM:CONSOLE"
|
||||
LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup"
|
||||
LINK_FLAGS_RELWITHDEBINFO "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup"
|
||||
# LINK_FLAGS_RELWITHDEBINFO "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup"
|
||||
LINK_FLAGS_MINSIZEREL "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup"
|
||||
)
|
||||
|
||||
|
@ -257,8 +255,3 @@ target_sources(Zelda64Recompiled PRIVATE ${SOURCES})
|
|||
|
||||
set_property(TARGET Zelda64Recompiled PROPERTY VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}")
|
||||
|
||||
add_custom_command(TARGET Zelda64Recompiled POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy
|
||||
${CMAKE_BINARY_DIR}/${RT64_DLL}
|
||||
${CMAKE_SOURCE_DIR}
|
||||
MAIN_DEPENDENCY ${CMAKE_BINARY_DIR}/${RT64_DLL})
|
||||
|
|
|
@ -10,18 +10,26 @@ namespace RT64 {
|
|||
|
||||
namespace ultramodern {
|
||||
struct WindowHandle;
|
||||
}
|
||||
struct RT64Context {
|
||||
public:
|
||||
~RT64Context();
|
||||
RT64Context(uint8_t* rdram, WindowHandle window_handle, bool developer_mode);
|
||||
bool valid() { return static_cast<bool>(app); }
|
||||
|
||||
RT64::Application* RT64Init(uint8_t* rdram, ultramodern::WindowHandle window_handle, bool developer_mode);
|
||||
void RT64UpdateConfig(RT64::Application* application, const ultramodern::GraphicsConfig& old_config, const ultramodern::GraphicsConfig& new_config);
|
||||
void RT64EnableInstantPresent(RT64::Application* application);
|
||||
void RT64SendDL(uint8_t* rdram, const OSTask* task);
|
||||
void RT64UpdateScreen(uint32_t vi_origin);
|
||||
void RT64ChangeWindow();
|
||||
void RT64Shutdown();
|
||||
RT64::UserConfiguration::Antialiasing RT64MaxMSAA();
|
||||
bool RT64SamplePositionsSupported();
|
||||
uint32_t RT64GetDisplayFramerate(RT64::Application* application);
|
||||
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();
|
||||
private:
|
||||
std::unique_ptr<RT64::Application> app;
|
||||
};
|
||||
|
||||
RT64::UserConfiguration::Antialiasing RT64MaxMSAA();
|
||||
bool RT64SamplePositionsSupported();
|
||||
}
|
||||
|
||||
void set_rt64_hooks();
|
||||
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
Subproject commit 75cbdf819785d9f94855987724e30a6ba0a87e29
|
2
lib/rt64
2
lib/rt64
|
@ -1 +1 @@
|
|||
Subproject commit 3e20a48565c8b33dce93c283267262854bdd36df
|
||||
Subproject commit cbab135a3133313085cf515d2067f7b037a88a52
|
|
@ -1,303 +0,0 @@
|
|||
#include <memory>
|
||||
#include <cstring>
|
||||
// #include <Windows.h>
|
||||
|
||||
#define HLSL_CPU
|
||||
#include "hle/rt64_application.h"
|
||||
#include "rt64_layer.h"
|
||||
#include "rt64_render_hooks.h"
|
||||
|
||||
typedef struct {
|
||||
// void* hWnd;
|
||||
// void* hStatusBar;
|
||||
|
||||
// int Reserved;
|
||||
|
||||
unsigned char* HEADER; /* This is the rom header (first 40h bytes of the rom) */
|
||||
unsigned char* RDRAM;
|
||||
unsigned char* DMEM;
|
||||
unsigned char* IMEM;
|
||||
|
||||
unsigned int* MI_INTR_REG;
|
||||
|
||||
unsigned int* DPC_START_REG;
|
||||
unsigned int* DPC_END_REG;
|
||||
unsigned int* DPC_CURRENT_REG;
|
||||
unsigned int* DPC_STATUS_REG;
|
||||
unsigned int* DPC_CLOCK_REG;
|
||||
unsigned int* DPC_BUFBUSY_REG;
|
||||
unsigned int* DPC_PIPEBUSY_REG;
|
||||
unsigned int* DPC_TMEM_REG;
|
||||
|
||||
unsigned int* VI_STATUS_REG;
|
||||
unsigned int* VI_ORIGIN_REG;
|
||||
unsigned int* VI_WIDTH_REG;
|
||||
unsigned int* VI_INTR_REG;
|
||||
unsigned int* VI_V_CURRENT_LINE_REG;
|
||||
unsigned int* VI_TIMING_REG;
|
||||
unsigned int* VI_V_SYNC_REG;
|
||||
unsigned int* VI_H_SYNC_REG;
|
||||
unsigned int* VI_LEAP_REG;
|
||||
unsigned int* VI_H_START_REG;
|
||||
unsigned int* VI_V_START_REG;
|
||||
unsigned int* VI_V_BURST_REG;
|
||||
unsigned int* VI_X_SCALE_REG;
|
||||
unsigned int* VI_Y_SCALE_REG;
|
||||
|
||||
void (*CheckInterrupts)(void);
|
||||
|
||||
unsigned int version;
|
||||
unsigned int* SP_STATUS_REG;
|
||||
const unsigned int* RDRAM_SIZE;
|
||||
} GFX_INFO;
|
||||
|
||||
#ifdef _WIN32
|
||||
#define DLLEXPORT extern "C" __declspec(dllexport)
|
||||
#define DLLIMPORT extern "C" __declspec(dllimport)
|
||||
#define CALL __cdecl
|
||||
#else
|
||||
#define DLLEXPORT extern "C" __attribute__((visibility("default")))
|
||||
#define DLLIMPORT extern "C"
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
extern "C" RT64::Application* InitiateGFXWindows(GFX_INFO Gfx_Info, HWND hwnd, DWORD threadId, uint8_t debug);
|
||||
#elif defined(__ANDROID__)
|
||||
static_assert(false && "Unimplemented");
|
||||
#elif defined(__linux__)
|
||||
extern "C" RT64::Application* InitiateGFXLinux(GFX_INFO Gfx_Info, Window window, Display *display, uint8_t debug);
|
||||
#else
|
||||
static_assert(false && "Unimplemented");
|
||||
#endif
|
||||
|
||||
DLLIMPORT void ProcessRDPList(void);
|
||||
DLLIMPORT void ProcessDList(void);
|
||||
DLLIMPORT void UpdateScreen(void);
|
||||
DLLIMPORT void ChangeWindow(void);
|
||||
DLLIMPORT void PluginShutdown(void);
|
||||
|
||||
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;
|
||||
|
||||
unsigned int SP_STATUS_REG = 0;
|
||||
unsigned int RDRAM_SIZE = 0x800000;
|
||||
|
||||
static RT64::UserConfiguration::Antialiasing device_max_msaa = RT64::UserConfiguration::Antialiasing::None;
|
||||
static bool sample_positions_supported = false;
|
||||
|
||||
#define GET_FUNC(lib, name) \
|
||||
name = (decltype(name))GetProcAddress(lib, #name)
|
||||
|
||||
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::Application* RT64Init(uint8_t* rdram, ultramodern::WindowHandle window_handle, bool debug) {
|
||||
static unsigned char dummy_rom_header[0x40];
|
||||
set_rt64_hooks();
|
||||
|
||||
GFX_INFO gfx_info{};
|
||||
|
||||
gfx_info.HEADER = dummy_rom_header;
|
||||
gfx_info.RDRAM = rdram;
|
||||
gfx_info.DMEM = DMEM;
|
||||
gfx_info.IMEM = IMEM;
|
||||
|
||||
gfx_info.MI_INTR_REG = &MI_INTR_REG;
|
||||
|
||||
gfx_info.DPC_START_REG = &DPC_START_REG;
|
||||
gfx_info.DPC_END_REG = &DPC_END_REG;
|
||||
gfx_info.DPC_CURRENT_REG = &DPC_CURRENT_REG;
|
||||
gfx_info.DPC_STATUS_REG = &DPC_STATUS_REG;
|
||||
gfx_info.DPC_CLOCK_REG = &DPC_CLOCK_REG;
|
||||
gfx_info.DPC_BUFBUSY_REG = &DPC_BUFBUSY_REG;
|
||||
gfx_info.DPC_PIPEBUSY_REG = &DPC_PIPEBUSY_REG;
|
||||
gfx_info.DPC_TMEM_REG = &DPC_TMEM_REG;
|
||||
|
||||
gfx_info.VI_STATUS_REG = &VI_STATUS_REG;
|
||||
gfx_info.VI_ORIGIN_REG = &VI_ORIGIN_REG;
|
||||
gfx_info.VI_WIDTH_REG = &VI_WIDTH_REG;
|
||||
gfx_info.VI_INTR_REG = &VI_INTR_REG;
|
||||
gfx_info.VI_V_CURRENT_LINE_REG = &VI_V_CURRENT_LINE_REG;
|
||||
gfx_info.VI_TIMING_REG = &VI_TIMING_REG;
|
||||
gfx_info.VI_V_SYNC_REG = &VI_V_SYNC_REG;
|
||||
gfx_info.VI_H_SYNC_REG = &VI_H_SYNC_REG;
|
||||
gfx_info.VI_LEAP_REG = &VI_LEAP_REG;
|
||||
gfx_info.VI_H_START_REG = &VI_H_START_REG;
|
||||
gfx_info.VI_V_START_REG = &VI_V_START_REG;
|
||||
gfx_info.VI_V_BURST_REG = &VI_V_BURST_REG;
|
||||
gfx_info.VI_X_SCALE_REG = &VI_X_SCALE_REG;
|
||||
gfx_info.VI_Y_SCALE_REG = &VI_Y_SCALE_REG;
|
||||
|
||||
gfx_info.CheckInterrupts = dummy_check_interrupts;
|
||||
|
||||
gfx_info.version = 2;
|
||||
gfx_info.SP_STATUS_REG = &SP_STATUS_REG;
|
||||
gfx_info.RDRAM_SIZE = &RDRAM_SIZE;
|
||||
|
||||
#if defined(_WIN32)
|
||||
RT64::Application* ret = InitiateGFXWindows(gfx_info, window_handle.window, window_handle.thread_id, debug);
|
||||
#elif defined(__ANDROID__)
|
||||
static_assert(false && "Unimplemented");
|
||||
#elif defined(__linux__)
|
||||
RT64::Application* ret = InitiateGFXLinux(gfx_info, window_handle.window, window_handle.display, debug);
|
||||
#else
|
||||
static_assert(false && "Unimplemented");
|
||||
#endif
|
||||
|
||||
// Before configuring multisampling, make sure the device actually supports it for the formats we'll use. If it doesn't, turn off antialiasing in the configuration.
|
||||
// RT64 requires programmable sample positions for MSAA to function without issues, so check that first.
|
||||
if (ret->device->getCapabilities().sampleLocations) {
|
||||
RT64::RenderSampleCounts color_sample_counts = ret->device->getSampleCountsSupported(RT64::RenderFormat::R8G8B8A8_UNORM);
|
||||
RT64::RenderSampleCounts depth_sample_counts = ret->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;
|
||||
}
|
||||
|
||||
// Update the config to account for MSAA support.
|
||||
ultramodern::GraphicsConfig cur_config = ultramodern::get_graphics_config();
|
||||
cur_config.msaa_option = std::min(cur_config.msaa_option, device_max_msaa);
|
||||
ultramodern::set_graphics_config(cur_config);
|
||||
|
||||
// Force gbi depth branches to prevent LODs from kicking in.
|
||||
ret->enhancementConfig.f3dex.forceBranch = true;
|
||||
// Scale LODs based on the output resolution.
|
||||
ret->enhancementConfig.textureLOD.scale = true;
|
||||
|
||||
ret->updateEnhancementConfig();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void RT64SendDL(uint8_t* rdram, const OSTask* task) {
|
||||
OSTask task_copy = *task;
|
||||
task_copy.t.data_ptr &= 0x3FFFFFF;
|
||||
task_copy.t.ucode &= 0x3FFFFFF;
|
||||
task_copy.t.ucode_data &= 0x3FFFFFF;
|
||||
|
||||
memcpy(DMEM + 0xFC0, &task_copy, 0x40);
|
||||
|
||||
ProcessDList();
|
||||
}
|
||||
|
||||
void RT64UpdateScreen(uint32_t vi_origin) {
|
||||
VI_ORIGIN_REG = vi_origin;
|
||||
|
||||
UpdateScreen();
|
||||
}
|
||||
|
||||
void RT64Shutdown() {
|
||||
PluginShutdown();
|
||||
}
|
||||
|
||||
void RT64UpdateConfig(RT64::Application* application, const ultramodern::GraphicsConfig& old_config, const ultramodern::GraphicsConfig& new_config) {
|
||||
if (new_config.wm_option != old_config.wm_option) {
|
||||
application->setFullScreen(new_config.wm_option == ultramodern::WindowMode::Fullscreen);
|
||||
}
|
||||
|
||||
switch (new_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 = new_config.ds_option;
|
||||
application->userConfig.downsampleMultiplier = new_config.ds_option;
|
||||
break;
|
||||
case ultramodern::Resolution::Original2x:
|
||||
application->userConfig.resolution = RT64::UserConfiguration::Resolution::Manual;
|
||||
application->userConfig.resolutionMultiplier = 2.0 * new_config.ds_option;
|
||||
application->userConfig.downsampleMultiplier = new_config.ds_option;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (new_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 = new_config.ar_option;
|
||||
application->userConfig.antialiasing = new_config.msaa_option;
|
||||
application->userConfig.refreshRate = new_config.rr_option;
|
||||
application->userConfig.refreshRateTarget = new_config.rr_manual_value;
|
||||
|
||||
application->updateUserConfig(true);
|
||||
|
||||
if (new_config.msaa_option != old_config.msaa_option) {
|
||||
application->updateMultisampling();
|
||||
}
|
||||
}
|
||||
|
||||
void RT64EnableInstantPresent(RT64::Application* application) {
|
||||
// Enable the present early presentation mode for minimal latency.
|
||||
application->enhancementConfig.presentation.mode = RT64::EnhancementConfiguration::Presentation::Mode::PresentEarly;
|
||||
|
||||
application->updateEnhancementConfig();
|
||||
}
|
||||
|
||||
RT64::UserConfiguration::Antialiasing RT64MaxMSAA() {
|
||||
return device_max_msaa;
|
||||
}
|
||||
|
||||
bool RT64SamplePositionsSupported() {
|
||||
return sample_positions_supported;
|
||||
}
|
||||
|
||||
uint32_t RT64GetDisplayFramerate(RT64::Application* application) {
|
||||
return application->presentQueue->ext.sharedResources->swapChainRate;
|
||||
}
|
|
@ -658,10 +658,10 @@ void recomp::set_debug_mode_enabled(bool enabled) {
|
|||
}
|
||||
|
||||
void recomp::update_supported_options() {
|
||||
msaa2x_supported = RT64MaxMSAA() >= RT64::UserConfiguration::Antialiasing::MSAA2X;
|
||||
msaa4x_supported = RT64MaxMSAA() >= RT64::UserConfiguration::Antialiasing::MSAA4X;
|
||||
msaa8x_supported = RT64MaxMSAA() >= RT64::UserConfiguration::Antialiasing::MSAA8X;
|
||||
sample_positions_supported = RT64SamplePositionsSupported();
|
||||
msaa2x_supported = ultramodern::RT64MaxMSAA() >= RT64::UserConfiguration::Antialiasing::MSAA2X;
|
||||
msaa4x_supported = ultramodern::RT64MaxMSAA() >= RT64::UserConfiguration::Antialiasing::MSAA4X;
|
||||
msaa8x_supported = ultramodern::RT64MaxMSAA() >= RT64::UserConfiguration::Antialiasing::MSAA8X;
|
||||
sample_positions_supported = ultramodern::RT64SamplePositionsSupported();
|
||||
|
||||
new_options = ultramodern::get_graphics_config();
|
||||
|
||||
|
|
|
@ -243,7 +243,7 @@ public:
|
|||
|
||||
// Create vertex buffer for the screen drawer (full-screen triangle).
|
||||
screen_vertex_buffer_size_ = sizeof(Rml::Vertex) * 3;
|
||||
screen_vertex_buffer_ = render_context->device->createBuffer(RT64::RenderBufferDesc::UploadBuffer(screen_vertex_buffer_size_));
|
||||
screen_vertex_buffer_ = render_context->device->createBuffer(RT64::RenderBufferDesc::VertexBuffer(screen_vertex_buffer_size_, RT64::RenderHeapType::UPLOAD));
|
||||
Rml::Vertex *vertices = (Rml::Vertex *)(screen_vertex_buffer_->map());
|
||||
const Rml::Colourb white(255, 255, 255, 255);
|
||||
vertices[0] = Rml::Vertex{ Rml::Vector2f(-1.0f, 1.0f), white, Rml::Vector2f(0.0f, 0.0f) };
|
||||
|
|
|
@ -297,15 +297,15 @@ void gfx_thread_func(uint8_t* rdram, std::atomic_flag* thread_ready, ultramodern
|
|||
|
||||
ultramodern::GraphicsConfig old_config;
|
||||
|
||||
RT64::Application* application = RT64Init(rdram, window_handle, cur_config.load().developer_mode);
|
||||
ultramodern::RT64Context rt64{rdram, window_handle, cur_config.load().developer_mode};
|
||||
|
||||
if (!rt64.valid()) {
|
||||
throw std::runtime_error("Failed to initialize RT64!");
|
||||
}
|
||||
|
||||
// TODO move recomp code out of ultramodern.
|
||||
recomp::update_supported_options();
|
||||
|
||||
if (application == nullptr) {
|
||||
throw std::runtime_error("Failed to initialize RT64!");
|
||||
}
|
||||
|
||||
rsp_constants_init();
|
||||
|
||||
// Notify the caller thread that this thread is ready.
|
||||
|
@ -320,7 +320,7 @@ void gfx_thread_func(uint8_t* rdram, std::atomic_flag* thread_ready, ultramodern
|
|||
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.
|
||||
if (ultramodern::is_game_started() && !enabled_instant_present) {
|
||||
RT64EnableInstantPresent(application);
|
||||
rt64.enable_instant_present();
|
||||
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
|
||||
|
@ -331,20 +331,20 @@ void gfx_thread_func(uint8_t* rdram, std::atomic_flag* thread_ready, ultramodern
|
|||
ultramodern::measure_input_latency();
|
||||
|
||||
auto rt64_start = std::chrono::high_resolution_clock::now();
|
||||
RT64SendDL(rdram, &task_action->task);
|
||||
rt64.send_dl(&task_action->task);
|
||||
auto rt64_end = std::chrono::high_resolution_clock::now();
|
||||
dp_complete();
|
||||
// printf("RT64 ProcessDList time: %d us\n", static_cast<u32>(std::chrono::duration_cast<std::chrono::microseconds>(rt64_end - rt64_start).count()));
|
||||
}
|
||||
else if (const auto* swap_action = std::get_if<SwapBuffersAction>(&action)) {
|
||||
events_context.vi.current_buffer = events_context.vi.next_buffer;
|
||||
RT64UpdateScreen(swap_action->origin);
|
||||
display_refresh_rate = RT64GetDisplayFramerate(application);
|
||||
rt64.update_screen(swap_action->origin);
|
||||
display_refresh_rate = rt64.get_display_framerate();
|
||||
}
|
||||
else if (const auto* config_action = std::get_if<UpdateConfigAction>(&action)) {
|
||||
ultramodern::GraphicsConfig new_config = cur_config;
|
||||
if (old_config != new_config) {
|
||||
RT64UpdateConfig(application, old_config, new_config);
|
||||
rt64.update_config(old_config, new_config);
|
||||
old_config = new_config;
|
||||
}
|
||||
}
|
||||
|
@ -352,7 +352,7 @@ void gfx_thread_func(uint8_t* rdram, std::atomic_flag* thread_ready, ultramodern
|
|||
}
|
||||
// TODO move recomp code out of ultramodern.
|
||||
recomp::destroy_ui();
|
||||
RT64Shutdown();
|
||||
rt64.shutdown();
|
||||
}
|
||||
|
||||
extern unsigned int VI_STATUS_REG;
|
||||
|
|
|
@ -0,0 +1,237 @@
|
|||
#include <memory>
|
||||
#include <cstring>
|
||||
// #include <Windows.h>
|
||||
|
||||
#define HLSL_CPU
|
||||
#include "hle/rt64_application.h"
|
||||
#include "rt64_layer.h"
|
||||
#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 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
#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;
|
||||
|
||||
// Set up the RT64 application.
|
||||
if (!app->setup(window_handle.thread_id)) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
RT64::UserConfiguration::Antialiasing ultramodern::RT64MaxMSAA() {
|
||||
return device_max_msaa;
|
||||
}
|
||||
|
||||
bool ultramodern::RT64SamplePositionsSupported() {
|
||||
return sample_positions_supported;
|
||||
}
|
Loading…
Reference in New Issue