diff --git a/Source/Core/VideoCommon/ConstantManager.h b/Source/Core/VideoCommon/ConstantManager.h index 88c25a9823..b8c65aaefb 100644 --- a/Source/Core/VideoCommon/ConstantManager.h +++ b/Source/Core/VideoCommon/ConstantManager.h @@ -58,6 +58,8 @@ struct alignas(16) PixelShaderConstants // For shader_framebuffer_fetch logic ops: u32 logic_op_enable; // bool LogicOp logic_op_mode; + // For custom shaders... + u32 time_ms; }; struct alignas(16) VertexShaderConstants diff --git a/Source/Core/VideoCommon/PixelShaderGen.cpp b/Source/Core/VideoCommon/PixelShaderGen.cpp index 326cd975d9..69fdc36efc 100644 --- a/Source/Core/VideoCommon/PixelShaderGen.cpp +++ b/Source/Core/VideoCommon/PixelShaderGen.cpp @@ -406,6 +406,7 @@ void WritePixelShaderCommonHeader(ShaderCode& out, APIType api_type, "\tbool blend_subtract_alpha;\n" "\tbool logic_op_enable;\n" "\tuint logic_op_mode;\n" + "\tuint time_ms;\n" "}};\n\n"); out.Write("#define bpmem_combiners(i) (bpmem_pack1[(i)].xy)\n" "#define bpmem_tevind(i) (bpmem_pack1[(i)].z)\n" @@ -869,6 +870,9 @@ void WriteCustomShaderStructImpl(ShaderCode* out, u32 num_stages, bool per_pixel // Actual data will be filled out in the tev stage code, just set the // stage count for now out->Write("\tcustom_data.tev_stage_count = {};\n", num_stages); + + // Time + out->Write("\tcustom_data.time_ms = time_ms;\n"); } static void WriteStage(ShaderCode& out, const pixel_shader_uid_data* uid_data, int n, diff --git a/Source/Core/VideoCommon/ShaderGenCommon.cpp b/Source/Core/VideoCommon/ShaderGenCommon.cpp index 5f2b2b224f..e4922f3e3e 100644 --- a/Source/Core/VideoCommon/ShaderGenCommon.cpp +++ b/Source/Core/VideoCommon/ShaderGenCommon.cpp @@ -447,5 +447,6 @@ void WriteCustomShaderStructDef(ShaderCode* out, u32 numtexgens) out->Write("\tCustomShaderTevStage[16] tev_stages;\n"); out->Write("\tuint tev_stage_count;\n"); out->Write("\tfloat4 final_color;\n"); + out->Write("\tuint time_ms;\n"); out->Write("}};\n\n"); } diff --git a/Source/Core/VideoCommon/UberShaderPixel.cpp b/Source/Core/VideoCommon/UberShaderPixel.cpp index 278be9c082..bcddde4adc 100644 --- a/Source/Core/VideoCommon/UberShaderPixel.cpp +++ b/Source/Core/VideoCommon/UberShaderPixel.cpp @@ -266,6 +266,9 @@ void WriteCustomShaderStructImpl(ShaderCode* out, u32 num_texgen, bool per_pixel // Actual data will be filled out in the tev stage code, just set the // stage count for now out->Write("\tcustom_data.tev_stage_count = num_stages;\n"); + + // Time + out->Write("\tcustom_data.time_ms = time_ms;\n"); } } // namespace PixelShaderUid GetPixelShaderUid() diff --git a/Source/Core/VideoCommon/VertexManagerBase.cpp b/Source/Core/VideoCommon/VertexManagerBase.cpp index 92e5be9952..564eb684dc 100644 --- a/Source/Core/VideoCommon/VertexManagerBase.cpp +++ b/Source/Core/VideoCommon/VertexManagerBase.cpp @@ -15,6 +15,7 @@ #include "Core/ConfigManager.h" #include "Core/DolphinAnalytics.h" +#include "Core/HW/SystemTimers.h" #include "Core/System.h" #include "VideoCommon/AbstractGfx.h" @@ -107,6 +108,8 @@ VertexManagerBase::~VertexManagerBase() = default; bool VertexManagerBase::Initialize() { m_frame_end_event = AfterFrameEvent::Register([this] { OnEndFrame(); }, "VertexManagerBase"); + m_after_present_event = AfterPresentEvent::Register( + [this](PresentInfo& pi) { m_ticks_elapsed = pi.emulated_timestamp; }, "VertexManagerBase"); m_index_generator.Init(); m_custom_shader_cache = std::make_unique(); m_cpu_cull.Init(); @@ -526,6 +529,13 @@ void VertexManagerBase::Flush() auto& geometry_shader_manager = system.GetGeometryShaderManager(); auto& vertex_shader_manager = system.GetVertexShaderManager(); + if (g_ActiveConfig.bGraphicMods) + { + const double seconds_elapsed = + static_cast(m_ticks_elapsed) / SystemTimers::GetTicksPerSecond(); + pixel_shader_manager.constants.time_ms = seconds_elapsed * 1000; + } + CalculateBinormals(VertexLoaderManager::GetCurrentVertexFormat()); // Calculate ZSlope for zfreeze const auto used_textures = UsedTextures(); diff --git a/Source/Core/VideoCommon/VertexManagerBase.h b/Source/Core/VideoCommon/VertexManagerBase.h index 66e24cbf36..ebb857ff21 100644 --- a/Source/Core/VideoCommon/VertexManagerBase.h +++ b/Source/Core/VideoCommon/VertexManagerBase.h @@ -233,8 +233,10 @@ private: bool m_allow_background_execution = true; std::unique_ptr m_custom_shader_cache; + u64 m_ticks_elapsed; Common::EventHook m_frame_end_event; + Common::EventHook m_after_present_event; }; extern std::unique_ptr g_vertex_manager; diff --git a/docs/CustomPipelineGraphicsMod.md b/docs/CustomPipelineGraphicsMod.md index c2f49e772a..771d3dba36 100644 --- a/docs/CustomPipelineGraphicsMod.md +++ b/docs/CustomPipelineGraphicsMod.md @@ -105,6 +105,7 @@ vec4 custom_main( in CustomShaderData data ) |``tev_stages`` | CustomShaderTevStage[] | v1 | An array of TEV stages, the amount is specified by ``tev_stage_count`` | |``tev_stage_count`` | uint | v1 | The count of TEV stages | |``final_color`` | vec4 | v1 | The final color generated by Dolphin after all TEV stages are executed | +|``time_ms`` | uint | v1 | The time that has passed in milliseconds, since the game was started. Useful for animating | `CustomShaderLightData` is used to denote lighting data the game is applying when rendering the specific draw call. It has the following structure: @@ -247,4 +248,4 @@ vec4 custom_main( in CustomShaderData data ) } return vec4(total_diffuse * vec3(0, 0, 1), 1); } -``` +``` \ No newline at end of file