addon.cpp things - clshortfuse/renodx GitHub Wiki

Swap chain proxy (= Final shader)

Example: addon.cpp / final pixel / final vertex

Required in addon.cpp:

      renodx::mods::swapchain::use_resource_cloning = true;
      //renodx::mods::swapchain::swapchain_proxy_compatibility_mode = true;
      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;

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

Note: compatibility_mode allows REST to access resources drawn on swapchain. Otherwise, cloning is preferred for efficiency (& possibly quality with 10bit swapchain).

swap_chain_proxy_vertex_shader.vs_X_X.hlsl content:

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);
}

swap_chain_proxy_pixel_shader.ps_X_X.hlsl content:

Texture2D t0 : register(t0);
SamplerState s0 : register(s0);
float4 main(float4 vpos : SV_POSITION, float2 uv : TEXCOORD0) : SV_TARGET {
  float4 color = t0.Sample(s0, uv);
  //color.rgb = ...;
  color.a = 1.f;
  return color;
}

Shader_hash based upgrade

Here is what's required to upgrade targets based on shader hashes. Everything happens in addon.cpp file.

The following functions can be placed in namespace. Ignore wrapping blocs, they're just indicators:

//----what usually preceeds in addon.cpp----//
#include "../../utils/settings.hpp"
#include "./shared.h"

namespace {

ShaderInjectData shader_injection;
//----what usually preceeds in addon.cpp----//
// DX11 Only
#define UpgradeRTVReplaceShader(value)       \
  {                                          \
      value,                                 \
      {                                      \
          .crc32 = value,                    \
          .code = __##value,                 \
          .on_draw = [](auto* cmd_list) {                                                             \
            auto rtvs = renodx::utils::swapchain::GetRenderTargets(cmd_list);                         \
            bool changed = false;                                                                     \
            for (auto rtv : rtvs) {                                                                   \
              changed = renodx::mods::swapchain::ActivateCloneHotSwap(cmd_list->get_device(), rtv);   \
            }                                                                                         \
            if (changed) {                                                                            \
              renodx::mods::swapchain::FlushDescriptors(cmd_list);                                    \
              renodx::mods::swapchain::RewriteRenderTargets(cmd_list, rtvs.size(), rtvs.data(), {0}); \
            }                                                                                         \
            return true; }, \
      },                                     \
  }

#define UpgradeRTVShader(value)              \
  {                                          \
      value,                                 \
      {                                      \
          .crc32 = value,                    \
          .on_draw = [](auto* cmd_list) {                                                           \
            auto rtvs = renodx::utils::swapchain::GetRenderTargets(cmd_list);                       \
            bool changed = false;                                                                   \
            for (auto rtv : rtvs) {                                                                 \
              changed = renodx::mods::swapchain::ActivateCloneHotSwap(cmd_list->get_device(), rtv); \
            }                                                                                       \
            if (changed) {                                                                          \
              renodx::mods::swapchain::FlushDescriptors(cmd_list);                                  \
              renodx::mods::swapchain::RewriteRenderTargets(cmd_list, rtvs.size(), rtvs.data(), {0});      \
            }                                                                                       \
            return true; }, \
      },                                     \
  }

renodx::mods::shader::CustomShaders custom_shaders = {
    CustomShaderEntry(0xFFFFFFFF),
    CustomShaderEntry(0xFFFFFFF),

    UpgradeRTVReplaceShader(0xFFFFFFFF),      // tonemapper > upgrade RTV & replace shader

    UpgradeRTVShader(0xFFFFFFFF),      // clamping resource 1 > upgrade RTV only
    UpgradeRTVShader(0xFFFFFFFF),      // clamping resource 2
  };
//----what usually follows in addon.cpp----//
renodx::utils::settings::Settings settings = {
    new renodx::utils::settings::Setting{
//----what usually follows in addon.cpp----//

Then you need resource cloning enabled and hotswap on corresponding resource upgrade. Again ignore wrapping blocs.

//----what usually preceeds in addon.cpp----//
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;
//----what usually preceeds in addon.cpp----//
      renodx::mods::swapchain::use_resource_cloning = true;

      renodx::mods::swapchain::swap_chain_upgrade_targets.push_back({
          .old_format = reshade::api::format::r8g8b8a8_unorm,  // adjust to your needs
          .new_format = reshade::api::format::r16g16b16a16_float,
          //.ignore_size = true, // usual stuff can be used, but only both below are required
          .use_resource_view_cloning = true,
          .use_resource_view_hot_swap = true,
      });
//----what usually follows in addon.cpp----//
      break;
    case DLL_PROCESS_DETACH:
      reshade::unregister_addon(h_module);
      break;
  }
//----what usually follows in addon.cpp----//

Perceptual film grain

In addon.cpp:

// at the top
#define NOMINMAX

#include <chrono>
#include <random>

// slider
    new renodx::utils::settings::Setting{
        .key = "FxFilmGrainStrength",
        .binding = &CUSTOM_FILM_GRAIN_STRENGTH,
        .default_value = 50.f,
        .label = "Film Grain Strength",
        .section = "Effects",
        .max = 100.f,
        .parse = [](float value) { return value * 0.02f; },
    },

// function
void OnPresent(
    reshade::api::command_queue* queue,
    reshade::api::swapchain* swapchain,
    const reshade::api::rect* source_rect,
    const reshade::api::rect* dest_rect,
    uint32_t dirty_rect_count,
    const reshade::api::rect* dirty_rects) {
    static std::mt19937 random_generator(std::chrono::system_clock::now().time_since_epoch().count());
    static auto random_range = static_cast<float>(std::mt19937::max() - std::mt19937::min());
  CUSTOM_RANDOM = static_cast<float>(random_generator() + std::mt19937::min()) / random_range;
}

// load/unload function in DllMain
      reshade::register_event<reshade::addon_event::present>(OnPresent);
      break;
    case DLL_PROCESS_DETACH:
      reshade::unregister_addon(h_module);
      reshade::unregister_event<reshade::addon_event::present>(OnPresent);
      break;
  }

In shared.h:

#define CUSTOM_FILM_GRAIN_STRENGTH             shader_injection.custom_film_grain_strength
#define CUSTOM_RANDOM                          shader_injection.custom_random

// Must be 32bit aligned
// Should be 4x32
struct ShaderInjectData {
  float custom_film_grain_strength;
  float custom_random;
};

In shader.hlsl:

float3 grained_color = renodx::effects::ApplyFilmGrain(
        linearColor.rgb,
        TEXCOORD.xy,
        CUSTOM_RANDOM,
        CUSTOM_FILM_GRAIN_STRENGTH * 0.03f);
⚠️ **GitHub.com Fallback** ⚠️