Guide: Using RenoDX to Upgrade HDR with Swapchain Proxy - clshortfuse/renodx GitHub Wiki

Introduction to RenoDX and HDR

RenoDX provides tools to enhance HDR (High Dynamic Range) rendering in games, enabling improved visual fidelity through features like extended color gamuts and higher luminance levels. The SwapChainPass function manages the final rendering pipeline to ensure compatibility with HDR standards.

This guide focuses on how to customize SwapChainPass using the relevant variables and their corresponding defines from BuildConfig. It also includes additional components: the addon.cpp, vertex proxy shader, and pixel proxy shader.


Customizing HDR Settings

Defines and Default Values Table

BuildConfig Variable Corresponding Define Default Value Description
swap_chain_decoding RENODX_SWAP_CHAIN_DECODING RENODX_INTERMEDIATE_ENCODING Controls the decoding method for input colors in the swapchain pipeline.
swap_chain_gamma_correction RENODX_SWAP_CHAIN_GAMMA_CORRECTION GAMMA_CORRECTION_NONE Specifies the gamma correction to apply (e.g., Gamma 2.2, Gamma 2.4, None).
swap_chain_decoding_color_space RENODX_SWAP_CHAIN_DECODING_COLOR_SPACE RENODX_INTERMEDIATE_COLOR_SPACE Sets the input color space for decoding.
swap_chain_custom_color_space RENODX_SWAP_CHAIN_CUSTOM_COLOR_SPACE COLOR_SPACE_CUSTOM_BT709D65 Applies a custom color space transformation (e.g., BT709D93, NTSCU).
swap_chain_scaling_nits RENODX_SWAP_CHAIN_SCALING_NITS RENODX_GRAPHICS_WHITE_NITS Scales luminance values for HDR rendering.
swap_chain_clamp_nits RENODX_SWAP_CHAIN_CLAMP_NITS RENODX_PEAK_WHITE_NITS Clamps maximum luminance to prevent excessive brightness.
swap_chain_clamp_color_space RENODX_SWAP_CHAIN_CLAMP_COLOR_SPACE COLOR_SPACE_NONE Specifies the color space used for clamping operations.
swap_chain_encoding RENODX_SWAP_CHAIN_ENCODING ENCODING_SCRGB Defines the encoding format for the swapchain output (e.g., scRGB, PQ).
swap_chain_encoding_color_space RENODX_SWAP_CHAIN_ENCODING_COLOR_SPACE COLOR_SPACE_BT709 Sets the target color space for encoding the output.

Values can be found in renodx::shaders::draw


How to Use Defines

To customize the swapchain behavior:

  1. Modify shared.h by adding or updating relevant defines.
  2. Save the changes—SwapChainPass will automatically apply the updates during execution.

Example configuration for HDR10 (PQ + BT2020):

#define RENODX_SWAP_CHAIN_DECODING ENCODING_SRGB
#define RENODX_SWAP_CHAIN_GAMMA_CORRECTION GAMMA_CORRECTION_GAMMA_2_4
#define RENODX_SWAP_CHAIN_SCALING_NITS 203.f
#define RENODX_SWAP_CHAIN_ENCODING ENCODING_PQ
#define RENODX_SWAP_CHAIN_ENCODING_COLOR_SPACE COLOR_SPACE_BT2020

Setting Up the Addon (addon.cpp)

The addon.cpp file includes the DllMain function, which sets up and cleans up the swapchain proxy during the appropriate phases of the addon lifecycle. Ensure that shaders.h is included so the shaders are properly recognized by C++.

#include <embed/shaders.h> // Include shaders for the swapchain proxy

BOOL APIENTRY DllMain(HMODULE h_module, DWORD fdw_reason, LPVOID lpv_reserved) {
  switch (fdw_reason) {
    case DLL_PROCESS_ATTACH:
      if (!reshade::register_addon(h_module)) return FALSE;

      // Enable resource cloning for proxying the swapchain resource
      renodx::mods::swapchain::use_resource_cloning = true;

      // Assign vertex and pixel shaders for the swapchain proxy
      renodx::mods::swapchain::swap_chain_proxy_vertex_shader = __swap_chain_proxy_vertex_shader;
      renodx::mods::swapchain::swap_chain_proxy_pixel_shader = __swap_chain_proxy_pixel_shader;
      break;

    case DLL_PROCESS_DETACH:
      reshade::unregister_addon(h_module);
      break;
  }

  renodx::mods::swapchain::Use(fdw_reason, &shader_injection);

  return TRUE;
}

Vertex Proxy Shader

The vertex shader ensures that input vertices are set up for full-screen rendering:

void main(uint id : SV_VERTEXID, out float4 pos : SV_POSITION, out float2 uv : TEXCOORD0) {
    uv.x = (id == 1) ? 2.0 : 0.0;
    uv.y = (id == 2) ? 2.0 : 0.0;
    pos = float4(uv * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0);
}

This shader simply maps the screen-space quad for the pixel shader to process.


Pixel Proxy Shader

The pixel shader processes input from the rendering pipeline and applies the SwapChainPass function:

#include "./shared.h"

Texture2D t0 : register(t0);  // Input texture
SamplerState s0 : register(s0);  // Sampler state

float4 main(float4 vpos : SV_POSITION, float2 uv : TEXCOORD0) : SV_TARGET {
  return renodx::draw::SwapChainPass(t0.Sample(s0, uv));
}
  • This shader ensures the rendering output is processed with the updated HDR settings before it reaches the display.