diff --git a/rt64 b/rt64 index ca26fb8..64b9e16 160000 --- a/rt64 +++ b/rt64 @@ -1 +1 @@ -Subproject commit ca26fb8096b9af117c668e8dfaa49fdde815c3b7 +Subproject commit 64b9e166f75b4dc44a59983b67c3e9ecc1f4cfd7 diff --git a/ultramodern/include/ultramodern/config.hpp b/ultramodern/include/ultramodern/config.hpp index a8b99e2..7212034 100644 --- a/ultramodern/include/ultramodern/config.hpp +++ b/ultramodern/include/ultramodern/config.hpp @@ -28,6 +28,12 @@ namespace ultramodern { Vulkan, OptionCount }; + enum class HighPrecisionFramebuffer { + Auto, + On, + Off, + OptionCount + }; struct GraphicsConfig { Resolution res_option; @@ -38,6 +44,7 @@ namespace ultramodern { RT64::UserConfiguration::AspectRatio ar_option; RT64::UserConfiguration::Antialiasing msaa_option; RT64::UserConfiguration::RefreshRate rr_option; + HighPrecisionFramebuffer hpfb_option; int rr_manual_value; int ds_option; bool developer_mode; @@ -70,6 +77,12 @@ namespace ultramodern { {ultramodern::GraphicsApi::D3D12, "D3D12"}, {ultramodern::GraphicsApi::Vulkan, "Vulkan"}, }); + + NLOHMANN_JSON_SERIALIZE_ENUM(ultramodern::HighPrecisionFramebuffer, { + {ultramodern::HighPrecisionFramebuffer::Auto, "Auto"}, + {ultramodern::HighPrecisionFramebuffer::On, "On"}, + {ultramodern::HighPrecisionFramebuffer::Off, "Off"}, + }); }; #endif diff --git a/ultramodern/include/ultramodern/rt64_layer.h b/ultramodern/include/ultramodern/rt64_layer.h index 0928d06..4b9f31a 100644 --- a/ultramodern/include/ultramodern/rt64_layer.h +++ b/ultramodern/include/ultramodern/rt64_layer.h @@ -32,14 +32,16 @@ namespace ultramodern { void shutdown(); void set_dummy_vi(); uint32_t get_display_framerate(); + float get_resolution_scale(); void load_shader_cache(std::span cache_binary); private: RT64SetupResult setup_result; std::unique_ptr app; }; - + RT64::UserConfiguration::Antialiasing RT64MaxMSAA(); bool RT64SamplePositionsSupported(); + bool RT64HighPrecisionFBEnabled(); } void set_rt64_hooks(); diff --git a/ultramodern/include/ultramodern/ultramodern.hpp b/ultramodern/include/ultramodern/ultramodern.hpp index 547fba1..871abee 100644 --- a/ultramodern/include/ultramodern/ultramodern.hpp +++ b/ultramodern/include/ultramodern/ultramodern.hpp @@ -122,9 +122,9 @@ void sleep_milliseconds(uint32_t millis); void sleep_until(const std::chrono::high_resolution_clock::time_point& time_point); // Graphics -void get_window_size(uint32_t& width, uint32_t& height); uint32_t get_target_framerate(uint32_t original); uint32_t get_display_refresh_rate(); +float get_resolution_scale(); void load_shader_cache(std::span cache_data); // Audio diff --git a/ultramodern/src/events.cpp b/ultramodern/src/events.cpp index 7fba7b6..9ca13c2 100644 --- a/ultramodern/src/events.cpp +++ b/ultramodern/src/events.cpp @@ -241,6 +241,7 @@ ultramodern::GraphicsConfig ultramodern::get_graphics_config() { } std::atomic_uint32_t display_refresh_rate = 60; +std::atomic resolution_scale = 1.0f; uint32_t ultramodern::get_target_framerate(uint32_t original) { ultramodern::GraphicsConfig graphics_config = ultramodern::get_graphics_config(); @@ -260,6 +261,10 @@ uint32_t ultramodern::get_display_refresh_rate() { return display_refresh_rate.load(); } +float ultramodern::get_resolution_scale() { + return resolution_scale.load(); +} + void ultramodern::load_shader_cache(std::span cache_data) { events_context.action_queue.enqueue(LoadShaderCacheAction{cache_data}); } @@ -322,6 +327,7 @@ void gfx_thread_func(uint8_t* rdram, moodycamel::LightweightSemaphore* thread_re events_context.vi.current_buffer = events_context.vi.next_buffer; rt64.update_screen(swap_action->origin); display_refresh_rate = rt64.get_display_framerate(); + resolution_scale = rt64.get_resolution_scale(); } else if (const auto* config_action = std::get_if(&action)) { ultramodern::GraphicsConfig new_config = cur_config; diff --git a/ultramodern/src/rt64_layer.cpp b/ultramodern/src/rt64_layer.cpp index 45290b1..dbc0e76 100644 --- a/ultramodern/src/rt64_layer.cpp +++ b/ultramodern/src/rt64_layer.cpp @@ -11,6 +11,7 @@ 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]; @@ -58,6 +59,19 @@ RT64::UserConfiguration::Antialiasing compute_max_supported_aa(RT64::RenderSampl 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: @@ -95,6 +109,7 @@ void set_application_user_config(RT64::Application* application, const ultramode 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) { @@ -223,6 +238,8 @@ ultramodern::RT64Context::RT64Context(uint8_t* rdram, ultramodern::WindowHandle 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) { @@ -268,6 +285,24 @@ 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 cache_binary) { // TODO figure out how to avoid a copy here. std::istringstream cache_stream{std::string{cache_binary.data(), cache_binary.size()}}; @@ -285,3 +320,7 @@ RT64::UserConfiguration::Antialiasing ultramodern::RT64MaxMSAA() { bool ultramodern::RT64SamplePositionsSupported() { return sample_positions_supported; } + +bool ultramodern::RT64HighPrecisionFBEnabled() { + return high_precision_fb_enabled; +}