#weird lighting on signs
1 messages · Page 1 of 1 (latest)
Thank you -- can you also please let us know:
- is this is on a desktop PC, laptop, or Steam Deck?
- if not Steam Deck: this this on Windows 10 or Windows 11?
Desktop Linux/proton steam, no special commands, AMD Radeon RX 5500M; I'll try to reproduce on windows too
Got it -- yes, I am able to repro this issue on my Steam Deck. We'll take a look into this.
does this only happen with russian text?
can't reproduce this with german or english on my laptop - AMD Radeon 760M (radeonsi phoenix
LLVM 19.1.7 DRM 3.61 6.14.5-arch1-1)
oops, turns out I can reproduce it - when running the game in Proton instead of using the native port
no idea why that should make a difference, but at least here it does.
@twin nest is it the same on your machine? does this look fine when using my native linux port?
This is where having a frame capture would be helpful because could see exactly what’s wrong in the light buffer
My guess is what’s happening in the lit font rendering is writing a 0 to the light buffer render target which then the post process effect reads and it overbrightens it significantly
sucks that it only happens in proton, not sure how to use apitrace there
(for some reason it doesn't even run in regular wine)
didn't play the native long enough to say confidently
i noticed this effect mostly in places with very dynamic shadows
if you play the GIF frame by frame, the note is bright in the shadowed spot until the camera zooms in and then the game applies the shadow properly to the note but not to the text
Yeah the light correction effect is only applied when zoom inspecting
So if the buffer has bad values in it, that wouldn’t impact the rendering when not inspecting
there's also this screenshot (the note in Stargazer lies on the edge of a shadow)
Hmm interesting
you could load the map through console (map sh_library01.map) and then use notarget and noclip to quickly get to the place to check (notarget so the enemies leave you alone)
I got an apitrace for running the windows version in wine where this bug happens
unfortunately it's 630MB 🙃
and I can reproduce it with llvmpipe
there are so many gl calls each frame -_-
You can build apitrace and set the steam launch option to LD_PRELOAD={path to apitrace build}/build/wrappers/glxtrace.so %command%
thanks, good to know :)
got it to work with wine (and skindeep.exe I compiled myself) now. I'm getting close to the problem but.. it's so many fucking gl calls, it's unbelievable: >12000 in a single frame
Stab in the dark but I recently added a workaround for z-fighting in the remastered Tomb Raiders force_gl_depth_component_type_int=true
nah, it's something about a texture that is first rendered into and later used as a mask
in the "good" trace (from native skindeep) the mask masks the whole postit except the letter, in the bad trrace (from wine) it masks only the letters.. or sth like that. currently trying to find out where/how that mask texture is created
because the whole postit is supposed to be highlighted => as bright as the area around the letters in the screenshot above
good mask
bad mask (in GL_TEXTURE2)
@spring lodge how is that brightness mask texture created? and what kind of opengl call is used to tell it to render into that texture? that texture has id 30 in my trace, but glBindTexture(..., 30) is only called when this texture is used, apparently? (I assume it gets updated each frame?)
I wish I actually knew opengl :-p
hmm, apparently glFramebufferTexture2D() and it looks like that is only done once and afterwards they don't need to be "synced"
If its hard to look through the gl calls you could try simply dumping the output of both traces into a text file run via apitrace replay --verbose name.trace &> dump.txt then try using diff or meld to spot any differences
It’s written to in interaction shaders as well as I think the basic surf
The font render should use basic surf
Just look at the shaders that write to output=2
I think it's not the font rendering that's going wrong, but the rendering of what's supposed to become the black quad
the font is probably rendered on top later and that should be fine
hrm, this makes no sense, too much noise..
@twin nest do you think you can create a minimal testmap that reproduces the issue? ideally spawning the player so she immediately looks at that thing?
no, only in the interaction shaders, and in that case it's interaction.frag
I wonder if because the attachment is still bound when the font is rendered it’s writing garbage
I don't think it's the font rendering
if the font stuff from the bad mask was rendered on top of a black quad it would be fine
this is probably exactly what's supposed to happen: write the dark quad and then the font on top, the letters themselves grey or whatever and the background of the polys containing them black
for reference, the finished frame in broken vs good
It almost seems like the alpha isn’t working
Can you try force setting the glimp.brokenAMD variable to true?
here
oh and also i do see this bug on Linux port and English locale, definitely
also you can open the memory palace - on the same map, the note in MP is overlit
doesn't make a difference
thank you very much, @twin nest !
with your testmap it also happens with the native version 🙃
but only on my laptop with AMD GPU and with llvmpipe, not on my desktop with nvidia, so I can compare on my desktop with nvidia vs llvmpipe.
and using qapitrace with the trace from your map is so fucking fast, it's unbelievable. compared to my other trace from sh_library01 it's a difference like night and day
on the downside, the bug is different now:
above on the good screenshot the whole note was as bright as the area around the letters - now it's the opposite, the area around the letters is brighter on the bad screenshot
but the difference is again in that brightness texture:
This is GL_COLOR_ATTACHMENT2 - on the left when running with nvidias driver, on the right when running with llvmpipe (radeonsi appaered to look the same).
The upper surfaces are from gl call 70891, the lower ones from gl call 70892 (in my sd_native2.trace that I'll try to upload somewhere soon).
So apparently the mesa driver renders something into that framebuffer (lightOutput or interactionLightBlend.frag ) here while nvidia doesn't (and nvidia looks more correct)
ok, after reducing the trace to just two frames with apitrace's gltrim, it finally had a size I could upload here
also wrote it all down here: https://github.com/DanielGibson/SkinDeep/issues/6
One place this happens is the "You're not my mom!" note on the basketball hoop on sh_library01.map, when "using" it so one zooms into it. There it only happens when running ...
oh damn, of course the gl call numbers are different now that I trimmed the trace -_-
the interesting gl call (that adds the glitchy black blocks where the letters are) is 51347 in the trimmed trace
and the drawcall that uses texture id 30 aka GL_COLOR_ATTACHMENT2 to make the rendered note look glitchy is 52203
At this point I'm out of ideas, but maybe @spring lodge or @thorn canyon have an idea WTF is going wrong there?
hmm it kinda seems like on nvidia lightOutput = light; in interaction.frag has no effect (at least visible in game, haven't traced that yet), because changing it to lightoutput = vec4(1,0,0,1); or vec4(0,0,0,0) or vec4(1,1,1,1) doesn't make a difference
this is potentially interesting: this is from a new trace, where I modified the shaders (I wish apitrace let me do this in the tool like renderdoc does).
interactionLightBlend.frag uses lightOutput = vec4(0,0,1,1); (=> sets lightOutput to blue)
interaction.frag uses lightOutput = vec4(1,0,0,1); (=> sets lightOutput to red)
On this screenshot above is GL_TEXTURE2 (that brightness texture) in the drawcall that makes the area round the letters look weird (on mesa drivers).
on the left is how it looks when making qapitrace use llvmpipe, on the right is how it looks with the nvidia driver
the color on the right is #ff00ff, i.e. vec4(1,0,1,1)
so in the nvidia driver the results of interaction.frag and interactionLightBlend.frag are blended, on mesa they aren't.
(also note that this buffer is GL_RGB16F, i.e. without an alpha chan)
the shader used in that drawcall does this, btw:
// Get luminance at this texel
float luminance = texture(uTexture2, temp1.xy).x; // this is the texture from the screenshot
and then does calculations with it. this means that it only uses the red channel, even though this texture is RGB and, as far as I can tell, gets meaningful data assigned to .x and .y (aka .g and .b) as well (maybe an average of RGB should be used?).
so with the left texture (where the letter-blocks are plain blue, #0000ff), luminace will be 0, while on the right one (where they are #ff00ff) it'll be 1
oh wait is this the classic Nvidia is happy with uninit components but other drivers aren't
in that light texture only the red component is sampled from, see brightness.frag line 32
originally that RGB16F texture was like a R16 (normalized int texture with one component), but not every driver supported normalized 16 bit so I switched to RGB16F
must have something to do with blending
at the draw call that adds the blue/pink rectangles to the red background (see my last screenshot), the blend state is this:
the drawcall uses interactionLightBlend.frag, but I modified the line setting lightOutput to:
lightOutput = vec4(0,0,1,1);
and nvidia adds the colors (adds blue to red to create that pink), while Mesa replaces red with blue (in the affected areas)
out of curiosity what happens if you do like
is that GL_BLEND state (supposed to be) used for all fragment shader output, or just for the first or something (the proper color output)?
and assuming it's supposed to be used for all, is this behavior correct given the blend state (I haven't looked up what it means exactly yet)
vec4 lightAlpha = light * alpha.w;
lightOutput = vec4(lightAlpha.w, lightAlpha.w, lightAlpha.w, 1.0f);
mainly I'm curious what's in that 4th component
in which shader?
because if it's different b/w the two drivers that would explain it
in interactionLightBlend.frag
that's what the draw call is using right?
yes
oh wait I think I understand now
or wait hm
I wonder if this fixes it
lightOutput = light * alpha.w;
lightOutput.w = alpha.w
nope
would be weird as the buffer behind lightOutput doesn't have a .w/.a chan
(the other suggestions didn't help either)
well it would use it for alpha blending still even if the destination doesn't have an A
one potential source of weirdness certainly is that GL_BLEND_SRC is GL_SRC_ALPHA, even though the source doesn't really have an alpha chan
but yeah it seems like the blending is applying to both location 0/1 on nvidia but only location 0 on the mesa/amd one?
maybe blending then assumes alpha = 1 in one driver and alpha = 0 in the other?
my brain is mush at this point, but with the blend state above, is it correct that dst_R = (src_R / src_A) + dst_R, where src is what is currently computed in the shader and dst is what is already in the buffer?
(in that case, with src_A = 1 it'd be src_R + dst_R which is what we're seeing on nvidia, and with src_a = 0 we're in a world of shit because we're dividing by 0)
no, doesn't fix it
not even when explicitly setting lightOutput.a = 1;
I found a post from 2005 which says alpha blending on floating point output buffers only works on NV hardware lmao
There must be an extension
I wonder if that’s what it is though
one would hope that this has changed by now
It certainly explains the result we’re seeing though
can you check if this assumption is true?
It does work on the PC AMD driver though
Is it possible whatever the extension is just isn’t implemented in Mesa?
qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, glConfig.vidWidth, glConfig.vidHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); doesn't help either
here's the trace I used for the screenshots above, with the modified shaders that write just red or blue
that's no extension, check https://www.khronos.org/opengl/wiki/Blending
(search for "float")
it mentions float textures several times without any note of extensions, apparently the only specialty is that (unlike with normalized int textures) the blending result is not clamped to [0, 1]
Was this in interaction blend or just interaction
interaction blend
I think try an rgba texture set it to 1 in regular interaction but don’t change it in blend?
Because if you set it to 1 in blend then it would overwrite all the transparent pixels which is the bad result anyway, like that would break it on Nvidia also
no difference
Also I think you have src and dst backwards maybe? Isn’t dst is what’s in the buffer right now and src is what you’re writing,
Dst alpha is set to 1
In the blend state
that's what I wrote?
"where src is what is currently computed in the shader and dst is what is already in the buffer?"
idea: you could try to fuck up the shaders so it looks the same kind of broken on nvidia (or AMD windows or whatever)
maybe we can deduce what's going wrong from there
Oh ok sorry I misread haha
Wouldn’t setting the interaction blend alpha to 1 just break it on Nvidia though?
Like I’d expect you get the same result then
Huh
I wrote down the new findings at https://github.com/DanielGibson/SkinDeep/issues/6#issuecomment-2880621203
One place this happens is the "You're not my mom!" note on the basketball hoop on sh_library01.map, when "using" it so one zooms into it. There it only happens when running ...
gotta take a break now, otherwise my brain will run out of my ears
Haha sounds good, thanks for all the research!
I have to go to jury duty but I will look at it later tonight hopefully
just got one small idea: where is that blend func set? a few calls before glDrawElements() that adds the blue/pink crap is a glBlendFunc() call
I could try if using (GL_ONE, GL_ONE) makes a difference
(no worries if you answer that later, have fun at jury duty, I just wanted to get the idea out of my head)
glBlendFunci() (from GL4.0) might be relevant, and maybe also glEnablei(GL_BLEND, idx)
My understanding is glBlendFunc is supposed to set it for all targets bound
maybe it doesn't in Mesa?
@thorn canyon any idea?
ok, found where that blending is set, RB_GLSL_CreateDrawInteractions() in draw_glsl.cpp, GL_State(GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE | GLS_DEPTHMASK | backEnd.depthFunc);
however, GLS_SRCBLEND_ONE doesn't help
calling
qglEnablei(GL_BLEND, 1);
qglEnablei(GL_BLEND, 2);
qglBlendFunci(1, GL_ONE, GL_ONE);
qglBlendFunci(2, GL_ONE, GL_ONE);
after the GL_State() call doesn't help either (in the red/blue testcase). I might really be out of ideas now
If you change interaction blend to just write vec4(0,0,0,0) to light output, what happens?
based on the original shaders or my modifications that write red/blue?
Instead of writing the blue in blend just write all 0s
if interaction.frag writes 0,0,0,0 and interactionLightBlend writes what it's supposed to write, it looks ok in both cases
but I think you meant the other way around
with interaction writing red and interactionLightBlend writing 0,0,0,0 it looks broken on mesa and ok-ish on nvidia, like before
same when interaction writes light (like originally) and interactionLightBlend writing 0,0,0,0
Ok, it seems like just in general the alpha blending is not working on mesa
why alpha?
even with glBlendFunc(GL_ONE, GL_ONE) it behaved like this
blending in general seems broken for that brightness texture thing
with or without alpha
yes, llvmpipe, that's what I'm using most of the time
(only occasionally I verify on my laptop on its AMD iGPU)
Ah ok
you could compile llvmpipe for windows to see if it behaves the same there - you can actually build an opengl32.dll from it
or use mesa-llvmpipe-x64-*.zip from https://github.com/mmozeiko/build-mesa/releases/tag/25.1.0 if you trust some rando on github
In the original apitrace, are the glBlendFunc etc calls definitely are buffers are set to color attachment 0 and 2?
yes
and the screenshot above from the glblend state was from that glDrawElements at the bottom, which is what added the blue/pink crap
but it's also clear from the code that blending is enabled: the only place using interactionLightBlend is RB_GLSL_CreateDrawInteractions() and right before that call there's GL_State(GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE | GLS_DEPTHMASK | backEnd.depthFunc);
(ok, not sure where the glEnable(GL_BLEND) is, but why would you configure src and dst blend mode if you wouldn't expect blending to be enabled)
Can you view the blend state for each different target in this?
My theory is maybe this is the issue
Because there is an integer render target, even though it’s not active, it thinks it needs to do per-color buffer blend state but it might be that the state is only being set for color buffer 0
which should be like the “global” state since we don’t set per target
I have no idea if it’s true but haha that’s my theory
Wouldn’t be surprised if it’s related to integer render targets somehow though since the other bug was also
Which makes me figure the path is not used that often
no, I don't think so
could be
however, I added these calls in RB_GLSL_CreateDrawInteractions(), without effect:
GL_State(GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE | GLS_DEPTHMASK | backEnd.depthFunc);
// the next 4 are new
qglEnablei(GL_BLEND, 1);
qglEnablei(GL_BLEND, 2);
qglBlendFunci(1, GL_ONE, GL_ONE);
qglBlendFunci(2, GL_ONE, GL_ONE);
R_GLSL_SetActiveProgram("interactionLightBlend");
so even if the blend state was only set for color buffer 0, it should now be set for the other ones as well
(I wasn't sure if I needed to use index 1 because it's for layout(location = 1) out vec4 lightOutput; or 2 because it's GL_COLOR_ATTACHMENT2, so I set both)
would it be much work to turn that integer color attachment into normalized integer or something?
(what is it good for anyway?)
if I use qglTexImage2D(GL_TEXTURE_2D, 0, GL_R8, glConfig.vidWidth, glConfig.vidHeight, 0, GL_RED, GL_UNSIGNED_BYTE, NULL); for customMaskTexture, the testlevel looks like it should, so your hunch about this being related to the integer texture (AGAIN) might've been correct
(unless something else broke by changing the custom mask texture type which just accidentally "fixes" the notes issue)
I was concerned there were more integer render target issues when looking through the code when fixing the other bug. @safe pebble are you able to delete the if statement @spring lodge points out above and see if that fixes the problem?
So the only thing is without the mask the brightness.frag might not apply the extra zoom brightness? So to completely test it I think would have to change it so it always applies the extra brightness regardless of the mask?
why does the mask require an integer texture anyway?
I will
those logic ops have been around since opengl 1.0, but (not-normalized) integer textures are a lot more recent, AFAIK, so the logic ops shouldn't need them?
it doesn't
So like you mean have the shader convert from the normalized float to the uint representation and then do the mask?
yeah, maybe (would just have to multiply with 255 and cast to int, right?) - where is that mask used in the shaders?
Brightness.frag and Outline.frag
how do you get those different integer values into the texture/buffer?
ok, set with customMaskPass.frag
@thorn canyon do you know of those logic ops, when used with regular normalized integer textures like GL_R8, operate on the integer values?
So when storing 8.0/255.0 in the shader, it's treated as 8u by the logical op?
if so, in theory it should work to make that texture GL_R8 and
- in customMaskPass.frag use
resultCustom.x = float(uCustomPostValue) * (1.0/255.0);(or similar, whatever makes the glsl compiler happy) - in brightness.frag use
uint inspectMask = uint(texture(uTexture1, temp1.xy).r * 255.0) & POST_INSPECT_LUMINANCE; - in outline.frag use
int mCenter = int( uint(texture(uTexture1, uvCenter).r * 255.0) & outlineMasks );(and similar for top/right/topright)
Do you have the api trace for download somewhere?
Honestly I can't answer your question. I don't normially work in this part of the driver, not my strong area
Think I maybe found the issue just need a second to understand the code I was blindly editing 😛
\o/
I guess you could tell if it works if like the frob outline and inspect outline still worked?
hmm yeah, probably, I guess I should take screenshots of the working state first for comparison
Beware that OpenGL specs also specify glLogicOp() logical operations being disabled with sRGB framebuffer target.
not relevant here, I think, but good to know
(from https://unlimited3d.wordpress.com/2020/01/08/srgb-color-space-in-opengl/)
Ok, I think I understand what is happening. There is some blending code that is skipped if an integer buffer is detected. The code is to naive is take the number of color attachments and uses that count to check against the integer buffer mask so it thinks the second color attachment is the integer buffer since its attached at color attachment 1
sounds very plausible
is using integer color attachments so unusual or why do we run into so many bugs there?
(I mean usually I find one mesa bug every few years or so :D)
and it's highly unusual that AMDs windows driver works better than radeonsi, never happened before
well its probably just a corner case that nobody normally hits when using them
This should solve the issue
I'll be adding piglit tests for these issues so any regression in future should be caught
yes, this works, thanks a lot for fixing it! :)
I think it's just the number of new games coming out that are using OpenGL PLUS integer render targets is very low
No problem. All your help tracking it down made it much easier 🙂
definitely, thanks a bunch, I woudl not have been able to figure this out as quickly since i don't have an easy way to debug on SteamDeck haha
but those have been supported since GL3 or so? they should've been used more at some point in the last 15 years or so?
Is this that last of the linux/mesa specific issues?
if this also fixes the one that looked the same but only happened in wine/proton, then I think so
hopefully 🤞
how long does it usually take for Mesa driver changes to be pushed up to the Steam Deck drivers?
well the change that disabled blending for integer buffer formats was 6 years ago, so it's possible that between 15 and 6 years ago it worked?
and like in the past 6 years how many new OpenGL games that use integer render targets have their been?
probably pretty few since vulkan came out, but the old ones are still played and some source ports (and TDM) do advanced shit
reminds me I wanted to check if TDM has the same line issue, I think someone mentioned that
well and also Steam Deck greatly increased the number of people gaming on linux
didn't some tomb raider game use opengl?
in its linux port
I vaguely remember something like that..
but then of course again, someone has to report and investigate such glitches
"The port is using Vulkan on Linux" for Rise of the Tomb Raider
and nowadays when native linux ports don't work people just use proton and the directx renderer 🤡
right
Tomb Raider 2013 used OpenGL
I believe it is fairly quick these days. I'm pretty sure they have someone assigned to make sure the bug fix releases get released reasonably fast
do they stick to mesa releases or do they push git snapshots or custom patched versions?
the linux port was a bit later, 2016 or so.. but shit, time flies
I'm not entirely sure. I know that a while ago it was getting very stable and bugs were fixed but not landing for a long time. Someone got assigned to making sure we update more regularly but not sure if they just stick to official bug releases
*getting very stale
Even if they do sitck to mesa releases the bug releases are dropped fairly often. For example the first fix for the begin calls went out in a release today
funny, now 25.0.x is more up-to-date than 25.1.x
I wonder if as a workaround it would've helped to make the integer buffer the last color attachment
(so when iterating the active ones ctx->DrawBuffer->_IntegerBuffers & (1 << i) wouldn't match)
yep, seems like it does \o/
and the code changes to do this are minimal: https://github.com/DanielGibson/SkinDeep/commit/04fa4c12b7b998cafe1ebf7675ec1c0a7a71677c
they screwed up their check (for active color attachments) and making
it the last color attachment works around that.
https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/34990
is the upstre...
verified on my laptop with radeonsi
might even work around similar bugs we just haven't noticed yet
huh. I think it also improved the lighting on the vent locks
if you press Shift, zoom into the locked vents and wiggle your camera around, unpatched versions have this weird light spots
huh. I wonder if that is another mesa bug or the same one as this
(probably someone who understands the mesa source should grep for DrawBuffer->_IntegerBuffers and check all occurrences - good news is, it's only 10, or 14 if you grep for only _IntegerBuffers)
Oh that’s a good idea. Will look to integrate it on our side
There were some other issues on Proton/Steam Deck with the light brightness effect which makes sense given the bug
If you had a volumetric light it probably alpha blend and instead would make sense that it’d over-bright it. So there was a bug on Steam Deck where some of the notes were too bright
Would make sense in the vent cause there’s like dust and stuff which also is interaction blend and that could cause problems as well
not in the vent, on the vent 🙂 #1344023574004105226 message
@thorn canyon I wonder if it would be easier to set up _IntegerBuffers in the way most of the checks erroneously expect it to be than to fix all the checks
I'm looking into it. I'm actualy concerned there are even more bugs here, there are other masks that do the same thing as _IntegerBuffers
oh, great :-D
and probably the other ones are similarly bad documented
GLbitfield _IntegerBuffers; /**< Which color buffers are integer valued */
I mean that kinda explains what it's for on a very high level, but the meaning of the bits is also kinda important?!
Yeah I've created a complete new fix https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/35014