diff --git a/Common/GPU/ShaderTranslation.cpp b/Common/GPU/ShaderTranslation.cpp index af34fadb12..34de213451 100644 --- a/Common/GPU/ShaderTranslation.cpp +++ b/Common/GPU/ShaderTranslation.cpp @@ -85,6 +85,7 @@ cbuffer data : register(b0) { float2 u_texelDelta; float2 u_pixelDelta; float4 u_time; + float4 u_timeDelta; float4 u_setting; float u_video; }; @@ -101,6 +102,7 @@ layout (std140, set = 0, binding = 0) uniform Data { vec2 u_texelDelta; vec2 u_pixelDelta; vec4 u_time; + vec4 u_timeDelta; vec4 u_setting; float u_video; }; @@ -111,8 +113,9 @@ float4 gl_HalfPixel : register(c0); float2 u_texelDelta : register(c1); float2 u_pixelDelta : register(c2); float4 u_time : register(c3); -float4 u_setting : register(c4); -float u_video : register(c5); +float4 u_timeDelta : register(c4); +float4 u_setting : register(c5); +float u_video : register(c6); )"; // SPIRV-Cross' HLSL output has some deficiencies we need to work around. diff --git a/GPU/Common/PresentationCommon.cpp b/GPU/Common/PresentationCommon.cpp index 2b429d7556..b6e9ecbdfc 100644 --- a/GPU/Common/PresentationCommon.cpp +++ b/GPU/Common/PresentationCommon.cpp @@ -185,6 +185,10 @@ void PresentationCommon::CalculatePostShaderUniforms(int bufferWidth, int buffer uniforms->pixelDelta[0] = u_pixel_delta; uniforms->pixelDelta[1] = v_pixel_delta; memcpy(uniforms->time, time, 4 * sizeof(float)); + uniforms->timeDelta[0] = time[0] - previousUniforms_.time[0]; + uniforms->timeDelta[1] = (time[2] - previousUniforms_.time[2]) * (1.0f / 60.0f); + uniforms->timeDelta[2] = time[2] - previousUniforms_.time[2]; + uniforms->timeDelta[3] = time[3] != previousUniforms_.time[3] ? 1.0f : 0.0f; uniforms->video = hasVideo_ ? 1.0f : 0.0f; // The shader translator tacks this onto our shaders, if we don't set it they render garbage. @@ -286,8 +290,9 @@ bool PresentationCommon::BuildPostShader(const ShaderInfo *shaderInfo, const Sha { "u_texelDelta", 1, 1, UniformType::FLOAT2, offsetof(PostShaderUniforms, texelDelta) }, { "u_pixelDelta", 2, 2, UniformType::FLOAT2, offsetof(PostShaderUniforms, pixelDelta) }, { "u_time", 3, 3, UniformType::FLOAT4, offsetof(PostShaderUniforms, time) }, - { "u_setting", 4, 4, UniformType::FLOAT4, offsetof(PostShaderUniforms, setting) }, - { "u_video", 5, 5, UniformType::FLOAT1, offsetof(PostShaderUniforms, video) }, + { "u_timeDelta", 4, 4, UniformType::FLOAT4, offsetof(PostShaderUniforms, timeDelta) }, + { "u_setting", 5, 5, UniformType::FLOAT4, offsetof(PostShaderUniforms, setting) }, + { "u_video", 6, 6, UniformType::FLOAT1, offsetof(PostShaderUniforms, video) }, } }; Draw::Pipeline *pipeline = CreatePipeline({ vs, fs }, true, &postShaderDesc); @@ -642,6 +647,7 @@ void PresentationCommon::CopyToOutput(OutputFlags flags, int uvRotation, float u // Grab the previous framebuffer early so we can change previousIndex_ when we want. Draw::Framebuffer *previousFramebuffer = previousFramebuffers_.empty() ? nullptr : previousFramebuffers_[previousIndex_]; + PostShaderUniforms uniforms; const auto performShaderPass = [&](const ShaderInfo *shaderInfo, Draw::Framebuffer *postShaderFramebuffer, Draw::Pipeline *postShaderPipeline) { if (postShaderOutput) { draw_->BindFramebufferAsTexture(postShaderOutput, 0, Draw::FB_COLOR_BIT, 0); @@ -658,7 +664,6 @@ void PresentationCommon::CopyToOutput(OutputFlags flags, int uvRotation, float u draw_->SetViewports(1, &viewport); draw_->SetScissorRect(0, 0, nextWidth, nextHeight); - PostShaderUniforms uniforms; CalculatePostShaderUniforms(lastWidth, lastHeight, nextWidth, nextHeight, shaderInfo, &uniforms); draw_->BindPipeline(postShaderPipeline); @@ -746,7 +751,6 @@ void PresentationCommon::CopyToOutput(OutputFlags flags, int uvRotation, float u BindSource(1); if (isFinalAtOutputResolution && previousFramebuffers_.empty()) { - PostShaderUniforms uniforms; CalculatePostShaderUniforms(lastWidth, lastHeight, (int)rc.w, (int)rc.h, &postShaderInfo_.back(), &uniforms); draw_->UpdateDynamicUniformBuffer(&uniforms, sizeof(uniforms)); } else { @@ -789,6 +793,8 @@ void PresentationCommon::CopyToOutput(OutputFlags flags, int uvRotation, float u // Unbinds all textures and samplers too, needed since sometimes a MakePixelTexture is deleted etc. draw_->BindPipeline(nullptr); + + previousUniforms_ = uniforms; } void PresentationCommon::CalculateRenderResolution(int *width, int *height, int *scaleFactor, bool *upscaling, bool *ssaa) { diff --git a/GPU/Common/PresentationCommon.h b/GPU/Common/PresentationCommon.h index 6a749fb6d7..63d8e4a2dc 100644 --- a/GPU/Common/PresentationCommon.h +++ b/GPU/Common/PresentationCommon.h @@ -31,6 +31,7 @@ struct CardboardSettings { struct PostShaderUniforms { float texelDelta[2]; float pixelDelta[2]; float time[4]; + float timeDelta[4]; float setting[4]; float video; float pad[3]; // Used on Direct3D9. @@ -133,6 +134,7 @@ protected: std::vector postShaderInfo_; std::vector previousFramebuffers_; int previousIndex_ = 0; + PostShaderUniforms previousUniforms_{}; Draw::Texture *srcTexture_ = nullptr; Draw::Framebuffer *srcFramebuffer_ = nullptr;