22
33#include < imgui.h>
44#include < reshade.hpp>
5+ #include < vector>
56
67using namespace reshade ::api;
78
89struct __declspec (uuid(" 745350f4-bd58-479b-8ad0-81e872a9952b" )) device_data
910{
1011 effect_runtime *main_runtime = nullptr ;
1112
13+ bool _hasBackBuffer = false ;
14+ resource_desc _back_buffer_desc;
15+ uint32_t _width;
16+ uint32_t _height;
17+ format _back_buffer_format;
18+ uint16_t _back_buffer_samples;
19+ resource _back_buffer_resolved = { 0 };
20+ resource_view _back_buffer_resolved_srv = { 0 };
21+ std::vector<resource_view> _back_buffer_targets;
22+
1223 resource depth_texture = { 0 };
1324 resource_view depth_texture_view = { 0 };
14- resource vertex_rect = { 0 };
1525
16- void free_resources () {
26+ void free_depth_resources () {
1727 if (main_runtime == 0 )
1828 return ;
1929
2030 const auto & device = main_runtime->get_device ();
21- if (vertex_rect != 0 ) {
22- device->destroy_resource (vertex_rect);
23- vertex_rect = { 0 };
24- }
2531 if (depth_texture_view != 0 ) {
2632 device->destroy_resource_view (depth_texture_view);
2733 depth_texture_view = { 0 };
@@ -46,6 +52,119 @@ struct __declspec(uuid("745350f4-bd58-479b-8ad0-81e872a9952b")) device_data
4652 runtime->set_uniform_value_bool (variable, depth_texture_view != 0 );
4753 });
4854 }
55+
56+ void free_buffer_resources () {
57+ if (main_runtime == 0 )
58+ return ;
59+
60+ const auto & device = main_runtime->get_device ();
61+
62+ device->destroy_resource (_back_buffer_resolved);
63+ _back_buffer_resolved = {};
64+ device->destroy_resource_view (_back_buffer_resolved_srv);
65+ _back_buffer_resolved_srv = {};
66+
67+ for (const auto view : _back_buffer_targets)
68+ device->destroy_resource_view (view);
69+ _back_buffer_targets.clear ();
70+
71+ _hasBackBuffer = false ;
72+ }
73+
74+ bool ensure_buffers (resource back_buffer_resource) {
75+ if (main_runtime == 0 )
76+ return false ;
77+
78+ const auto & device = main_runtime->get_device ();
79+ const resource_desc back_buffer_desc = device->get_resource_desc (back_buffer_resource);
80+
81+ if (!_hasBackBuffer
82+ || back_buffer_desc.flags != _back_buffer_desc.flags
83+ || back_buffer_desc.heap != _back_buffer_desc.heap
84+ || back_buffer_desc.texture .depth_or_layers != _back_buffer_desc.texture .depth_or_layers
85+ || back_buffer_desc.texture .format != _back_buffer_desc.texture .format
86+ || back_buffer_desc.texture .height != _back_buffer_desc.texture .height
87+ || back_buffer_desc.texture .levels != _back_buffer_desc.texture .levels
88+ || back_buffer_desc.texture .samples != _back_buffer_desc.texture .samples
89+ || back_buffer_desc.texture .width != _back_buffer_desc.texture .width
90+ || back_buffer_desc.type != _back_buffer_desc.type
91+ || back_buffer_desc.usage != _back_buffer_desc.usage
92+ ) {
93+ if (_hasBackBuffer) {
94+ free_buffer_resources ();
95+ }
96+
97+ _back_buffer_desc = back_buffer_desc;
98+
99+ _width = back_buffer_desc.texture .width ;
100+ _height = back_buffer_desc.texture .height ;
101+ _back_buffer_format = format_to_default_typed (back_buffer_desc.texture .format );
102+ _back_buffer_samples = back_buffer_desc.texture .samples ;
103+
104+ // Create resolve texture and copy pipeline (do this before creating effect resources, to ensure correct back buffer format is set up)
105+ if (back_buffer_desc.texture .samples > 1
106+ // Some effects rely on there being an alpha channel available, so create resolve texture if that is not the case
107+ || (_back_buffer_format == format::r8g8b8x8_unorm || _back_buffer_format == format::b8g8r8x8_unorm)
108+ )
109+ {
110+ switch (_back_buffer_format)
111+ {
112+ case format::r8g8b8x8_unorm:
113+ _back_buffer_format = format::r8g8b8a8_unorm;
114+ break ;
115+ case format::b8g8r8x8_unorm:
116+ _back_buffer_format = format::b8g8r8a8_unorm;
117+ break ;
118+ }
119+
120+ if (!device->create_resource (
121+ resource_desc (_width, _height, 1 , 1 , format_to_typeless (_back_buffer_format), 1 , memory_heap::gpu_only, resource_usage::shader_resource | resource_usage::render_target | resource_usage::copy_dest | resource_usage::resolve_dest),
122+ nullptr , back_buffer_desc.texture .samples == 1 ? resource_usage::copy_dest : resource_usage::resolve_dest, &_back_buffer_resolved) ||
123+ !device->create_resource_view (
124+ _back_buffer_resolved,
125+ resource_usage::shader_resource,
126+ resource_view_desc (_back_buffer_format),
127+ &_back_buffer_resolved_srv) ||
128+ !device->create_resource_view (
129+ _back_buffer_resolved,
130+ resource_usage::render_target,
131+ resource_view_desc (format_to_default_typed (_back_buffer_format, 0 )),
132+ &_back_buffer_targets.emplace_back ()) ||
133+ !device->create_resource_view (
134+ _back_buffer_resolved,
135+ resource_usage::render_target,
136+ resource_view_desc (format_to_default_typed (_back_buffer_format, 1 )),
137+ &_back_buffer_targets.emplace_back ()))
138+ {
139+ free_buffer_resources ();
140+ return false ;
141+ }
142+ }
143+ // Create render targets for the back buffer resources
144+ else if (!device->create_resource_view (
145+ back_buffer_resource,
146+ resource_usage::render_target,
147+ resource_view_desc (
148+ back_buffer_desc.texture .samples > 1 ? resource_view_type::texture_2d_multisample : resource_view_type::texture_2d,
149+ format_to_default_typed (back_buffer_desc.texture .format , 0 ), 0 , 1 , 0 , 1 ),
150+ &_back_buffer_targets.emplace_back ()) ||
151+ !device->create_resource_view (
152+ back_buffer_resource,
153+ resource_usage::render_target,
154+ resource_view_desc (
155+ back_buffer_desc.texture .samples > 1 ? resource_view_type::texture_2d_multisample : resource_view_type::texture_2d,
156+ format_to_default_typed (back_buffer_desc.texture .format , 1 ), 0 , 1 , 0 , 1 ),
157+ &_back_buffer_targets.emplace_back ()))
158+ {
159+ free_buffer_resources ();
160+ return false ;
161+ }
162+
163+ _hasBackBuffer = true ;
164+ }
165+
166+ return _hasBackBuffer;
167+ }
49168};
50169
51170command_list* g_MainCommandList = 0 ;
@@ -64,7 +183,7 @@ bool supply_depth(void* pDepthTextureResource) {
64183 auto & dev_data = device->get_private_data <device_data>();
65184
66185 if (pDepthTextureResource == 0 ) {
67- dev_data.free_resources ();
186+ dev_data.free_depth_resources ();
68187 return false ;
69188 }
70189
@@ -75,8 +194,8 @@ bool supply_depth(void* pDepthTextureResource) {
75194 const resource_desc rs_depth_desc (device->get_resource_desc (rs_depth));
76195 const resource_desc rs_depth_target_desc (dev_data.depth_texture != 0 ? device->get_resource_desc (dev_data.depth_texture ) : resource_desc ());
77196
78- if (dev_data.depth_texture != 0 && (rs_depth_desc.texture .width != rs_depth_target_desc.texture .width || rs_depth_desc.texture .height != rs_depth_desc.texture .height ) || true ) {
79- dev_data.free_resources ();
197+ if (dev_data.depth_texture != 0 && (rs_depth_desc.texture .width != rs_depth_target_desc.texture .width || rs_depth_desc.texture .height != rs_depth_desc.texture .height )) {
198+ dev_data.free_depth_resources ();
80199 }
81200
82201 if (dev_data.depth_texture == 0 ) {
@@ -95,34 +214,12 @@ bool supply_depth(void* pDepthTextureResource) {
95214 if (!device->create_resource_view (dev_data.depth_texture , resource_usage::shader_resource, view_desc, &dev_data.depth_texture_view ))
96215 return false ;
97216
98- float vertex_data[4 ][3 ] = {
99- {-1 ,-1 ,0 },
100- {1 ,-1 ,0 },
101- {-1 ,1 ,0 },
102- { 1 ,1 ,0 }
103- };
104- subresource_data data;
105- data.data = &vertex_data;
106- resource_desc vertex_data_desc (sizeof (float ) * 4 * 3 , memory_heap::gpu_only, resource_usage::vertex_buffer);
107- if (!device->create_resource (vertex_data_desc, &data, resource_usage::vertex_buffer, &dev_data.vertex_rect ))
108- return false ;
109-
110217 update_effect_runtime (dev_data.main_runtime );
111218 }
112219 if (dev_data.depth_texture == 0
113- || dev_data.depth_texture_view == 0
114- || dev_data.vertex_rect == 0 )
220+ || dev_data.depth_texture_view == 0 )
115221 return false ;
116222
117- render_pass_render_target_desc rts;
118- rts.clear_color [0 ] = 1 ;
119- rts.clear_color [1 ] = 1 ;
120- rts.clear_color [2 ] = 1 ;
121- rts.clear_color [3 ] = 1 ;
122- rts.load_op = render_pass_load_op::load;
123- rts.store_op = render_pass_store_op::store;
124- rts.view = dev_data.depth_texture_view ;
125-
126223 g_MainCommandList->barrier (dev_data.depth_texture , resource_usage::shader_resource, resource_usage::copy_dest);
127224 g_MainCommandList->barrier (rs_depth, resource_usage::render_target, resource_usage::copy_source);
128225
@@ -140,7 +237,7 @@ extern "C" bool __declspec(dllexport) AdvancedfxRenderEffects(void* pRenderTarge
140237 return false ;
141238
142239 device* const device = g_MainCommandList->get_device ();
143- const auto & dev_data = device->get_private_data <device_data>();
240+ auto & dev_data = device->get_private_data <device_data>();
144241
145242 if (dev_data.main_runtime == 0 )
146243 return false ;
@@ -151,19 +248,54 @@ extern "C" bool __declspec(dllexport) AdvancedfxRenderEffects(void* pRenderTarge
151248 return true ;
152249 }
153250
154- resource_view rtv { (uint64_t )pRenderTargetView };
251+ resource back_buffer_resource { (uint64_t )pRenderTargetView };
155252
156- uint32_t width, height;
157- dev_data.main_runtime ->get_screenshot_width_and_height (&width, &height);
158-
159- const resource_desc render_target_desc = device->get_resource_desc (device->get_resource_from_view (rtv));
253+ if (!dev_data.ensure_buffers (back_buffer_resource))
254+ return false ;
160255
161- if (render_target_desc.texture .width != width || render_target_desc.texture .height != height)
162- return false ; // Ignore render targets that do not match the effect runtime back buffer dimensions
256+ // Resolve MSAA back buffer if MSAA is active or copy when format conversion is required
257+ if (dev_data._back_buffer_resolved != 0 )
258+ {
259+ if (dev_data._back_buffer_samples == 1 )
260+ {
261+ g_MainCommandList->barrier (back_buffer_resource, resource_usage::present, resource_usage::copy_source);
262+ g_MainCommandList->copy_texture_region (back_buffer_resource, 0 , nullptr , dev_data._back_buffer_resolved , 0 , nullptr );
263+ g_MainCommandList->barrier (dev_data._back_buffer_resolved , resource_usage::copy_dest, resource_usage::render_target);
264+ }
265+ else
266+ {
267+ g_MainCommandList->barrier (back_buffer_resource, resource_usage::present, resource_usage::resolve_source);
268+ g_MainCommandList->resolve_texture_region (back_buffer_resource, 0 , nullptr , dev_data._back_buffer_resolved , 0 , 0 , 0 , 0 , dev_data._back_buffer_format );
269+ g_MainCommandList->barrier (dev_data._back_buffer_resolved , resource_usage::resolve_dest, resource_usage::render_target);
270+ }
271+ }
163272
164273 supply_depth (pDepthTextureResource);
165274
166- dev_data.main_runtime ->render_effects (g_MainCommandList, rtv);
275+ if (dev_data._back_buffer_resolved != 0 )
276+ {
277+ dev_data.main_runtime ->render_effects (g_MainCommandList, dev_data._back_buffer_targets [0 ], dev_data._back_buffer_targets [1 ]);
278+ }
279+ else
280+ {
281+ g_MainCommandList->barrier (back_buffer_resource, resource_usage::present, resource_usage::render_target);
282+ dev_data.main_runtime ->render_effects (g_MainCommandList, dev_data._back_buffer_targets [0 ], dev_data._back_buffer_targets [1 ]);
283+ g_MainCommandList->barrier (back_buffer_resource, resource_usage::render_target, resource_usage::present);
284+ }
285+
286+ // Stretch main render target back into MSAA back buffer if MSAA is active or copy when format conversion is required
287+ if (dev_data._back_buffer_resolved != 0 )
288+ {
289+ const resource resources[2 ] = { back_buffer_resource, dev_data._back_buffer_resolved };
290+ const resource_usage state_old[2 ] = { resource_usage::copy_source | resource_usage::resolve_source, resource_usage::render_target };
291+ const resource_usage state_final[2 ] = { resource_usage::present, resource_usage::resolve_dest };
292+
293+ const resource_usage state_new[2 ] = { resource_usage::copy_dest, resource_usage::copy_source };
294+
295+ g_MainCommandList->barrier (2 , resources, state_old, state_new);
296+ g_MainCommandList->copy_texture_region (dev_data._back_buffer_resolved , 0 , nullptr , back_buffer_resource, 0 , nullptr );
297+ g_MainCommandList->barrier (2 , resources, state_new, state_final);
298+ }
167299
168300 return true ;
169301}
@@ -198,7 +330,8 @@ static void on_destroy_effect_runtime(effect_runtime *runtime)
198330
199331 auto &dev_data = device->get_private_data <device_data>();
200332 if (runtime == dev_data.main_runtime ) {
201- dev_data.free_resources ();
333+ dev_data.free_depth_resources ();
334+ dev_data.free_buffer_resources ();
202335 dev_data.main_runtime = nullptr ;
203336 }
204337}
@@ -214,7 +347,7 @@ static void on_draw_settings(effect_runtime *runtime)
214347 return ;
215348 }
216349
217- ImGui::TextUnformatted (" v1.0 .0" );
350+ ImGui::TextUnformatted (" v1.1 .0" );
218351 ImGui::TextUnformatted (" There are no settings currently." );
219352}
220353
0 commit comments