protonscr

Static samplers rendering Assetto Corsa Evo 0.6.x

vkd3dclosed
HansKristian-Work/vkd3d-proton#3030 · opened 2026-05-16 by Michael1459 · updated 2026-08-10 · 12 comments · github
MMichael1459 2026-05-16 github

Some information / screenshots in this steam forum thread

https://steamcommunity.com/app/3058630/discussions/0/797842245107687640 (Although it's the usual page 1 of people telling him he's bad for using linux - page 2 has some screenshots and discussion)

The title renders ok on native dx12 under windows but, since 0.6.x was released, some textures appear to be rendered with CLAMP_EDGE rather than REPEAT

If you have access to the title, this can be easily seen in the opening titles where the game renders a car on top of a large plane and we get one square of texture under the car and long lines of solid colour expanding to infinity.

https://steamcommunity.com/sharedfiles/filedetails/?id=3726927607

I tried to debug this (and I'm willing to do more - I think I've just reached my limited knowledge of vulkan) by using renderdoc. To my untrained eyes the data in renderdoc looks ok. There's a shader that references 5 static samplers and the static samplers have the same parameters as the dx12 render.

But, if I edit resource.c and hard code VK_SAMPLER_ADDRESS_MODE_REPEAT in d3d12_setup_static_sampler_info() for AddressMode UVW, for every static sampler the floor renders ok like this :-

https://steamcommunity.com/sharedfiles/filedetails/?id=3725389212

So I thought I was along the right lines. There's a long timeline of commands for this scene, I note earlier in the scene, before it gets to the floor texture, it does set some of these static samplers to CLAMP_EDGE so I wondered if the issue is that the state the shader sees is stale? And thus me making everything REPEAT avoids that happening because the stale state is REPEAT. But that's just a guess.

If I edit the shader in renderdoc there's basically a _155 variable with a REPEAT and 2 aniso samplers _156 and _157 with ANISO. If I do #define _157 _155 to override the floor will render with REPEAT but these samplers look ok in renderdoc. So potentially some conflict with ANISO?

In terms of nvidia drivers and proton versions it doesn't seem to matter. I've tried latest release Nvidia drivers, I've tried their vulkan beta drivers. I've tried proton 10 and proton 11 beta in steam. To do the code change above I cloned the latest from here and compiled - and the bug happens with them all.

At this point it's not obvious to me whether this is a game bug, a proton issue or a driver bug. My logic here is that the game renders ok on windows but I guess that doesn't preclude the dx12 drivers ignoring something odd they are doing and rendering correctly. Previous versions of the game rendered ok on both dx12 and proton. So they changed something to trigger the issue. Because we have source code for proton it seemed the easiest place to start debugging.

I'll attach a PROTON=1 log as a follow up (I need to boot into linux and remove all the hard coded changes and ERR messages I've added to get info to get a clean log) and I'll attach a screenshot of the samplers in renderdoc to make it more clear what I'm describing above.

Thanks.

MMichael1459 2026-05-16 github

steam-3058630.log

And NVIDIA-Linux-x86_64-595.44.07 to give an exact driver version

Ddoitsujin maintainer 2026-05-16 github

is it trying to dynamically index into those samplers or something? Game bugs in that area aren't exactly uncommon, but would need to see the (original) shader to figure out what's happening.

MMichael1459 2026-05-16 github

(Let me first say that there's a possibility this doesn't happen on AMD hardware, if so it's probably a nvidia driver bug but putting that aside until I get some confirmation on that....
edit: https://images.steamusercontent.com/ugc/12560336593843223685/78698CB60996DA934780ACC7F96DB07EA7B79117/ this looks ok so perhaps points to nvidia vulkan driver being the culprit?
)

The dx12 disassembly has

SamplerState samLinearWrap : register(s0, space0);
SamplerState samLinearClamp : register(s1, space0);
SamplerState samAnisoHighWrap : register(s4, space0);
SamplerState samAnisoLowWrap : register(s5, space0);
SamplerComparisonState samShadow : register(s6, space0);

And then the code (tons of it) is referencing SamAnisoHighWrap et al all over.
Far too much code for me to start debugging that. The 'it works' thing I guess is that it renders beautifully on windows dx12 suggesting there's no obvious 'they're using the wrong sampler in the shader' bug.

In renderdoc pipeline state tab (for dx12) I see 'Samplers' and those 5 samplers described above and the parameters look ok - and they look the same as the vulkan equivs.

In the vulkan / proton fragment shader I see the same 5 samplers

layout(set = 3, binding = 0) uniform sampler _155;
layout(set = 3, binding = 1) uniform sampler _156;
layout(set = 3, binding = 4) uniform sampler _157;
layout(set = 3, binding = 5) uniform sampler _158;
layout(set = 3, binding = 6) uniform samplerShadow _159;

And everything looks fine on these parameter wise.

And these are referenced throughout the shader, e.g

sampler _270 = *_159;
sampler _271 = *_158;
sampler _272 = *_157;
sampler _273 = *_156;
sampler _274 = *_155;

and then

  if(_1465) {
      float4* _1651 = &_127._child0[89];
      float4 _1652 = *_1651;
      float _1653 = _1652.x;
      SampledImage<float, 2D> _1654 = SampledImage(_1460, _272) : [[NonUniform]];
      float2 _1656 = CompositeConstruct({_1025, _1027});
      float4 _1655 = ImageSampleImplicitLod(_1654, _1656, Bias(_1653));
      float _1657 = _1655.x;
      float _1658 = _1655.y;
      float _1659 = _1655.z;
      float _1660 = _1655.w;
    } else {
      SampledImage<float, 2D> _1661 = SampledImage(_1460, _272) : [[NonUniform]];
      float2 _1663 = CompositeConstruct({_886, _888});
      float4 _1662 = ImageSampleImplicitLod(_1661, _1663, );
      float _1664 = _1662.x;
      float _1665 = _1662.y;
      float _1666 = _1662.z;
      float _1667 = _1662.w;
    }

    float _1262 = Phi(_1657, _1664);
    float _1265 = Phi(_1658, _1665);
    float _1268 = Phi(_1659, _1666);
    float _1271 = Phi(_1660, _1667);

I note that on the Descriptor Layout there's actually 8 samplers, but presumably 3 of them are not referenced and not shown in renderdoc 'pipeline state'

The odd thing is, if I edit the shader code in renderdoc and change it from layout(set = 3, binding = 4) uniform sampler _157; to layout(set = 3, binding = 3) uniform sampler _157; This binding = 3 shader (which isn't referenced in the code until I add it) says 'CLAMPEDGE' but it tiles ok then? So that confuses me. It's like opposite day or something, yes means no and no means yes.

i.e the original code (that renders clamp edge incorrectly for the floor) uses a shader in renderdoc that looks like this

Set 3, 4: _157 Sampler Sampler 3627 UVW: Repeat Min&Mag&Mip: Anisotropic Aniso 16x, LODs: 0 - FLT_MAX and I change it to

Set 3, 3: _157 Sampler Sampler 2510 UVW: ClampEdge Min&Mag&Mip: Point, LODs: 0 - FLT_MAX

But the effects seem reversed, i.e running 'Start replay loop' with the 3,3 gives me a nice tiled plane and with 3,4 gives me clampedge?!?!

Same thing happens on windows using vkd3d-proton so if it's a nvidia bug it's in their windows driver too.

Perhaps I need some software reference driver that can output something correct to point the finger or eliminate the nvidia driver...and perhaps I should put some hard-coded aniso 16x on all the samplers and see if it's not that. Because that's another notable difference here between the samplers where repeat seems to function and where it doesn't, one has 16x Aniso.

But yeah, I appreciate any insight or ideas to test further.

HHansKristian-Work maintainer 2026-05-18 github

Reproduced something. It does not reproduce on RADV, neither on NV with descriptor heap, so it's likely a buggy case with embedded samplers ...

HHansKristian-Work maintainer 2026-05-18 github

This must be a driver bug. I cannot understand anything else otherwise. It works fine on RADV and NV with heap path enabled and I ruled out a state bug on our end.

HHansKristian-Work maintainer 2026-05-18 github

Reported to NV. You can try using heap path and see if that helps, otherwise I don't know what to do.

MMichael1459 2026-05-19 github

Thanks for your help Hans & pushing the bug report forwards.

I'll try the descriptor heap (but I can easily get pretty enough graphics with my hard-coded hack until the bug fix appears)

Ppdaniell-nv 2026-05-26 github

Reported to NV. You can try using heap path and see if that helps, otherwise I don't know what to do.

Our latest Vulkan beta driver (found at https://developer.nvidia.com/vulkan-driver) should have a fix for this problem. Let me know how it works out for you if you have a chance to give it a try. Thanks.

MMichael1459 2026-05-29 github

Firstly apologies for not seeing your post earlier.

I've just tested latest vulkan beta driver and it seems to be rendering fine now. Many thanks for the speedy fix.

(Hans : I used the descriptor-heap-rebase all week with this game and that path has been rendering fine too)

Ppdaniell-nv 2026-05-29 github

Awesome, thanks for trying the beta driver out. :-)

Ttonystratum 2026-08-09 github

Sorry if this is off-topic, but since this issue is referenced in the NV patch notes for the latest driver with AC EVO, I thought it would be appropriate to ask here @pdaniell-nv

I have a problem with texture flickering, that is e.g. on Nordschleife the trees, trailers, and other stuff off-track is popping in and out, may be of low resolution or distorted in shape. Sometimes the car textures (e.g. dashboard elements) are not rendered too.

Cachyos, Proton Experimental, driver 610.57.04. Many thanks for any help!

Ppdaniell-nv 2026-08-10 github

We are aware of an issue with depth image corruption after copies from color images. I'm not sure if this is the same one you're seeing. Once we fix the depth image problem we should revisit the issue you describe if it still exists.

Proton versions