addon.cpp things - clshortfuse/renodx GitHub Wiki
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;
}
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----//
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);