Skip to content

fix: proton shadow taa jitter#1665

Closed
davo0411 wants to merge 2 commits into
community-shaders:devfrom
davo0411:linux-shadow-flicker
Closed

fix: proton shadow taa jitter#1665
davo0411 wants to merge 2 commits into
community-shaders:devfrom
davo0411:linux-shadow-flicker

Conversation

@davo0411
Copy link
Copy Markdown
Collaborator

@davo0411 davo0411 commented Dec 31, 2025

should address #1479

replaces typical taa shadow accumulation with a worldspace hash function variant when dxvk, wine, llvmpipe are detected in the gpu adapter description.
this list might be wrong as i am unfamiliar with linux and just got common names.

untested

Summary by CodeRabbit

  • Bug Fixes
    • Improved shadow quality and stability on Linux/Proton/DXVK systems, reducing visual artifacts and temporal shimmering for enhanced visual fidelity.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Dec 31, 2025

📝 Walkthrough

Walkthrough

The PR introduces runtime detection for DXVK/Wine environments and conditionally adjusts shadow denoising strategies. When detected, position-based hashing replaces frame-count-based randomness to reduce temporal artifacts in shadow sampling on non-native D3D11 platforms.

Changes

Cohort / File(s) Summary
Shader Data Structure
package/Shaders/Common/SharedData.hlsli
Adds uint IsNotNativeD3D11 field to SharedData cbuffer to communicate platform information to GPU. Replaces padding slot, affecting cbuffer memory layout.
Shadow Denoising Logic
package/Shaders/Utility.hlsl
Modifies GetPoissonDiskFilteredShadowVisibility and PS_OUTPUT main to branch on IsNotNativeD3D11: uses position-based murmur3 hashing for non-native D3D11, retains frame-count-based randomness for native D3D11. Reduces temporal jitter on Linux/Proton/DXVK.
Runtime Platform Detection
src/State.cpp, src/State.h
Adds bool isRunningOnDXVK field to State class; implements adapter-description-based detection logic to identify DXVK environments. Populates shared data buffer with IsNotNativeD3D11 flag before GPU upload. Updates SharedDataCB structure to replace float pad0 with uint IsNotNativeD3D11.

Sequence Diagram

sequenceDiagram
    participant CPU as CPU / State.cpp
    participant SharedMem as Shared Data Buffer
    participant GPU as GPU / Utility.hlsl
    
    CPU->>CPU: Inspect adapter description
    alt DXVK Detected
        CPU->>CPU: isRunningOnDXVK = true
    else Native D3D11
        CPU->>CPU: isRunningOnDXVK = false
    end
    
    CPU->>SharedMem: Populate IsNotNativeD3D11 flag
    CPU->>GPU: Upload SharedData cbuffer
    
    GPU->>GPU: GetPoissonDiskFilteredShadowVisibility()
    alt IsNotNativeD3D11 == 1
        GPU->>GPU: frameOffset = position-based hash
        note over GPU: Spatial denoising (no temporal jitter)
    else IsNotNativeD3D11 == 0
        GPU->>GPU: frameOffset = frame count
        note over GPU: Temporal denoising (native D3D11)
    end
    
    GPU->>GPU: Apply filtered shadow sampling
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • doodlum/skyrim-community-shaders#1346: Also modifies GetPoissonDiskFilteredShadowVisibility with frame-count-based hashing and sampling logic; overlapping shader changes warrant cross-validation.

Suggested reviewers

  • doodlum
  • alandtse
  • jiayev

Poem

🐰 Across the wire where platforms dance,
Detection blooms—DXVK's stance!
Frame counts fade; position takes flight,
Spatial whispers chase jitter's blight.
Shadows denoised, without temporal stain! ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix: proton shadow taa jitter' directly summarizes the main objective: addressing TAA jitter artifacts in shadow rendering on Proton/Linux environments by switching from frame-count-based to position-based hashing.
✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Automated formatting by clang-format, prettier, and other hooks.
See https://pre-commit.ci for details.
@github-actions
Copy link
Copy Markdown

Using provided base ref: 5ed6701
Using base ref: 5ed6701
Base commit date: 2025-12-31T14:40:51+10:00 (Wednesday, December 31, 2025 02:40 PM)
No actionable suggestions for changed features.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5ed6701 and c11a390.

