Skip to content

Commit

Permalink
refactor(swapchain): move resizebuffer and setcolorspace to utils
Browse files Browse the repository at this point in the history
  • Loading branch information
clshortfuse committed Aug 1, 2024
1 parent c3c8375 commit 7becb38
Show file tree
Hide file tree
Showing 2 changed files with 161 additions and 130 deletions.
134 changes: 4 additions & 130 deletions src/mods/swapchain.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,6 @@ struct __declspec(uuid("0a2b51ad-ef13-4010-81a4-37a4a0f857a6")) CommandListData

static std::vector<SwapChainUpgradeTarget> swap_chain_upgrade_targets = {};

static reshade::api::effect_runtime* current_effect_runtime = nullptr;
static reshade::api::color_space current_color_space = reshade::api::color_space::unknown;
static reshade::api::format target_format = reshade::api::format::r16g16b16a16_float;
static reshade::api::color_space target_color_space = reshade::api::color_space::extended_srgb_linear;

Expand Down Expand Up @@ -294,42 +292,7 @@ static bool OnCreateSwapchain(reshade::api::swapchain_desc& desc, void* hwnd) {
|| (old_present_flags != desc.present_flags);
}

static bool ChangeColorSpace(reshade::api::swapchain* swapchain, reshade::api::color_space color_space) {
DXGI_COLOR_SPACE_TYPE dx_color_space = DXGI_COLOR_SPACE_CUSTOM;
switch (color_space) {
case reshade::api::color_space::srgb_nonlinear: dx_color_space = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709; break;
case reshade::api::color_space::extended_srgb_linear: dx_color_space = DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709; break;
case reshade::api::color_space::hdr10_st2084: dx_color_space = DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020; break;
case reshade::api::color_space::hdr10_hlg: dx_color_space = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P2020; break;
default: return false;
}

auto* native_swapchain = reinterpret_cast<IDXGISwapChain*>(swapchain->get_native());

IDXGISwapChain4* swapchain4;

if (!SUCCEEDED(native_swapchain->QueryInterface(IID_PPV_ARGS(&swapchain4)))) {
reshade::log_message(reshade::log_level::error, "changeColorSpace(Failed to get native swap chain)");
return false;
}

const HRESULT hr = swapchain4->SetColorSpace1(dx_color_space);
swapchain4->Release();
swapchain4 = nullptr;
if (!SUCCEEDED(hr)) {
return false;
}

current_color_space = color_space;

if (current_effect_runtime != nullptr) {
current_effect_runtime->set_color_space(current_color_space);
} else {
reshade::log_message(reshade::log_level::warning, "changeColorSpace(effectRuntimeNotSet)");
}

return true;
}

static void CheckSwapchainSize(
reshade::api::swapchain* swapchain,
Expand Down Expand Up @@ -385,72 +348,7 @@ static void CheckSwapchainSize(
}
}

static void ResizeBuffer(
reshade::api::swapchain* swapchain) {
auto* native_swapchain = reinterpret_cast<IDXGISwapChain*>(swapchain->get_native());

IDXGISwapChain4* swapchain4;

if (FAILED(native_swapchain->QueryInterface(IID_PPV_ARGS(&swapchain4)))) {
reshade::log_message(reshade::log_level::error, "resize_buffer(Failed to get native swap chain)");
return;
}

DXGI_SWAP_CHAIN_DESC1 desc;
if (FAILED(swapchain4->GetDesc1(&desc))) {
reshade::log_message(reshade::log_level::error, "resize_buffer(Failed to get desc)");
swapchain4->Release();
swapchain4 = nullptr;
return;
}

auto new_format = (target_format == reshade::api::format::r16g16b16a16_float)
? DXGI_FORMAT_R16G16B16A16_FLOAT
: DXGI_FORMAT_R10G10B10A2_UNORM;
if (desc.Format == new_format) {
reshade::log_message(reshade::log_level::debug, "resize_buffer(Format OK)");
swapchain4->Release();
swapchain4 = nullptr;
return;
}
reshade::log_message(reshade::log_level::debug, "resize_buffer(Resizing...)");

const HRESULT hr = swapchain4->ResizeBuffers(
desc.BufferCount == 1 ? 2 : 0,
desc.Width,
desc.Height,
new_format,
desc.Flags);

swapchain4->Release();
swapchain4 = nullptr;

if (hr == DXGI_ERROR_INVALID_CALL) {
std::stringstream s;
s << "mods::swapchain::ResizeBuffer(DXGI_ERROR_INVALID_CALL";
s << ", BufferCount = " << desc.BufferCount;
s << ", Width = " << desc.Width;
s << ", Height = " << desc.Height;
s << ", Format = " << desc.Format;
s << ", Flags = 0x" << std::hex << desc.Flags << std::dec;
s << ')';
reshade::log_message(reshade::log_level::error, s.str().c_str());
return;
}
std::stringstream s;
s << "mods::swapchain::ResizeBuffer(";
s << "resize: " << hr;
s << ")";
reshade::log_message(reshade::log_level::info, s.str().c_str());

// Reshade doesn't actually inspect colorspace
// auto colorspace = swapchain->get_color_space();
if (ChangeColorSpace(swapchain, target_color_space)) {
reshade::log_message(reshade::log_level::info, "resize_buffer(Color Space: OK)");
} else {
reshade::log_message(reshade::log_level::error, "resize_buffer(Color Space: Failed.)");
}
}

