Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
RWTexture2D<float> BlendedDepthTexture : register(u0);
RWTexture2D<unorm half> BlendedDepthTexture16 : register(u1);
RWTexture2D<float> MainDepthCopy : register(u2); // R32_FLOAT snapshot replaces CopyResource(terrainDepth <- mainDepth)

Texture2D<unorm float> MainDepthTexture : register(t0);
Texture2D<unorm float> TerrainDepthTexture : register(t1);

[numthreads(8, 8, 1)] void main(uint3 DTid : SV_DispatchThreadID) {
float mixedDepth = min(MainDepthTexture[DTid.xy], TerrainDepthTexture[DTid.xy]);
float mainDepth = MainDepthTexture[DTid.xy];
float mixedDepth = min(mainDepth, TerrainDepthTexture[DTid.xy]);
BlendedDepthTexture[DTid.xy] = mixedDepth;
BlendedDepthTexture16[DTid.xy] = mixedDepth;
MainDepthCopy[DTid.xy] = mainDepth;
}
31 changes: 22 additions & 9 deletions src/Features/TerrainBlending.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -693,6 +693,16 @@ void TerrainBlending::SetupResources()
blendedDepthTexture16->CreateSRV(srvDesc);
blendedDepthTexture16->CreateUAV(uavDesc);

// R32_FLOAT snapshot of main depth written by DepthBlend CS; replaces the per-frame
// CopyResource(terrainDepth <- mainDepth) that was needed for terrain shader slot 55.
texDesc.Format = DXGI_FORMAT_R32_FLOAT;
srvDesc.Format = texDesc.Format;
uavDesc.Format = texDesc.Format;

mainDepthCopy = new Texture2D(texDesc);
mainDepthCopy->CreateSRV(srvDesc);
mainDepthCopy->CreateUAV(uavDesc);

auto& mainDepth = renderer->GetDepthStencilData().depthStencils[RE::RENDER_TARGETS_DEPTHSTENCIL::kMAIN];
depthSRVBackup = mainDepth.depthSRV;

Expand Down Expand Up @@ -781,10 +791,13 @@ void TerrainBlending::BlendPrepassDepths()
auto dispatchCount = Util::GetScreenDispatchCount();

{
TracyD3D11Zone(globals::state->tracyCtx, "Terrain Blending - Depth Blend CS");

ID3D11ShaderResourceView* views[2] = { depthSRVBackup, terrainDepth.depthSRV };
context->CSSetShaderResources(0, ARRAYSIZE(views), views);

ID3D11UnorderedAccessView* uavs[2] = { blendedDepthTexture->uav.get(), blendedDepthTexture16->uav.get() };
// u0=blendedDepth(R32), u1=blendedDepth16(R16), u2=mainDepthCopy(R32) written inline
ID3D11UnorderedAccessView* uavs[3] = { blendedDepthTexture->uav.get(), blendedDepthTexture16->uav.get(), mainDepthCopy->uav.get() };
context->CSSetUnorderedAccessViews(0, ARRAYSIZE(uavs), uavs, nullptr);

context->CSSetShader(GetDepthBlendShader(), nullptr, 0);
Expand All @@ -795,19 +808,16 @@ void TerrainBlending::BlendPrepassDepths()
ID3D11ShaderResourceView* views[2] = { nullptr, nullptr };
context->CSSetShaderResources(0, ARRAYSIZE(views), views);

ID3D11UnorderedAccessView* uavs[2] = { nullptr, nullptr };
ID3D11UnorderedAccessView* uavs[3] = { nullptr, nullptr, nullptr };
context->CSSetUnorderedAccessViews(0, ARRAYSIZE(uavs), uavs, nullptr);

ID3D11ComputeShader* shader = nullptr;
context->CSSetShader(shader, nullptr, 0);

auto stateUpdateFlags = globals::game::stateUpdateFlags;
stateUpdateFlags->set(RE::BSGraphics::ShaderFlags::DIRTY_RENDERTARGET);

auto renderer = globals::game::renderer;
auto& mainDepth = renderer->GetDepthStencilData().depthStencils[RE::RENDER_TARGETS_DEPTHSTENCIL::kMAIN];

context->CopyResource(terrainDepth.texture, mainDepth.texture);
// CopyResource(terrainDepth <- mainDepth) eliminated: main depth is now written
// directly into mainDepthCopy (u2) by the CS above, saving a full-stereo D24S8 copy.

if (globals::state->frameAnnotations)
globals::state->EndPerfEvent();
Expand Down Expand Up @@ -992,8 +1002,11 @@ void TerrainBlending::RenderTerrainBlendingPasses()
auto shadowState = globals::game::shadowState;
auto stateUpdateFlags = globals::game::stateUpdateFlags;

// Used to get the distance of the surface to the lowest depth
context->PSSetShaderResources(55, 1, &terrainDepth.depthSRV);
// Slot 55: main depth snapshot used to measure surface-to-lowest-depth distance.
// R32_FLOAT copy written inline by DepthBlend CS; safe to read here because
// mainDepthCopy is not written during the main rendering pass.
auto mainDepthSRV = mainDepthCopy->srv.get();
context->PSSetShaderResources(55, 1, &mainDepthSRV);

const uint64_t terrainPassCount = static_cast<uint64_t>(terrainRenderPasses.size());
const uint64_t noBlendPassCount = static_cast<uint64_t>(renderPasses.size());
Expand Down
1 change: 1 addition & 0 deletions src/Features/TerrainBlending.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ struct TerrainBlending : Feature

Texture2D* blendedDepthTexture = nullptr;
Texture2D* blendedDepthTexture16 = nullptr;
Texture2D* mainDepthCopy = nullptr; // R32_FLOAT snapshot written inline by DepthBlend CS, replaces CopyResource

ID3D11ShaderResourceView* GetBlendedDepthSRV() const
{
Expand Down
24 changes: 13 additions & 11 deletions src/Features/Upscaling.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1912,9 +1912,16 @@ void Upscaling::UpscaleDepth()
};

{
// Sometimes this is not already copied e.g. map menu.
// Skip alias copies to reduce unnecessary copy churn.
copyIfNonAliased(depthCopy.texture, depth.texture);
// Engine copies kMAIN→kMAIN_COPY during 3D scene rendering.
// In non-3D contexts (map, main menu, loading, pause) the engine skips its copy.
auto* ui = globals::game::ui;
const bool inMenuContext = globals::state->isMapMenuOpen ||
globals::state->isMainMenuOpen ||
globals::state->isLoadingMenuOpen ||
(ui && ui->GameIsPaused());
if (inMenuContext) {
copyIfNonAliased(depthCopy.texture, depth.texture);
}
Comment thread
alandtse marked this conversation as resolved.

// Clear stencil to be 0xFF
if (globals::game::isVR) {
Expand Down Expand Up @@ -1989,18 +1996,13 @@ void Upscaling::ApplySharpening()
auto renderer = globals::game::renderer;
auto& main = renderer->GetRuntimeData().renderTargets[RE::RENDER_TARGETS::kMAIN];

ID3D11Resource* mainResource = nullptr;
main.SRV->GetResource(&mainResource);

if (!mainResource)
if (!main.UAV)
return;

context->OMSetRenderTargets(0, nullptr, nullptr);

rcas.ApplySharpen(main.SRV, sharpenerTexture->uav.get(), currentSharpness);
context->CopyResource(mainResource, sharpenerTexture->resource.get());

mainResource->Release();
// Zero-copy path: DLSS has already written to sharpenerTexture; sharpen directly into kMAIN.UAV.
rcas.ApplySharpen(sharpenerTexture->srv.get(), main.UAV, currentSharpness);

globals::game::stateUpdateFlags->set(RE::BSGraphics::ShaderFlags::DIRTY_RENDERTARGET);
}
Expand Down
13 changes: 9 additions & 4 deletions src/Features/Upscaling/Streamline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -612,11 +612,16 @@ void Streamline::Upscale(ID3D11Resource* a_upscalingTexture, ID3D11Resource* a_r
auto screenSize = state->screenSize;
auto renderSize = Util::ConvertToDynamic(screenSize);

// When RCAS sharpening is active, direct DLSS output to sharpenerTexture so RCAS can
// sharpen directly into kMAIN.UAV without a CopyResource round-trip.
auto& upscaling = globals::features::upscaling;
ID3D11Resource* colorOut =
(upscaling.settings.sharpnessDLSS > 0.0f && upscaling.sharpenerTexture) ? upscaling.sharpenerTexture->resource.get() : a_upscalingTexture;

// VR: Combined-buffer mode with extent offsets causes temporal ghosting on the right eye
// because DLSS's internal history buffers use extent offsets as indices.
// Per-eye isolation with extents at {0,0} is required.
if (globals::game::isVR) {
auto& upscaling = globals::features::upscaling;
uint32_t eyeWidthOut = (uint32_t)(screenSize.x / 2);
uint32_t eyeHeightOut = (uint32_t)screenSize.y;
uint32_t eyeWidthIn = (uint32_t)(renderSize.x / 2);
Expand All @@ -636,14 +641,14 @@ void Streamline::Upscale(ID3D11Resource* a_upscalingTexture, ID3D11Resource* a_r
extentIn, extentOut, eyeWidthOut);
}

upscaling.FinalizePerEyeOutputs(a_upscalingTexture);
upscaling.FinalizePerEyeOutputs(colorOut);
} else {
// Non-VR: Simple full-texture upscale
// Non-VR: Simple full-texture upscale.
sl::Extent extentIn{ 0, 0, (uint)renderSize.x, (uint)renderSize.y };
sl::Extent extentOut{ 0, 0, (uint)screenSize.x, (uint)screenSize.y };

EvaluateDLSS(viewport, 0,
a_upscalingTexture, a_upscalingTexture,
a_upscalingTexture, colorOut,
depthTexture.texture, a_motionVectors, a_reactiveMask, a_transparencyCompositionMask,
extentIn, extentOut, (uint)screenSize.x);
}
Expand Down
Loading