📒 Files selected for processing (4)
  • package/Shaders/Common/SharedData.hlsli
  • package/Shaders/Utility.hlsl
  • src/State.cpp
  • src/State.h
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{cpp,cxx,cc,c,h,hpp,hxx,hlsl,hlsli,fx,fxh,py}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Do not include TODO/FIXME placeholders; provide complete, working solutions

Files:

  • src/State.cpp
  • src/State.h
  • package/Shaders/Utility.hlsl
  • package/Shaders/Common/SharedData.hlsli
src/**/*.{cpp,cxx,cc,h,hpp,hxx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

src/**/*.{cpp,cxx,cc,h,hpp,hxx}: Ensure SE/AE/VR runtime compatibility; use runtime detection patterns (e.g., REL::RelocateMember())
Include robust error handling and resource management with graceful degradation in the plugin code

Files:

  • src/State.cpp
  • src/State.h
**/*

⚙️ CodeRabbit configuration file

**/*: When reviewing PRs, please provide suggestions for:

  1. Conventional Commit Titles (if not following https://www.conventionalcommits.org/ or
    if the existing title does not describe the code changes):
    Format: type(scope): description
    Length: 50 characters limit for title, 72 for body
    Style: lowercase description, no ending period
    Examples:

    • feat(vr): add cross-eye sampling
    • fix(water): resolve flowmap bug
    • docs: update shader documentation
  2. Issue References (if PR fixes bugs or implements features):
    Suggest adding appropriate GitHub keywords:

    • "Fixes #123" or "Closes #123" for bug fixes
    • "Implements #123" or "Addresses #123" for features
    • "Related to #123" for partial implementations

Otherwise, use your standard review approach focusing on code quality.

Files:

  • src/State.cpp
  • src/State.h
  • package/Shaders/Utility.hlsl
  • package/Shaders/Common/SharedData.hlsli
🧠 Learnings (9)
📓 Common learnings
Learnt from: alandtse
Repo: doodlum/skyrim-community-shaders PR: 0
File: :0-0
Timestamp: 2025-07-05T05:20:45.823Z
Learning: In the skyrim-community-shaders repository, file deletion error handling improvements that replace existence checks and try-catch blocks with std::filesystem::remove error-code-based approaches are considered bug fixes rather than refactoring, as they address inadequate error handling and misleading log messages.
Learnt from: jiayev
Repo: doodlum/skyrim-community-shaders PR: 0
File: :0-0
Timestamp: 2025-08-03T18:37:19.690Z
Learning: ISReflectionsRayTracing.hlsl and ISWorldMap.hlsl in the skyrim-community-shaders repository are image-space post-processing shaders that perform color sampling and blending operations that need proper linear color space handling for the linear lighting system. ISReflectionsRayTracing handles screen-space reflections and should use conditional Color::IrradianceToLinear/Gamma conversions similar to ISCompositeLensFlareVolumetricLighting.hlsl. ISWorldMap performs 7x7 color accumulation that should be done in linear space similar to the pattern used in ISSAOComposite.hlsl.
📚 Learning: 2025-06-08T11:25:14.536Z
Learnt from: alandtse
Repo: doodlum/skyrim-community-shaders PR: 577
File: src/Features/WetnessEffects.h:36-36
Timestamp: 2025-06-08T11:25:14.536Z
Learning: In the skyrim-community-shaders project, boolean flags in C++ structs that interface with HLSL shaders use `uint` type instead of `bool` for compatibility reasons. This ensures consistent 4-byte size, proper 16-byte alignment in constant buffers, and cross-platform compatibility when passing data between C++ and HLSL shaders.

Applied to files:

  • src/State.h
  • package/Shaders/Utility.hlsl
  • package/Shaders/Common/SharedData.hlsli
📚 Learning: 2025-06-08T11:25:14.536Z
Learnt from: alandtse
Repo: doodlum/skyrim-community-shaders PR: 577
File: src/Features/WetnessEffects.h:36-36
Timestamp: 2025-06-08T11:25:14.536Z
Learning: In the skyrim-community-shaders project, boolean flags in C++ structs that interface with HLSL shaders use `uint` type instead of `bool` for compatibility reasons. This ensures consistent size, alignment, and cross-platform compatibility when passing data to shader constant buffers.

Applied to files:

  • src/State.h
  • package/Shaders/Utility.hlsl
  • package/Shaders/Common/SharedData.hlsli
📚 Learning: 2025-08-03T18:37:19.690Z
Learnt from: jiayev
Repo: doodlum/skyrim-community-shaders PR: 0
File: :0-0
Timestamp: 2025-08-03T18:37:19.690Z
Learning: ISReflectionsRayTracing.hlsl and ISWorldMap.hlsl in the skyrim-community-shaders repository are image-space post-processing shaders that perform color sampling and blending operations that need proper linear color space handling for the linear lighting system. ISReflectionsRayTracing handles screen-space reflections and should use conditional Color::IrradianceToLinear/Gamma conversions similar to ISCompositeLensFlareVolumetricLighting.hlsl. ISWorldMap performs 7x7 color accumulation that should be done in linear space similar to the pattern used in ISSAOComposite.hlsl.

Applied to files:

  • package/Shaders/Utility.hlsl
📚 Learning: 2025-08-17T18:37:35.839Z
Learnt from: CR
Repo: doodlum/skyrim-community-shaders PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-08-17T18:37:35.839Z
Learning: Applies to features/*/Shaders/**/*.{hlsl,hlsli,fx,fxh} : Avoid GPU register/buffer conflicts in HLSL; verify register usage (e.g., with hlslkit buffer scanning)

Applied to files:

  • package/Shaders/Utility.hlsl
  • package/Shaders/Common/SharedData.hlsli
📚 Learning: 2025-10-02T14:20:33.454Z
Learnt from: ThePagi
Repo: doodlum/skyrim-community-shaders PR: 1369
File: src/Features/SnowCover.cpp:515-515
Timestamp: 2025-10-02T14:20:33.454Z
Learning: In the Community Shaders codebase (skyrim-community-shaders repository), hardcoded shader resource slot numbers are used directly in code rather than being defined as named constants. This is the established convention and should not be flagged as an issue.

Applied to files:

  • package/Shaders/Utility.hlsl
  • package/Shaders/Common/SharedData.hlsli
📚 Learning: 2025-07-01T18:01:07.079Z
Learnt from: alandtse
Repo: doodlum/skyrim-community-shaders PR: 0
File: :0-0
Timestamp: 2025-07-01T18:01:07.079Z
Learning: In the skyrim-community-shaders project, simple scalar constants in HLSL shaders use #define (e.g., #define NTHREADS 128), while more complex constants use static const within namespaces (e.g., Math namespace in Math.hlsli). For epsilon standardization, #define is the appropriate choice since epsilon values are simple scalar constants.

Applied to files:

  • package/Shaders/Utility.hlsl
📚 Learning: 2025-07-05T05:20:45.823Z
Learnt from: alandtse
Repo: doodlum/skyrim-community-shaders PR: 0
File: :0-0
Timestamp: 2025-07-05T05:20:45.823Z
Learning: In the skyrim-community-shaders repository, file deletion error handling improvements that replace existence checks and try-catch blocks with std::filesystem::remove error-code-based approaches are considered bug fixes rather than refactoring, as they address inadequate error handling and misleading log messages.

Applied to files:

  • package/Shaders/Utility.hlsl
📚 Learning: 2025-08-05T17:40:44.828Z
Learnt from: ThePagi
Repo: doodlum/skyrim-community-shaders PR: 1369
File: package/Shaders/Lighting.hlsl:0-0
Timestamp: 2025-08-05T17:40:44.828Z
Learning: In the skyrim-community-shaders repository, ultra trees (object LOD trees) are detected using a compound shader define condition `defined(DO_ALPHA_TEST) && defined(LOD_BLENDING) && defined(RIM_LIGHTING) && defined(SOFT_LIGHTING)` because "they have no define" according to the comment. The `ExtraFlags::IsTree` flag is used for different tree handling (AO removal in skylighting) and may not apply to ultra trees specifically. Before replacing the compound condition with `IsTree`, verification is needed to ensure the flag covers ultra trees.

Applied to files:

  • package/Shaders/Common/SharedData.hlsli
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Validate shader compilation (Flatrim, .github/configs/shader-validation.yaml)
  • GitHub Check: Validate shader compilation (VR, .github/configs/shader-validation-vr.yaml)
  • GitHub Check: Build plugin and addons
  • GitHub Check: Run Shader Unit Tests
🔇 Additional comments (6)
package/Shaders/Common/SharedData.hlsli (1)

26-26: LGTM - Field addition aligns with C++ struct.

The uint IsNotNativeD3D11 field correctly replaces the previous padding and uses uint type for proper C++/HLSL constant buffer compatibility. Based on learnings, this project uses uint instead of bool for shader interface compatibility.

package/Shaders/Utility.hlsl (2)

378-386: LGTM - Position-based offset for DXVK shadow stability.

The spatial hashing approach using murmur3 with quantized world position provides stable shadow sampling patterns that won't flicker with TAA jitter on DXVK. The conditional correctly preserves the original frame-based behavior on native D3D11.

The quantization factor of 8.0 means the hash changes every 0.125 world units. This could potentially cause visible banding patterns in shadow penumbras at certain viewing angles. Consider testing with different quantization values if artifacts appear.


627-635: LGTM - Consistent spatial noise for DXVK path.

The noise generation mirrors the shadow sampling approach, providing stable per-pixel noise based on world position rather than frame count when running under DXVK. This prevents the shimmering artifacts caused by TAA jitter in the translation layer.

src/State.cpp (1)

791-792: LGTM - Correct propagation of DXVK flag to shader.

The boolean-to-uint conversion follows project conventions for shader constant buffer compatibility. Based on learnings, using uint instead of bool ensures consistent 4-byte size and proper alignment.

src/State.h (2)

48-48: LGTM - Runtime detection flag.

The isRunningOnDXVK boolean flag provides clean runtime state tracking for the DXVK detection, populated during adapter description parsing.


207-207: LGTM - Shader-compatible flag replaces padding.

The uint IsNotNativeD3D11 field correctly replaces the previous float pad0 with a meaningful flag while maintaining the struct's 16-byte alignment. Using uint ensures proper C++/HLSL constant buffer compatibility per project conventions.

Comment thread src/State.cpp
Comment on lines +710 to +719

// Detect Linux/Proton/DXVK by checking adapter description
std::string lowerDesc = adapterDescription;
std::transform(lowerDesc.begin(), lowerDesc.end(), lowerDesc.begin(), ::tolower);
isRunningOnDXVK = (lowerDesc.find("dxvk") != std::string::npos) ||
(lowerDesc.find("wine") != std::string::npos) ||
(lowerDesc.find("llvmpipe") != std::string::npos);
if (isRunningOnDXVK) {
logger::info("Detected Linux/Proton/DXVK environment - using spatial shadow denoising");
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🌐 Web query:

DXVK adapter description string D3D11 GetAdapterDesc

💡 Result:

Short answer

  • DXVK fills DXGI_ADAPTER_DESC.Description with the Vulkan physical device name (VkPhysicalDeviceProperties::deviceName, converted to wide chars). VendorId/DeviceId come from VkPhysicalDeviceProperties.vendorID/deviceID and memory fields from the device memory info; DXGI structs otherwise follow DXGI_ADAPTER_DESC semantics. Sources: DXVK uses Vulkan physical-device properties when enumerating adapters, Vulkan exposes deviceName/vendorID/deviceID, and DXGI_ADAPTER_DESC defines the Description field. [1][2][3]

Sources

  • DXVK project (repository / adapter handling / docs showing DXVK maps Vulkan physical devices to DXGI adapters). [1]
  • Vulkan reference: VkPhysicalDeviceProperties (deviceName, vendorID, deviceID). [2]
  • Microsoft: DXGI_ADAPTER_DESC / IDXGIAdapter::GetDesc (Description field semantics). [3]

🌐 Web query:

Wine DXVK llvmpipe adapter name identification

💡 Result:

Short answer — identify the llvmpipe adapter by checking Vulkan device names (vulkaninfo) or DXVK logs, then use that string with DXVK_FILTER_DEVICE_NAME to exclude/choose it.

How to do it

  • List Vulkan devices: run
    vulkaninfo | grep -i deviceName
    The output shows lines like "deviceName = llvmpipe (LLVM 15.0.7, 256 bits)" for software (llvmpipe) and your real GPU(s). Use the exact substring you want to match. [1][2]

  • Or read DXVK startup logs: DXVK prints adapter names when enumerating devices, e.g. "Skipping Vulkan 1.0 adapter: llvmpipe (LLVM ...)" — inspect your DXVK stdout/log to see the same name. [2]

  • Force/select a device in DXVK:
    export DXVK_FILTER_DEVICE_NAME="Your GPU device substring"
    (DXVK matches substrings from the Vulkan device name; if the filter matches the wrong device or none, DXVK will fail to create a device — use the exact substring from vulkaninfo/DXVK logs). [3]

Notes

  • If Vulkan lists only llvmpipe, the system is using Mesa software rendering (install or fix your GPU Vulkan ICD or set VK_ICD_FILENAMES to the GPU ICD JSON). [2]
  • You can also select by UUID with DXVK_FILTER_DEVICE_UUID (vulkaninfo shows UUIDs). [3]

Sources

  • Example of llvmpipe in Vulkan output / Mesa issues. [1]
  • DXVK logging and examples showing llvmpipe in adapter list. [2]
  • DXVK device-filter environment variables (DXVK_FILTER_DEVICE_NAME / UUID). [3]

References
[1] Mesa / llvmpipe example (vulkan/glxinfo output).
[2] DXVK/GitHub issues and community posts showing "llvmpipe" in DXVK logs.
[3] DXVK documentation / README (DXVK_FILTER_DEVICE_NAME and DXVK_FILTER_DEVICE_UUID).


🌐 Web query:

How to detect DXVK Wine Proton in Direct3D adapter description

💡 Result:

Short answer: you generally can't reliably detect DXVK/Proton/Wine just from the Direct3D adapter description alone. Instead check for DXVK-specific signs at runtime (logs, HUD, DLLs, env vars) or for mismatches between the reported adapter string and the underlying Vulkan driver. Sources: DXVK docs and project pages. [1][2][3][4]

Practical checks (ordered from most reliable to least):

  1. Look for DXVK logs or output
  • DXVK prints logs to stderr when used under Wine/Proton (or to files when DXVK_LOG_PATH set). If you can capture process stderr or the game folder, presence of d3d9/d3d11/dxgi log messages proves DXVK. [2][3]
  1. Check for DXVK binaries / DLL overrides in the prefix/process
  • If the process loads DXVK DLLs (d3d11.dll, dxgi.dll, d3d9.dll from dxvk) that’s definitive. Inspect loaded modules (Process Explorer / lsof / /proc//maps) or the Wine prefix to see installed DLLs. [2][3]
  1. Use DXVK_HUD or environment variables
  • DXVK has a HUD (DXVK_HUD) that can show "version", "devinfo" and device strings. If enabling DXVK_HUD produces the overlay, DXVK is active. Also check for DXVK_/VKD3D_ env vars in the process environment. [1][4]
  1. Detect vendor/driver mismatch (heuristic only)
  • Under DXVK the adapter description will often reflect the host Vulkan driver (Mesa, RADV, NVIDIA) rather than a Windows native driver. If the adapter string contains obvious Linux/Vulkan driver names (e.g., "RADV", "Mesa", "vulkan", "Intel Vulkan"), or mentions "Proton"/"Wine" in other outputs, that’s a hint but not definitive. This is fragile and can be spoofed. [1][4]
  1. For D3D12: check for vkd3d(-proton)
  • D3D12 translation on Proton uses vkd3d(-proton) rather than DXVK; look for vkd3d logs, DLLs or HUD differences. [1][3]

Example quick commands (Linux/Wine host)

  • Check loaded modules: lsof -p or grep dxgi /proc//maps (shows dxgi/d3d11 DLL path). (See point 2.) [2][3]
  • Run with DXVK_HUD=devinfo,fps to force the overlay and verify. (See point 3.) [1][4]
  • Inspect stderr or set DXVK_LOG_PATH to force log files and inspect them for "info: " lines. [2][3]

References

  • DXVK official site / FAQ (HUD, usage). [1]
  • DXVK README / setup and logging behavior (how it emits logs under Wine/Proton and DLLs). [2][3]
  • HOWTO / Linux pages describing DXVK_HUD and devinfo behavior. [4]

If you want, tell me whether you need a small script (Windows/Wine) to perform these checks automatically and I’ll give one.


Detection keywords are unlikely to match adapter descriptions.

The DXVK adapter description is populated from the Vulkan physical device name (e.g., "llvmpipe (LLVM ...)", "RADV", "Intel Vulkan"), not from DXVK or Wine identifiers. Checking for "dxvk" or "wine" strings in the adapter description will not reliably detect DXVK/Proton environments—these translation layer names do not appear in the reported device names. The "llvmpipe" check is valid and will match software rendering, but it doesn't specifically identify DXVK or Wine.

For reliable detection of DXVK/Wine at runtime, consider checking for DXVK-specific signs: presence of DXVK logs, DLL overrides, environment variables (DXVK_*), or the DXVK HUD. Adapter string matching alone is insufficient for this purpose.

@github-actions
Copy link
Copy Markdown

✅ A pre-release build is available for this PR:
Download

@doodlum doodlum closed this Dec 31, 2025
@davo0411 davo0411 deleted the linux-shadow-flicker branch January 26, 2026 23:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants