diff --git a/Source/Core/Core.vcxproj b/Source/Core/Core.vcxproj index 30f1f9f3..3c3e216f 100644 --- a/Source/Core/Core.vcxproj +++ b/Source/Core/Core.vcxproj @@ -608,6 +608,7 @@ + @@ -615,6 +616,7 @@ + diff --git a/Source/Core/Core.vcxproj.filters b/Source/Core/Core.vcxproj.filters index 721c82a4..5287438d 100644 --- a/Source/Core/Core.vcxproj.filters +++ b/Source/Core/Core.vcxproj.filters @@ -105,5 +105,11 @@ Includes + + Includes + + + Includes + \ No newline at end of file diff --git a/Source/Core/core.hpp b/Source/Core/core.hpp index 209b623b..7d475bc4 100644 --- a/Source/Core/core.hpp +++ b/Source/Core/core.hpp @@ -2570,6 +2570,12 @@ namespace } #endif // ENABLE_SR + // Execute all Luma callbacks. + for (const auto& callback : LumaCallbacks::on_destroy_device) + { + callback.second(); + } + device->destroy_private_data(); } @@ -2959,6 +2965,12 @@ namespace // TODO: put code to track all recently created resources and late upgraded them if the size/aspect ratio now matches the swapchain (some games resize the swapchain after resources, so in that case we should handle indirect upgrades like this) } + // Execute all Luma callbacks. + for (const auto& callback : LumaCallbacks::on_init_swapchain) + { + callback.second(); + } + game->OnInitSwapchain(swapchain); } diff --git a/Source/Core/includes/callbacks.h b/Source/Core/includes/callbacks.h new file mode 100644 index 00000000..dc1e8765 --- /dev/null +++ b/Source/Core/includes/callbacks.h @@ -0,0 +1,20 @@ +#pragma once + +#include +#include + +// struct cause maybe we want to make some members private in future +// +// So far std::unoredered_map may be the best solution for this. +// std::unordered_set could be better, but it won't work with std::function. +// std::vector could be too much manual management for the user (developer)? +// +// Signal user that callback was executed? +struct LumaCallbacks final +{ + // Executed after swapchain resize and after swapchain creation. + static inline std::unordered_map> on_init_swapchain; + + // Executed before device is destroyed. + static inline std::unordered_map> on_destroy_device; +}; \ No newline at end of file diff --git a/Source/Core/includes/instance_data.h b/Source/Core/includes/instance_data.h index eea5f224..2f7230d8 100644 --- a/Source/Core/includes/instance_data.h +++ b/Source/Core/includes/instance_data.h @@ -16,6 +16,8 @@ #include #include +#include "managed_resources.h" + // Forward declarations struct GameDeviceData; @@ -90,7 +92,7 @@ struct TraceDrawCallData AppendCommandList, ResetCommmandList, FlushCommandList, - Custom, // Custom draw call for custom passes we added/replaced + Custom, // Custom draw call for custom passes we added/replaced }; TraceDrawCallType type = TraceDrawCallType::Shader; @@ -583,6 +585,8 @@ struct __declspec(uuid("cfebf6d4-d184-4e1a-ac14-09d088e560ca")) DeviceData buffers.push_back(luma_ui_data.get()); return buffers; } + + ManagedResources managed_resources; }; struct __declspec(uuid("c5805458-2c02-4ebf-b139-38b85118d971")) SwapchainData @@ -595,5 +599,5 @@ struct __declspec(uuid("c5805458-2c02-4ebf-b139-38b85118d971")) SwapchainData std::vector> display_composition_rtvs; // Whether the original SDR (vanilla) swapchain was linear space (e.g. sRGB formats) - bool vanilla_was_linear_space = false; + bool vanilla_was_linear_space = false; }; diff --git a/Source/Core/includes/managed_resources.h b/Source/Core/includes/managed_resources.h new file mode 100644 index 00000000..403379ed --- /dev/null +++ b/Source/Core/includes/managed_resources.h @@ -0,0 +1,46 @@ +#pragma once + +#include +#include +#include +#include "com_ptr.h" + +struct ManagedResources +{ + // Key should be result of CompileTimeStringHash()! + // Example usage: shader_resource_views[CompileTimeStringHash("scene")] = srv_scene; + // Example usage: shader_resource_views["scene"_h] = srv_scene; + std::unordered_map> shader_resource_views; + std::unordered_map> render_target_views; + std::unordered_map> unordered_access_views; + std::unordered_map> depth_stencil_views; + std::unordered_map> resources; + std::unordered_map> buffers; + std::unordered_map> textures_1d; + std::unordered_map> textures_2d; + std::unordered_map> textures_3d; + std::unordered_map> input_layouts; + std::unordered_map> rasterizers; + std::unordered_map> samplers; + std::unordered_map> blends; + std::unordered_map> depth_stencils; + std::unordered_map> vertex_shaders; + std::unordered_map> compute_shaders; + std::unordered_map> pixel_shaders; + std::unordered_map> domain_shaders; + std::unordered_map> geometry_shaders; + std::unordered_map> hull_shaders; +}; + +// TODO: Move this somewhere else. +inline void ResetCOMArray(auto& array) +{ + for (auto*& ptr : array) + { + if (ptr) + { + ptr->Release(); + ptr = nullptr; + } + } +} \ No newline at end of file diff --git a/Source/Core/includes/math.h b/Source/Core/includes/math.h index 61b1d2a7..44a4054b 100644 --- a/Source/Core/includes/math.h +++ b/Source/Core/includes/math.h @@ -182,6 +182,13 @@ namespace Math return hash; } + // User-defined literal for CompileTimeStringHash. + // Usage: `"some_string"_h`, this is equivalent to `CompileTimeStringHash("some_string")`. + consteval uint32_t operator"" _h(const char* str, size_t len) + { + return CompileTimeStringHash(str); + } + uint32_t FindNextUniqueNumberInRange(uint32_t value, uint32_t min_value, uint32_t max_value, std::unordered_set excluded_values) { assert(value >= min_value && value <= max_value); diff --git a/Source/Core/utils/draw.hpp b/Source/Core/utils/draw.hpp index 079477f6..4d6c82ad 100644 --- a/Source/Core/utils/draw.hpp +++ b/Source/Core/utils/draw.hpp @@ -3,6 +3,11 @@ #include "../texture_data/SMAA_AreaTex.h" #include "../texture_data/SMAA_SearchTex.h" +#include "../includes/callbacks.h" +#include "../includes/math.h" + +using Math::operator"" _h; + enum class DrawStateStackType { // Same as "FullGraphics" but skips some states that are usually not changed by our code. @@ -1319,16 +1324,10 @@ void SanitizeNaNs(ID3D11Device* device, ID3D11DeviceContext* device_context, ID3 } } -struct DrawSMAAData +void DrawSMAA(ID3D11Device* device, ID3D11DeviceContext* device_context, DeviceData& device_data, ID3D11RenderTargetView* rtv, ID3D11ShaderResourceView* srv_color_tex, ID3D11ShaderResourceView* srv_color_tex_gamma, ID3D11ShaderResourceView* srv_predication_tex = nullptr) { - ComPtr srv_area_tex; - ComPtr srv_search_tex; - ComPtr ds_disable_depth_replace_stencil; - ComPtr ds_disable_depth_use_stencil; -}; + auto& managed_resources = device_data.managed_resources; -void DrawSMAA(ID3D11Device* device, ID3D11DeviceContext* device_context, const DeviceData& device_data, DrawSMAAData& data, ID3D11RenderTargetView* rtv, ID3D11ShaderResourceView* srv_color_tex, ID3D11ShaderResourceView* srv_color_tex_gamma, ID3D11ShaderResourceView* srv_predication_tex = nullptr) -{ // Backup IA. D3D11_PRIMITIVE_TOPOLOGY primitive_topology_original; device_context->IAGetPrimitiveTopology(&primitive_topology_original); @@ -1388,38 +1387,41 @@ void DrawSMAA(ID3D11Device* device, ID3D11DeviceContext* device_context, const D viewport.Height = tex_desc.Height; // Create DS. - [[unlikely]] if (!data.ds_disable_depth_replace_stencil) + [[unlikely]] if (!managed_resources.depth_stencils["smaa_disable_depth_replace_stencil"_h]) { CD3D11_DEPTH_STENCIL_DESC ds_desc(D3D11_DEFAULT); ds_desc.DepthEnable = FALSE; ds_desc.StencilEnable = TRUE; ds_desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_REPLACE; - ensure(device->CreateDepthStencilState(&ds_desc, data.ds_disable_depth_replace_stencil.put()), >= 0); + ensure(device->CreateDepthStencilState(&ds_desc, managed_resources.depth_stencils["smaa_disable_depth_replace_stencil"_h].put()), >= 0); } // Create DSV. - tex_desc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; - tex_desc.BindFlags = D3D11_BIND_DEPTH_STENCIL; - ensure(device->CreateTexture2D(&tex_desc, nullptr, tex.put()), >= 0); - ComPtr dsv; - ensure(device->CreateDepthStencilView(tex.get(), nullptr, dsv.put()), >= 0); + [[unlikely]] if (!managed_resources.depth_stencil_views["smaa_dsv"_h]) + { + tex_desc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; + tex_desc.BindFlags = D3D11_BIND_DEPTH_STENCIL; + ensure(device->CreateTexture2D(&tex_desc, nullptr, tex.put()), >= 0); + ensure(device->CreateDepthStencilView(tex.get(), nullptr, managed_resources.depth_stencil_views["smaa_dsv"_h].put()), >= 0); + } // Create RT and views. - tex_desc.Format = DXGI_FORMAT_R8G8_UNORM; - tex_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; - ensure(device->CreateTexture2D(&tex_desc, nullptr, tex.put()), >= 0); - ComPtr rtv_edge_detection; - ensure(device->CreateRenderTargetView(tex.get(), nullptr, rtv_edge_detection.put()), >= 0); - ComPtr srv_edge_detection; - ensure(device->CreateShaderResourceView(tex.get(), nullptr, srv_edge_detection.put()), >= 0); + [[unlikely]] if (!managed_resources.render_target_views["smaa_edge_detection"_h]) + { + tex_desc.Format = DXGI_FORMAT_R8G8_UNORM; + tex_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; + ensure(device->CreateTexture2D(&tex_desc, nullptr, tex.put()), >= 0); + ensure(device->CreateRenderTargetView(tex.get(), nullptr, managed_resources.render_target_views["smaa_edge_detection"_h].put()), >= 0); + ensure(device->CreateShaderResourceView(tex.get(), nullptr, managed_resources.shader_resource_views["smaa_edge_detection"_h].put()), >= 0); + } // Bindings. device_context->OMSetBlendState(nullptr, nullptr, UINT_MAX); - device_context->OMSetDepthStencilState(data.ds_disable_depth_replace_stencil.get(), 1); - device_context->OMSetRenderTargets(1, &rtv_edge_detection, dsv.get()); + device_context->OMSetDepthStencilState(managed_resources.depth_stencils["smaa_disable_depth_replace_stencil"_h].get(), 1); + device_context->OMSetRenderTargets(1, &managed_resources.render_target_views["smaa_edge_detection"_h], managed_resources.depth_stencil_views["smaa_dsv"_h].get()); device_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - device_context->VSSetShader(device_data.native_vertex_shaders.at(Math::CompileTimeStringHash("SMAA Edge Detection VS")).get(), nullptr, 0); - device_context->PSSetShader(device_data.native_pixel_shaders.at(Math::CompileTimeStringHash("SMAA Edge Detection PS")).get(), nullptr, 0); + device_context->VSSetShader(device_data.native_vertex_shaders.at("SMAA Edge Detection VS"_h).get(), nullptr, 0); + device_context->PSSetShader(device_data.native_pixel_shaders.at("SMAA Edge Detection PS"_h).get(), nullptr, 0); const std::array ps_samplers = { device_data.sampler_state_linear.get(), device_data.sampler_state_point.get() }; device_context->PSSetSamplers(0, ps_samplers.size(), ps_samplers.data()); const std::array ps_srvs_edge_detection = { srv_color_tex_gamma, srv_predication_tex }; @@ -1428,8 +1430,8 @@ void DrawSMAA(ID3D11Device* device, ID3D11DeviceContext* device_context, const D device_context->RSSetState(nullptr); static constexpr FLOAT clear_color[4] = {}; - device_context->ClearRenderTargetView(rtv_edge_detection.get(), clear_color); - device_context->ClearDepthStencilView(dsv.get(), D3D10_CLEAR_STENCIL, 1.0f, 0); + device_context->ClearRenderTargetView(managed_resources.render_target_views["smaa_edge_detection"_h].get(), clear_color); + device_context->ClearDepthStencilView(managed_resources.depth_stencil_views["smaa_dsv"_h].get(), D3D11_CLEAR_STENCIL, 1.0f, 0); device_context->Draw(3, 0); // @@ -1438,7 +1440,7 @@ void DrawSMAA(ID3D11Device* device, ID3D11DeviceContext* device_context, const D // // Create area texture. - [[unlikely]] if (!data.srv_area_tex) + [[unlikely]] if (!managed_resources.shader_resource_views["smaa_area_tex"_h]) { D3D11_TEXTURE2D_DESC tex_desc = {}; tex_desc.Width = AREATEX_WIDTH; @@ -1453,11 +1455,11 @@ void DrawSMAA(ID3D11Device* device, ID3D11DeviceContext* device_context, const D subresource_data.pSysMem = areaTexBytes; subresource_data.SysMemPitch = AREATEX_PITCH; ensure(device->CreateTexture2D(&tex_desc, &subresource_data, tex.put()), >= 0); - ensure(device->CreateShaderResourceView(tex.get(), nullptr, data.srv_area_tex.put()), >= 0); + ensure(device->CreateShaderResourceView(tex.get(), nullptr, managed_resources.shader_resource_views["smaa_area_tex"_h].put()), >= 0); } // Create search texture. - [[unlikely]] if (!data.srv_search_tex) + [[unlikely]] if (!managed_resources.shader_resource_views["smaa_search_tex"_h]) { D3D11_TEXTURE2D_DESC tex_desc = {}; tex_desc.Width = SEARCHTEX_WIDTH; @@ -1472,36 +1474,37 @@ void DrawSMAA(ID3D11Device* device, ID3D11DeviceContext* device_context, const D subresource_data.pSysMem = searchTexBytes; subresource_data.SysMemPitch = SEARCHTEX_PITCH; ensure(device->CreateTexture2D(&tex_desc, &subresource_data, tex.put()), >= 0); - ensure(device->CreateShaderResourceView(tex.get(), nullptr, data.srv_search_tex.put()), >= 0); + ensure(device->CreateShaderResourceView(tex.get(), nullptr, managed_resources.shader_resource_views["smaa_search_tex"_h].put()), >= 0); } // Create DS. - [[unlikely]] if (!data.ds_disable_depth_use_stencil) + [[unlikely]] if (!managed_resources.depth_stencils["smaa_disable_depth_use_stencil"_h]) { CD3D11_DEPTH_STENCIL_DESC ds_desc(D3D11_DEFAULT); ds_desc.DepthEnable = FALSE; ds_desc.StencilEnable = TRUE; ds_desc.FrontFace.StencilFunc = D3D11_COMPARISON_EQUAL; - ensure(device->CreateDepthStencilState(&ds_desc, data.ds_disable_depth_use_stencil.put()), >= 0); + ensure(device->CreateDepthStencilState(&ds_desc, managed_resources.depth_stencils["smaa_disable_depth_use_stencil"_h].put()), >= 0); } // Create RT and views. - tex_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - ensure(device->CreateTexture2D(&tex_desc, nullptr, tex.put()), >= 0); - ComPtr rtv_blending_weight_calculation; - ensure(device->CreateRenderTargetView(tex.get(), nullptr, rtv_blending_weight_calculation.put()), >= 0); - ComPtr srv_blending_weight_calculation; - ensure(device->CreateShaderResourceView(tex.get(), nullptr, srv_blending_weight_calculation.put()), >= 0); + [[unlikely]] if (!managed_resources.render_target_views["smaa_blending_weight_calculation"_h]) + { + tex_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + ensure(device->CreateTexture2D(&tex_desc, nullptr, tex.put()), >= 0); + ensure(device->CreateRenderTargetView(tex.get(), nullptr, managed_resources.render_target_views["smaa_blending_weight_calculation"_h].put()), >= 0); + ensure(device->CreateShaderResourceView(tex.get(), nullptr, managed_resources.shader_resource_views["smaa_blending_weight_calculation"_h].put()), >= 0); + } // Bindings. - device_context->OMSetDepthStencilState(data.ds_disable_depth_use_stencil.get(), 1); - device_context->OMSetRenderTargets(1, &rtv_blending_weight_calculation, dsv.get()); - device_context->VSSetShader(device_data.native_vertex_shaders.at(Math::CompileTimeStringHash("SMAA Blending Weight Calculation VS")).get(), nullptr, 0); - device_context->PSSetShader(device_data.native_pixel_shaders.at(Math::CompileTimeStringHash("SMAA Blending Weight Calculation PS")).get(), nullptr, 0); - const std::array ps_srvs_blending_weight_calculation = { srv_edge_detection.get(), data.srv_area_tex.get(), data.srv_search_tex.get() }; + device_context->OMSetDepthStencilState(managed_resources.depth_stencils["smaa_disable_depth_use_stencil"_h].get(), 1); + device_context->OMSetRenderTargets(1, &managed_resources.render_target_views["smaa_blending_weight_calculation"_h], managed_resources.depth_stencil_views["smaa_dsv"_h].get()); + device_context->VSSetShader(device_data.native_vertex_shaders.at("SMAA Blending Weight Calculation VS"_h).get(), nullptr, 0); + device_context->PSSetShader(device_data.native_pixel_shaders.at("SMAA Blending Weight Calculation PS"_h).get(), nullptr, 0); + const std::array ps_srvs_blending_weight_calculation = { managed_resources.shader_resource_views["smaa_edge_detection"_h].get(), managed_resources.shader_resource_views["smaa_area_tex"_h].get(), managed_resources.shader_resource_views["smaa_search_tex"_h].get() }; device_context->PSSetShaderResources(0, ps_srvs_blending_weight_calculation.size(), ps_srvs_blending_weight_calculation.data()); - device_context->ClearRenderTargetView(rtv_blending_weight_calculation.get(), clear_color); + device_context->ClearRenderTargetView(managed_resources.render_target_views["smaa_blending_weight_calculation"_h].get(), clear_color); device_context->Draw(3, 0); // @@ -1511,15 +1514,26 @@ void DrawSMAA(ID3D11Device* device, ID3D11DeviceContext* device_context, const D // Bindings. device_context->OMSetRenderTargets(1, &rtv, nullptr); - device_context->VSSetShader(device_data.native_vertex_shaders.at(Math::CompileTimeStringHash("SMAA Neighborhood Blending VS")).get(), nullptr, 0); - device_context->PSSetShader(device_data.native_pixel_shaders.at(Math::CompileTimeStringHash("SMAA Neighborhood Blending PS")).get(), nullptr, 0); - const std::array ps_srvs_neighborhood_blending = { srv_color_tex, srv_blending_weight_calculation.get() }; + device_context->VSSetShader(device_data.native_vertex_shaders.at("SMAA Neighborhood Blending VS"_h).get(), nullptr, 0); + device_context->PSSetShader(device_data.native_pixel_shaders.at("SMAA Neighborhood Blending PS"_h).get(), nullptr, 0); + const std::array ps_srvs_neighborhood_blending = { srv_color_tex, managed_resources.shader_resource_views["smaa_blending_weight_calculation"_h].get() }; device_context->PSSetShaderResources(0, ps_srvs_neighborhood_blending.size(), ps_srvs_neighborhood_blending.data()); device_context->Draw(3, 0); // + // Reset resolution dependent resources on init swapchain. + // Some are intentionaly left out, we will recreate them here (in the DrawSMAA function). + auto on_init_swapchain = [&]() + { + managed_resources.depth_stencil_views["smaa_dsv"_h].reset(); + managed_resources.render_target_views["smaa_edge_detection"_h].reset(); + managed_resources.render_target_views["smaa_blending_weight_calculation"_h].reset(); + }; + + LumaCallbacks::on_init_swapchain.try_emplace("luma_smaa"_h, on_init_swapchain); + // Restore. device_context->OMSetBlendState(blend_original.get(), blend_factor_original, sample_mask_original); device_context->OMSetDepthStencilState(ds_original.get(), stencil_ref_original); @@ -1539,8 +1553,10 @@ void DrawSMAA(ID3D11Device* device, ID3D11DeviceContext* device_context, const D release_com_array(ps_srvs_original); } -void DrawKarisAverage(ID3D11Device* device, ID3D11DeviceContext* device_context, const DeviceData& device_data, ID3D11ShaderResourceView* srv_source, ID3D11ShaderResourceView** srv_out) +void DrawKarisAverage(ID3D11Device* device, ID3D11DeviceContext* device_context, DeviceData& device_data, ID3D11ShaderResourceView* srv_source, ID3D11ShaderResourceView** srv_out) { + auto& managed_resources = device_data.managed_resources; + // Backup CS. ComPtr cs_original; device_context->CSGetShader(cs_original.put(), nullptr, nullptr); @@ -1558,29 +1574,42 @@ void DrawKarisAverage(ID3D11Device* device, ID3D11DeviceContext* device_context, tex->GetDesc(&tex_desc); // Create RT and views. - tex_desc.MipLevels = 1; - tex_desc.ArraySize = 1; - tex_desc.Format = DXGI_FORMAT_R16G16B16A16_FLOAT; - tex_desc.SampleDesc.Count = 1; - tex_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_UNORDERED_ACCESS; - ensure(device->CreateTexture2D(&tex_desc, nullptr, tex.put()), >= 0); - ComPtr uav; - ensure(device->CreateUnorderedAccessView(tex.get(), nullptr, uav.put()), >= 0); + if (!managed_resources.unordered_access_views["luma_karis_average"_h]) + { + tex_desc.MipLevels = 1; + tex_desc.ArraySize = 1; + tex_desc.Format = DXGI_FORMAT_R16G16B16A16_FLOAT; + tex_desc.SampleDesc.Count = 1; + tex_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_UNORDERED_ACCESS; + ensure(device->CreateTexture2D(&tex_desc, nullptr, tex.put()), >= 0); + ensure(device->CreateUnorderedAccessView(tex.get(), nullptr, managed_resources.unordered_access_views["luma_karis_average"_h].put()), >= 0); + ensure(device->CreateShaderResourceView(tex.get(), nullptr, managed_resources.shader_resource_views["luma_karis_average"_h].put()), >= 0); + } // Bindings. - device_context->CSSetUnorderedAccessViews(0, 1, &uav, nullptr); - device_context->CSSetShader(device_data.native_compute_shaders.at(Math::CompileTimeStringHash("Karis Average CS")).get(), nullptr, 0); + device_context->CSSetUnorderedAccessViews(0, 1, &managed_resources.unordered_access_views["luma_karis_average"_h], nullptr); + device_context->CSSetShader(device_data.native_compute_shaders.at("Karis Average CS"_h).get(), nullptr, 0); device_context->CSSetShaderResources(0, 1, &srv_source); device_context->Dispatch((tex_desc.Width + 8 - 1) / 8, (tex_desc.Height + 8 - 1) / 8, 1); // Karis averaged out. - ensure(device->CreateShaderResourceView(tex.get(), nullptr, srv_out), >= 0); + *srv_out = managed_resources.shader_resource_views["luma_karis_average"_h].get(); + (*srv_out)->AddRef(); // Restore. device_context->CSSetUnorderedAccessViews(0, 1, &uav_original, nullptr); device_context->CSSetShader(cs_original.get(), nullptr, 0); device_context->CSSetShaderResources(0, 1, &srv_original); + + // Reset resolution dependent resources on init swapchain. + // Some are intentioanlly left out, we will recreate/reset them here. + auto on_init_swapchain = [&]() + { + managed_resources.unordered_access_views["luma_karis_average"_h].reset(); + }; + + LumaCallbacks::on_init_swapchain.try_emplace("luma_karis_average"_h, on_init_swapchain); } struct alignas(16) CBLumaBloomData @@ -1591,15 +1620,35 @@ struct alignas(16) CBLumaBloomData float sigma; }; -struct DrawLumaBloomData +void DrawBloom(ID3D11Device* device, ID3D11DeviceContext* device_context, DeviceData& device_data, ID3D11ShaderResourceView* srv_scene, int nmips, const float* sigmas, ID3D11ShaderResourceView** srv_bloom) { - ComPtr cb; - ComPtr blend; -}; + auto& managed_resources = device_data.managed_resources; -void DrawBloom(ID3D11Device* device, ID3D11DeviceContext* device_context, const DeviceData& device_data, DrawLumaBloomData& draw_luma_bloom_data, ID3D11ShaderResourceView* srv_scene, int nmips, const float* sigmas, ID3D11ShaderResourceView** srv_bloom) -{ - // Backup IA. + // TODO: Reorganize this better. + static std::vector rtv_mips_x(nmips); + static std::vector srv_mips_x(nmips); + static std::vector rtv_mips_y(nmips); + static std::vector srv_mips_y(nmips); + +#if DEVELOPMENT + static int last_nmips = nmips; + if (nmips != last_nmips) + { + ResetCOMArray(rtv_mips_x); + ResetCOMArray(srv_mips_x); + ResetCOMArray(rtv_mips_y); + ResetCOMArray(srv_mips_y); + + rtv_mips_x.resize(nmips); + srv_mips_x.resize(nmips); + rtv_mips_y.resize(nmips); + srv_mips_y.resize(nmips); + + last_nmips = nmips; + } +#endif + + // Backup IA. D3D11_PRIMITIVE_TOPOLOGY primitive_topology_original; device_context->IAGetPrimitiveTopology(&primitive_topology_original); @@ -1638,9 +1687,6 @@ void DrawBloom(ID3D11Device* device, ID3D11DeviceContext* device_context, const ComPtr dsv_original; device_context->OMGetRenderTargets(rtvs_original.size(), rtvs_original.data(), dsv_original.put()); - // Create MIPs and views. - // - // Get the scene resource and texture description from the SRV. ComPtr resource; srv_scene->GetResource(resource.put()); @@ -1652,82 +1698,73 @@ void DrawBloom(ID3D11Device* device, ID3D11DeviceContext* device_context, const const auto scene_width = tex_desc.Width; const auto scene_height = tex_desc.Height; - // Create Y MIPs and views. - //// - - tex_desc.Width /= 2; - tex_desc.Height /= 2; - tex_desc.MipLevels = nmips; - tex_desc.Format = DXGI_FORMAT_R16G16B16A16_FLOAT; - tex_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; - ensure(device->CreateTexture2D(&tex_desc, nullptr, tex.put()), >= 0); + const UINT x_mip0_width = tex_desc.Width / 2; + const UINT x_mip0_height = tex_desc.Height; - const UINT y_mip0_width = tex_desc.Width; - const UINT y_mip0_height = tex_desc.Height; + const UINT y_mip0_width = tex_desc.Width / 2; + const UINT y_mip0_height = tex_desc.Height / 2; - std::vector rtv_mips_y(nmips); - std::vector srv_mips_y(nmips); + // Create Y MIPs and views. + [[unlikely]] if (!rtv_mips_y[0]) + { + tex_desc.Width = y_mip0_width; + tex_desc.Height = y_mip0_height; + tex_desc.MipLevels = nmips; + tex_desc.Format = DXGI_FORMAT_R16G16B16A16_FLOAT; + tex_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; + ensure(device->CreateTexture2D(&tex_desc, nullptr, tex.put()), >= 0); - D3D11_RENDER_TARGET_VIEW_DESC rtv_desc = {}; - rtv_desc.Format = tex_desc.Format; - rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + D3D11_RENDER_TARGET_VIEW_DESC rtv_desc = {}; + rtv_desc.Format = tex_desc.Format; + rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; - D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc = {}; - srv_desc.Format = tex_desc.Format; - srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srv_desc.Texture2D.MipLevels = 1; + D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc = {}; + srv_desc.Format = tex_desc.Format; + srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + srv_desc.Texture2D.MipLevels = 1; - for (int i = 0; i < nmips; ++i) - { - rtv_desc.Texture2D.MipSlice = i; - ensure(device->CreateRenderTargetView(tex.get(), &rtv_desc, &rtv_mips_y[i]), >= 0); - srv_desc.Texture2D.MostDetailedMip = i; - ensure(device->CreateShaderResourceView(tex.get(), &srv_desc, &srv_mips_y[i]), >= 0); + for (int i = 0; i < nmips; ++i) + { + rtv_desc.Texture2D.MipSlice = i; + ensure(device->CreateRenderTargetView(tex.get(), &rtv_desc, &rtv_mips_y[i]), >= 0); + srv_desc.Texture2D.MostDetailedMip = i; + ensure(device->CreateShaderResourceView(tex.get(), &srv_desc, &srv_mips_y[i]), >= 0); + } } - //// - // Create X MIPs and views. - //// - - std::vector rtv_mips_x(nmips); - std::vector srv_mips_x(nmips); - - // Create X MIP0 and views. - tex_desc.Width = scene_width / 2; - tex_desc.Height = scene_height; - tex_desc.MipLevels = 1; - ensure(device->CreateTexture2D(&tex_desc, nullptr, tex.put()), >= 0); - ensure(device->CreateRenderTargetView(tex.get(), nullptr, &rtv_mips_x[0]), >= 0); - ensure(device->CreateShaderResourceView(tex.get(), nullptr, &srv_mips_x[0]), >= 0); - - const UINT x_mip0_width = tex_desc.Width; - const UINT x_mip0_height = tex_desc.Height; - - // Create rest of X MIPs and views. - for (UINT i = 1; i < nmips; ++i) { - tex_desc.Width = max(1u, x_mip0_width >> i); - tex_desc.Height = max(1u, x_mip0_height >> i); + [[unlikely]] if (!rtv_mips_x[0]) + { + // Create X MIP0 and views. + tex_desc.Width = x_mip0_width; + tex_desc.Height = x_mip0_height; + tex_desc.MipLevels = 1; ensure(device->CreateTexture2D(&tex_desc, nullptr, tex.put()), >= 0); - ensure(device->CreateRenderTargetView(tex.get(), nullptr, &rtv_mips_x[i]), >= 0); - ensure(device->CreateShaderResourceView(tex.get(), nullptr, &srv_mips_x[i]), >= 0); - } + ensure(device->CreateRenderTargetView(tex.get(), nullptr, &rtv_mips_x[0]), >= 0); + ensure(device->CreateShaderResourceView(tex.get(), nullptr, &srv_mips_x[0]), >= 0); - //// - - // + // Create rest of X MIPs and views. + for (UINT i = 1; i < nmips; ++i) + { + tex_desc.Width = max(1u, x_mip0_width >> i); + tex_desc.Height = max(1u, x_mip0_height >> i); + ensure(device->CreateTexture2D(&tex_desc, nullptr, tex.put()), >= 0); + ensure(device->CreateRenderTargetView(tex.get(), nullptr, &rtv_mips_x[i]), >= 0); + ensure(device->CreateShaderResourceView(tex.get(), nullptr, &srv_mips_x[i]), >= 0); + } + } // Create bloom CB. // - if (!draw_luma_bloom_data.cb) + [[unlikely]] if (!managed_resources.buffers["luma_bloom_cb"_h]) { D3D11_BUFFER_DESC buffer_desc = {}; buffer_desc.ByteWidth = sizeof(CBLumaBloomData); buffer_desc.Usage = D3D11_USAGE_DYNAMIC; buffer_desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - ensure(device->CreateBuffer(&buffer_desc, nullptr, draw_luma_bloom_data.cb.put()), >= 0); + ensure(device->CreateBuffer(&buffer_desc, nullptr, managed_resources.buffers["luma_bloom_cb"_h].put()), >= 0); } CBLumaBloomData cb_data; @@ -1735,9 +1772,9 @@ void DrawBloom(ID3D11Device* device, ID3D11DeviceContext* device_context, const auto update_constant_buffer = [&]() { D3D11_MAPPED_SUBRESOURCE mapped_subresource; - ensure(device_context->Map(draw_luma_bloom_data.cb.get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_subresource), >= 0); + ensure(device_context->Map(managed_resources.buffers["luma_bloom_cb"_h].get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_subresource), >= 0); std::memcpy(mapped_subresource.pData, &cb_data, sizeof(CBLumaBloomData)); - device_context->Unmap(draw_luma_bloom_data.cb.get(), 0); + device_context->Unmap(managed_resources.buffers["luma_bloom_cb"_h].get(), 0); }; // @@ -1761,7 +1798,7 @@ void DrawBloom(ID3D11Device* device, ID3D11DeviceContext* device_context, const device_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); device_context->VSSetShader(device_data.native_vertex_shaders.at(Math::CompileTimeStringHash("Bloom VS")).get(), nullptr, 0); device_context->PSSetShader(device_data.native_pixel_shaders.at(Math::CompileTimeStringHash("Bloom Downsample PS")).get(), nullptr, 0); - device_context->PSSetConstantBuffers(11, 1, &draw_luma_bloom_data.cb); + device_context->PSSetConstantBuffers(11, 1, &managed_resources.buffers["luma_bloom_cb"_h]); const std::array ps_samplers = { device_data.sampler_state_linear.get() }; device_context->PSSetSamplers(0, ps_samplers.size(), ps_samplers.data()); device_context->PSSetShaderResources(0, 1, &srv_scene); @@ -1783,7 +1820,7 @@ void DrawBloom(ID3D11Device* device, ID3D11DeviceContext* device_context, const // Bindings. device_context->OMSetRenderTargets(1, &rtv_mips_y[0], nullptr); - device_context->PSSetShader(device_data.native_pixel_shaders.at(Math::CompileTimeStringHash("Bloom Prefilter PS")).get(), nullptr, 0); + device_context->PSSetShader(device_data.native_pixel_shaders.at("Bloom Prefilter PS"_h).get(), nullptr, 0); device_context->PSSetShaderResources(0, 1, &srv_mips_x[0]); device_context->RSSetViewports(1, &viewports_y[0]); @@ -1795,10 +1832,11 @@ void DrawBloom(ID3D11Device* device, ID3D11DeviceContext* device_context, const // Downsample passes // - device_context->PSSetShader(device_data.native_pixel_shaders.at(Math::CompileTimeStringHash("Bloom Downsample PS")).get(), nullptr, 0); + device_context->PSSetShader(device_data.native_pixel_shaders.at("Bloom Downsample PS"_h).get(), nullptr, 0); // Render downsample passes. - for (UINT i = 1; i < nmips; ++i) { + for (UINT i = 1; i < nmips; ++i) + { viewport_x.Width = max(1u, x_mip0_width >> i); viewport_x.Height = max(1u, x_mip0_height >> i); @@ -1840,15 +1878,15 @@ void DrawBloom(ID3D11Device* device, ID3D11DeviceContext* device_context, const // Upsample passes // - device_context->PSSetShader(device_data.native_pixel_shaders.at(Math::CompileTimeStringHash("Bloom Upsample PS")).get(), nullptr, 0); + device_context->PSSetShader(device_data.native_pixel_shaders.at("Bloom Upsample PS"_h).get(), nullptr, 0); - if (!draw_luma_bloom_data.blend) + [[unlikely]] if (!managed_resources.blends["luma_bloom_blend"_h]) { CD3D11_BLEND_DESC blend_desc(D3D11_DEFAULT); blend_desc.RenderTarget[0].BlendEnable = TRUE; blend_desc.RenderTarget[0].SrcBlend = D3D11_BLEND_BLEND_FACTOR; blend_desc.RenderTarget[0].DestBlend = D3D11_BLEND_BLEND_FACTOR; - ensure(device->CreateBlendState(&blend_desc, draw_luma_bloom_data.blend.put()), >= 0); + ensure(device->CreateBlendState(&blend_desc, managed_resources.blends["luma_bloom_blend"_h].put()), >= 0); } for (int i = nmips - 1; i > 0; --i) @@ -1865,7 +1903,7 @@ void DrawBloom(ID3D11Device* device, ID3D11DeviceContext* device_context, const device_context->OMSetRenderTargets(1, &rtv_mips_y[i - 1], nullptr); device_context->PSSetShaderResources(0, 1, &srv_mips_y[i]); device_context->RSSetViewports(1, &viewports_y[i - 1]); - device_context->OMSetBlendState(draw_luma_bloom_data.blend.get(), blend_factor, UINT_MAX); + device_context->OMSetBlendState(managed_resources.blends["luma_bloom_blend"_h].get(), blend_factor, UINT_MAX); device_context->Draw(3, 0); } @@ -1889,10 +1927,16 @@ void DrawBloom(ID3D11Device* device, ID3D11DeviceContext* device_context, const device_context->RSSetState(rasterizer_original.get()); // Release com arrays. - auto release_com_array = [](auto& array){ for (auto* p : array) if (p) p->Release(); }; - release_com_array(rtvs_original); - release_com_array(rtv_mips_x); - release_com_array(srv_mips_x); - release_com_array(rtv_mips_y); - release_com_array(srv_mips_y); + ResetCOMArray(rtvs_original); + + auto reset_mips = [&]() + { + ResetCOMArray(rtv_mips_x); + ResetCOMArray(srv_mips_x); + ResetCOMArray(rtv_mips_y); + ResetCOMArray(srv_mips_y); + }; + + LumaCallbacks::on_destroy_device.try_emplace("luma_bloom"_h, reset_mips); + LumaCallbacks::on_init_swapchain.try_emplace("luma_bloom"_h, reset_mips); } \ No newline at end of file diff --git a/Source/Games/BioShock Series/main.cpp b/Source/Games/BioShock Series/main.cpp index fb19f5d3..73df8a82 100644 --- a/Source/Games/BioShock Series/main.cpp +++ b/Source/Games/BioShock Series/main.cpp @@ -152,8 +152,6 @@ struct GameDeviceDataBioshockSeries final : public GameDeviceData com_ptr scene_texture_srv; ComPtr srv_depth; - DrawSMAAData draw_smaa_data; - DrawLumaBloomData draw_luma_bloom_data; ComPtr cb_bloom; }; @@ -825,7 +823,7 @@ class BioshockSeries final : public Game com_ptr rtv; native_device->CreateRenderTargetView(resource.get(), nullptr, &rtv); - DrawSMAA(native_device, native_device_context, device_data, game_device_data.draw_smaa_data, rtv.get(), srv_copy.get(), srv_linear_to_gamma.get(), game_device_data.srv_depth.get()); + DrawSMAA(native_device, native_device_context, device_data, rtv.get(), srv_copy.get(), srv_linear_to_gamma.get(), game_device_data.srv_depth.get()); } if (g_luma_bloom_enable) @@ -839,7 +837,7 @@ class BioshockSeries final : public Game native_device_context->PSSetConstantBuffers(0, 1, &game_device_data.cb_bloom); ComPtr srv_bloom; - DrawBloom(native_device, native_device_context, device_data, game_device_data.draw_luma_bloom_data, srv_original.get(), g_bloom_nmips, g_bloom_sigmas.data(), srv_bloom.put()); + DrawBloom(native_device, native_device_context, device_data, srv_original.get(), g_bloom_nmips, g_bloom_sigmas.data(), srv_bloom.put()); native_device_context->PSSetConstantBuffers(0, 1, &cb_original); diff --git a/Source/Games/Burnout Paradise Remastered/main.cpp b/Source/Games/Burnout Paradise Remastered/main.cpp index 654ffb79..9f752ab5 100644 --- a/Source/Games/Burnout Paradise Remastered/main.cpp +++ b/Source/Games/Burnout Paradise Remastered/main.cpp @@ -66,7 +66,6 @@ struct GameDeviceDataBurnoutParadise final : public GameDeviceData ComPtr motion_blur_ps_cb_copy; ComPtr motion_blur_vs_cb_copy; - DrawLumaBloomData draw_luma_bloom_data; ComPtr srv_luma_bloom; ComPtr srv_xegtao; }; @@ -578,7 +577,7 @@ class BurnoutParadise final : public Game ComPtr srv_karis_averaged_scene; DrawKarisAverage(native_device, native_device_context, device_data, srv_linear_scene.get(), srv_karis_averaged_scene.put()); - DrawBloom(native_device, native_device_context, device_data, game_device_data.draw_luma_bloom_data, srv_karis_averaged_scene.get(), g_bloom_nmips, g_bloom_sigmas.data(), game_device_data.srv_luma_bloom.put()); + DrawBloom(native_device, native_device_context, device_data, srv_karis_averaged_scene.get(), g_bloom_nmips, g_bloom_sigmas.data(), game_device_data.srv_luma_bloom.put()); // Delinearize bloom pass // diff --git a/Source/Games/Deus Ex Human Revolution Director's Cut/main.cpp b/Source/Games/Deus Ex Human Revolution Director's Cut/main.cpp index 908af026..3a9e02c4 100644 --- a/Source/Games/Deus Ex Human Revolution Director's Cut/main.cpp +++ b/Source/Games/Deus Ex Human Revolution Director's Cut/main.cpp @@ -222,8 +222,6 @@ struct GameDeviceDataDeusExHumanRevolutionDC final : public GameDeviceData ComPtr cb_ssao_scene_buffer; - DrawSMAAData draw_smaa_data; - struct BlendDescCompare { bool operator()(const D3D11_BLEND_DESC& a, const D3D11_BLEND_DESC& b) const @@ -647,7 +645,7 @@ class GameDeusExHumanRevolutionDC final : public Game // - DrawSMAA(native_device, native_device_context, device_data, game_device_data.draw_smaa_data, game_device_data.swapchain_rtv.get(), srv_linearize.get(), srv_scene.get(), game_device_data.depth_buffer_srv.get()); + DrawSMAA(native_device, native_device_context, device_data, game_device_data.swapchain_rtv.get(), srv_linearize.get(), srv_scene.get(), game_device_data.depth_buffer_srv.get()); return DrawOrDispatchOverrideType::Replaced; } diff --git a/Source/Games/Fallout 4/main.cpp b/Source/Games/Fallout 4/main.cpp index 8572611f..979d2fe8 100644 --- a/Source/Games/Fallout 4/main.cpp +++ b/Source/Games/Fallout 4/main.cpp @@ -58,18 +58,6 @@ namespace std::memcpy(mapped_subresource.pData, data, size); ctx->Unmap(cb, 0); } - - void release_com_array(auto& array) - { - for (auto*& ptr : array) - { - if (ptr) - { - ptr->Release(); - ptr = nullptr; - } - } - } } struct GameDeviceDataFallout4 final : GameDeviceData @@ -154,7 +142,7 @@ class GameFallout4 final : public Game { auto& game_device_data = GetGameDeviceData(device_data); - release_com_array(game_device_data.uav_xe_gtao_prefilter_depths16x16); + ResetCOMArray(game_device_data.uav_xe_gtao_prefilter_depths16x16); Game::OnDestroyDeviceData(device_data); } @@ -482,7 +470,7 @@ class GameFallout4 final : public Game // Copy DLSS output to the original TAA's current frame and the backbuffer. native_device_context->CopyResource(resource_output.get(), game_device_data.tex_dlss_output.get()); - release_com_array(rtvs); + ResetCOMArray(rtvs); return DrawOrDispatchOverrideType::Replaced; }