static void OnPresentForResizeBuffer(
reshade::api::command_queue* queue,
Expand All @@ -461,7 +359,7 @@ static void OnPresentForResizeBuffer(
const reshade::api::rect* dirty_rects) {
if (use_resize_buffer_on_demand && !use_resize_buffer_on_present) return;
reshade::unregister_event<reshade::addon_event::present>(OnPresentForResizeBuffer);
ResizeBuffer(swapchain);
renodx::utils::swapchain::ResizeBuffer(swapchain, target_format, target_color_space);
}

static void OnInitSwapchain(reshade::api::swapchain* swapchain) {
Expand All @@ -488,17 +386,11 @@ static void OnInitSwapchain(reshade::api::swapchain* swapchain) {
if (use_resize_buffer_on_demand || use_resize_buffer_on_present) {
reshade::register_event<reshade::addon_event::present>(OnPresentForResizeBuffer);
} else if (!use_resize_buffer_on_set_full_screen) {
ResizeBuffer(swapchain);
renodx::utils::swapchain::ResizeBuffer(swapchain, target_format, target_color_space);
}
return;
}
// Reshade doesn't actually inspect colorspace
// auto colorspace = swapchain->get_color_space();
if (ChangeColorSpace(swapchain, target_color_space)) {
reshade::log_message(reshade::log_level::info, "initSwapChain(Color Space: OK)");
} else {
reshade::log_message(reshade::log_level::error, "initSwapChain(Color Space: Failed.)");
}
renodx::utils::swapchain::ChangeColorSpace(swapchain, target_color_space);
}

static bool OnCreateResource(
Expand Down Expand Up @@ -2426,24 +2318,10 @@ static void OnBarrier(
}
}

static void OnInitEffectRuntime(reshade::api::effect_runtime* runtime) {
current_effect_runtime = runtime;
reshade::log_message(reshade::log_level::info, "Effect runtime created.");
if (current_color_space != reshade::api::color_space::unknown) {
runtime->set_color_space(current_color_space);
reshade::log_message(reshade::log_level::info, "Effect runtime colorspace updated.");
}
}

static void OnDestroyEffectRuntime(reshade::api::effect_runtime* runtime) {
if (current_effect_runtime == runtime) {
current_effect_runtime = nullptr;
}
}

static bool OnSetFullscreenState(reshade::api::swapchain* swapchain, bool fullscreen, void* hmonitor) {
if (use_resize_buffer && use_resize_buffer_on_set_full_screen) {
ResizeBuffer(swapchain);
renodx::utils::swapchain::ResizeBuffer(swapchain, target_format, target_color_space);
}
auto* device = swapchain->get_device();
if (device == nullptr) return false;
Expand Down Expand Up @@ -2544,8 +2422,6 @@ static void Use(DWORD fdw_reason) {
// reshade::register_event<reshade::addon_event::barrier>(on_barrier);
}

reshade::register_event<reshade::addon_event::init_effect_runtime>(OnInitEffectRuntime);
reshade::register_event<reshade::addon_event::destroy_effect_runtime>(OnDestroyEffectRuntime);

reshade::register_event<reshade::addon_event::set_fullscreen_state>(OnSetFullscreenState);

Expand All @@ -2563,8 +2439,6 @@ static void Use(DWORD fdw_reason) {
reshade::unregister_event<reshade::addon_event::create_resource_view>(OnCreateResourceView);
reshade::unregister_event<reshade::addon_event::init_resource_view>(OnInitResourceView);

reshade::unregister_event<reshade::addon_event::init_effect_runtime>(OnInitEffectRuntime);
reshade::unregister_event<reshade::addon_event::destroy_effect_runtime>(OnDestroyEffectRuntime);

reshade::unregister_event<reshade::addon_event::set_fullscreen_state>(OnSetFullscreenState);

Expand Down
157 changes: 157 additions & 0 deletions src/utils/swapchain.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@

#pragma once

#include <dxgi1_6.h>
#include <ios>
#include <mutex>
#include <unordered_set>
#include <vector>

Expand All @@ -15,6 +18,12 @@

namespace renodx::utils::swapchain {

namespace internal {
static std::shared_mutex mutex;
static reshade::api::effect_runtime* current_effect_runtime = nullptr;
static reshade::api::color_space current_color_space = reshade::api::color_space::unknown;
} // namespace internal

struct __declspec(uuid("25b7ec11-a51f-4884-a6f7-f381d198b9af")) SwapchainData {
reshade::api::swapchain_desc original_descc;
reshade::api::swapchain_desc current_desc;
Expand Down Expand Up @@ -83,6 +92,23 @@ static void OnDestroySwapchain(reshade::api::swapchain* swapchain) {
}
}

static void OnInitEffectRuntime(reshade::api::effect_runtime* runtime) {
std::unique_lock lock(internal::mutex);
internal::current_effect_runtime = runtime;
reshade::log_message(reshade::log_level::info, "Effect runtime created.");
if (internal::current_color_space != reshade::api::color_space::unknown) {
runtime->set_color_space(internal::current_color_space);
reshade::log_message(reshade::log_level::info, "Effect runtime colorspace updated.");
}
}

static void OnDestroyEffectRuntime(reshade::api::effect_runtime* runtime) {
std::unique_lock lock(internal::mutex);
if (internal::current_effect_runtime == runtime) {
internal::current_effect_runtime = nullptr;
}
}

static void OnInitCommandList(reshade::api::command_list* cmd_list) {
auto& data = cmd_list->create_private_data<CommandListData>();
}
Expand Down Expand Up @@ -185,6 +211,133 @@ static reshade::api::resource_view& GetDepthStencil(reshade::api::command_list*
return cmd_list_data.current_depth_stencil;
};

static bool IsDirectX(reshade::api::swapchain* swapchain) {
auto* device = swapchain->get_device();
switch (device->get_api()) {
case reshade::api::device_api::d3d9:
case reshade::api::device_api::d3d10:
case reshade::api::device_api::d3d11:
case reshade::api::device_api::d3d12:
return true;
default:
return false;
}
}

static bool ChangeColorSpace(reshade::api::swapchain* swapchain, reshade::api::color_space color_space) {
if (!IsDirectX(swapchain)) return false;

DXGI_COLOR_SPACE_TYPE dx_color_space = DXGI_COLOR_SPACE_CUSTOM;
switch (color_space) {
case reshade::api::color_space::srgb_nonlinear: dx_color_space = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709; break;
case reshade::api::color_space::extended_srgb_linear: dx_color_space = DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709; break;
case reshade::api::color_space::hdr10_st2084: dx_color_space = DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020; break;
case reshade::api::color_space::hdr10_hlg: dx_color_space = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P2020; break;
default: return false;
}

auto* native_swapchain = reinterpret_cast<IDXGISwapChain*>(swapchain->get_native());

IDXGISwapChain4* swapchain4;

if (!SUCCEEDED(native_swapchain->QueryInterface(IID_PPV_ARGS(&swapchain4)))) {
reshade::log_message(reshade::log_level::error, "changeColorSpace(Failed to get native swap chain)");
return false;
}

const HRESULT hr = swapchain4->SetColorSpace1(dx_color_space);
swapchain4->Release();
swapchain4 = nullptr;
if (!SUCCEEDED(hr)) {
return false;
}

std::unique_lock lock(internal::mutex);
internal::current_color_space = color_space;

if (internal::current_effect_runtime != nullptr) {
internal::current_effect_runtime->set_color_space(internal::current_color_space);
} else {
reshade::log_message(reshade::log_level::warning, "renodx::utils::swapchain::ChangeColorSpace(effectRuntimeNotSet)");
}

return true;
}

static void ResizeBuffer(
reshade::api::swapchain* swapchain,
reshade::api::format format = reshade::api::format::r16g16b16a16_float,
reshade::api::color_space color_space = reshade::api::color_space::unknown) {
if (!IsDirectX(swapchain)) return;
auto* native_swapchain = reinterpret_cast<IDXGISwapChain*>(swapchain->get_native());

IDXGISwapChain4* swapchain4;

if (FAILED(native_swapchain->QueryInterface(IID_PPV_ARGS(&swapchain4)))) {
reshade::log_message(reshade::log_level::error, "resize_buffer(Failed to get native swap chain)");
return;
}

DXGI_SWAP_CHAIN_DESC1 desc;
if (FAILED(swapchain4->GetDesc1(&desc))) {
reshade::log_message(reshade::log_level::error, "resize_buffer(Failed to get desc)");
swapchain4->Release();
swapchain4 = nullptr;
return;
}

// Reshade formats are mostly compatible with DXGI_FORMAT
auto new_format = static_cast<DXGI_FORMAT>(format);

if (desc.Format == new_format) {
reshade::log_message(reshade::log_level::debug, "resize_buffer(Format OK)");
swapchain4->Release();
swapchain4 = nullptr;
return;
}
reshade::log_message(reshade::log_level::debug, "resize_buffer(Resizing...)");

const HRESULT hr = swapchain4->ResizeBuffers(
desc.BufferCount == 1 ? 2 : 0,
desc.Width,
desc.Height,
new_format,
desc.Flags);

swapchain4->Release();
swapchain4 = nullptr;

if (hr == DXGI_ERROR_INVALID_CALL) {
std::stringstream s;
s << "mods::swapchain::ResizeBuffer(DXGI_ERROR_INVALID_CALL";
s << ", BufferCount = " << desc.BufferCount;
s << ", Width = " << desc.Width;
s << ", Height = " << desc.Height;
s << ", Format = " << desc.Format;
s << ", Flags = 0x" << std::hex << desc.Flags << std::dec;
s << ')';
reshade::log_message(reshade::log_level::error, s.str().c_str());
return;
}
{
std::stringstream s;
s << "mods::swapchain::ResizeBuffer(";
s << "resize: " << hr;
s << ")";
reshade::log_message(reshade::log_level::info, s.str().c_str());
}

// Reshade doesn't actually inspect colorspace
// auto colorspace = swapchain->get_color_space();
if (color_space != reshade::api::color_space::unknown) {
if (ChangeColorSpace(swapchain, color_space)) {
reshade::log_message(reshade::log_level::info, "resize_buffer(Color Space: OK)");
} else {
reshade::log_message(reshade::log_level::error, "resize_buffer(Color Space: Failed.)");
}
}
}

static bool attached = false;

inline void Use(DWORD fdw_reason) {
Expand All @@ -200,6 +353,8 @@ inline void Use(DWORD fdw_reason) {
reshade::register_event<reshade::addon_event::init_command_list>(OnInitCommandList);
reshade::register_event<reshade::addon_event::destroy_command_list>(OnDestroyCommandList);
reshade::register_event<reshade::addon_event::bind_render_targets_and_depth_stencil>(OnBindRenderTargetsAndDepthStencil);
reshade::register_event<reshade::addon_event::init_effect_runtime>(OnInitEffectRuntime);
reshade::register_event<reshade::addon_event::destroy_effect_runtime>(OnDestroyEffectRuntime);

break;
case DLL_PROCESS_DETACH:
Expand All @@ -209,6 +364,8 @@ inline void Use(DWORD fdw_reason) {
reshade::unregister_event<reshade::addon_event::destroy_swapchain>(OnDestroySwapchain);
reshade::unregister_event<reshade::addon_event::init_command_list>(OnInitCommandList);
reshade::unregister_event<reshade::addon_event::destroy_command_list>(OnDestroyCommandList);
reshade::unregister_event<reshade::addon_event::init_effect_runtime>(OnInitEffectRuntime);
reshade::unregister_event<reshade::addon_event::destroy_effect_runtime>(OnDestroyEffectRuntime);

break;
}
Expand Down

0 comments on commit 7becb38

Please sign in to comment.