-
Notifications
You must be signed in to change notification settings - Fork 527
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Washed-out colors / HDR issues? #1180
Comments
It's surprising that Metal behaves differently here, I would have expected that GL is the issue (since sokol_gfx.h has a hack here so that the GL backend behaves the same as the Metal and D3D11 backend when it comes to SRGB handling: Lines 9123 to 9145 in c1cc713
...in this commit: ...to find the related changelog entry search for One potential difference might be the pixel format in CAMetalLayer vs sokol_app.h, but according to the documentation, both use BGRA8Unorm: https://developer.apple.com/documentation/quartzcore/cametallayer/pixelformat?language=objc vs: Line 3993 in c1cc713
...another difference might be the MTKView colorspace property which might kick off a colorspace conversion in the window system: https://developer.apple.com/documentation/metalkit/mtkview/colorspace?language=objc ...but I'm not setting that anywhere in sokol_app.h (but MTKView's default of There's also this discussion thread: https://forums.developer.apple.com/forums/thread/745810 TL;DR: as far as I'm aware, there shouldn't be any difference between sokol_app.h's use of MTKView versus your code's CAMetalLayer, but apparently there is... |
PS: also see this open issue: #713 and this: #758 (but I'm not sure if the issue you're seeing is about linear RGB vs sRGB surfaces, or about the general colorspace conversion stuff in the macOS composer) E.g. Filament explicitly sets a color space on their macOS window: ...but GLFW doesn't seem to do anything like that (and sokol_app.h also doesn't). |
Long story short: sokol_app.h needs more explicit control over RGB vs sRGB and color profiles (but at least the latter is probably not portable between platforms). |
Thank you for all the pointers, I'll see if I can find something. Interestingly, // Added to the above GLFW + Metal code.
swapchain.pixelFormat = MTLPixelFormatBGRA8Unorm; I get the same washed-out colors (!). But when I query it before setting, it already has that value, so I'm puzzled as to what is going on. |
Ok, that's really weird :D Apple docs being out of date wouldn't be surprising, but the property returning ObjC properties are setter/getter methods under the hood, maybe there's another object below CAMetalLayer which now has a different default, but CAMetalLayer maintains its own 'cached' pixel format value which is then out-of-sync until explicitly set. Just speculation though. |
I did try adding implementation of So I made the following addition to - (CALayer*)makeBackingLayer {
CAMetalLayer* layer = [[CAMetalLayer alloc] init];
NSLog(@"makeBackingLayer created layer: %p", layer);
return layer;
}
- (instancetype)initWithFrame:(CGRect)frame device:(id<MTLDevice>)device {
self = [super initWithFrame:frame device:device];
if (self) {
NSLog(@"after init, layer is: %p", self.layer);
}
return self;
}
- (void)setLayer:(CALayer *)layer {
NSLog(@"setLayer called with: %p", layer);
[super setLayer:layer];
} And indeed, it seems like
I'll have to take a look at the call stack of |
OK, so I did "solve" it by essentially patching the view in sapp's Note that I'm patching neither the depth-stencil (nor the msaa color texture), so that might be eventually needed as well, but I currently don't need depth buffer in my toy project, so it works as is. Leaving my "solution" here in case anyone else faces the same issue. I'm afraid it would require more poking, to understand what's really going on and make a proper workaround. static CAMetalLayer* g_layer = nil;
void patch_sokol_app_macos() {
#if defined(SOKOL_METAL) && defined(_SAPP_MACOS)
assert(g_layer == nil);
g_layer = [CAMetalLayer layer];
g_layer.device = _sapp.macos.mtl_device;
g_layer.opaque = YES;
_sapp.macos.view.layer = g_layer;
_sapp.macos.view.wantsLayer = YES;
#endif
}
sg_swapchain patched_sglue_swapchain() {
#if !(defined(SOKOL_METAL) && defined(_SAPP_MACOS))
return sglue_swapchain();
#else
g_layer.drawableSize = CGSizeMake(sapp_width(), sapp_height());
id<CAMetalDrawable> drawable = [g_layer nextDrawable];
sg_swapchain swapchain = {};
swapchain.width = sapp_width();
swapchain.height = sapp_height();
swapchain.sample_count = sapp_sample_count();
swapchain.color_format = (sg_pixel_format)sapp_color_format();
swapchain.depth_format = (sg_pixel_format)sapp_depth_format();
swapchain.metal.current_drawable = (__bridge const void*)drawable;
swapchain.metal.depth_stencil_texture = sapp_metal_get_depth_stencil_texture(); // Might need to be patched, too.
swapchain.metal.msaa_color_texture = sapp_metal_get_msaa_color_texture(); // Might need to be patched, too.
swapchain.d3d11.render_view = sapp_d3d11_get_render_view();
swapchain.d3d11.resolve_view = sapp_d3d11_get_resolve_view();
swapchain.d3d11.depth_stencil_view = sapp_d3d11_get_depth_stencil_view();
swapchain.wgpu.render_view = sapp_wgpu_get_render_view();
swapchain.wgpu.resolve_view = sapp_wgpu_get_resolve_view();
swapchain.wgpu.depth_stencil_view = sapp_wgpu_get_depth_stencil_view();
swapchain.gl.framebuffer = sapp_gl_get_framebuffer();
return swapchain;
#endif
} |
I spoke too soon 😂. Acquiring the depth-stencil texture in |
Thanks for the investigation! It's on my list to kick out MTKView and go one level lower to CAMetalLayer and CVDisplayLink (or whatever that is called nowadays), I guess it makes sense to wait with the proper fix until that is done (but tbh I don't know yet when I'll do that, I want to tackle compute shader support in sokol-gfx first to get that out of the way). |
That's understandable. I have this workaround for now. Compute shaders sound awesome. I can't imagine managing a project like sokol 🙂! Not sure if you want to close the issue or keep it alive, but either is fine by me. |
I'll keep the issue open until I get around to working on a fix. |
Hi, first thank you for all the outstanding work!
I've noticed that on my recent-ish Mac, the colors are somewhat washed out, compared to GLFW.
I hope the issue is going to be visible in the side-by-side screenshot (I'll take a photo of the monitor if not):
![image](https://private-user-images.githubusercontent.com/602372/402174719-019d102f-158d-4c3f-b306-af932ec3d307.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MzkxNTAxMDksIm5iZiI6MTczOTE0OTgwOSwicGF0aCI6Ii82MDIzNzIvNDAyMTc0NzE5LTAxOWQxMDJmLTE1OGQtNGMzZi1iMzA2LWFmOTMyZWMzZDMwNy5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjUwMjEwJTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI1MDIxMFQwMTEwMDlaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT1lYjE4MmQzZGMyM2RjMjU2ZjU4MmI2MzNmMTcwOGIzMzc5NWFjY2EyZWI5ZGQ3YjhkOWY1MmJmYWZkNDg0ODRhJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCJ9.pBF8VpNakbrEAiYemEIQ7Uwt41USIwRgX_xQzAagYAw)
The repro is below, it's just setting up the window with Sokol / GLFW and clearing screen.
Sokol
GLFW + Metal (but works the same with OpenGL), code from here.
For what it's worth, the Display settings on my Mac is like so:
![Screenshot 2025-01-10 at 23 29 50](https://private-user-images.githubusercontent.com/602372/402176037-428d53ba-3f98-4cba-879b-56d7f2a461f0.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MzkxNTAxMDksIm5iZiI6MTczOTE0OTgwOSwicGF0aCI6Ii82MDIzNzIvNDAyMTc2MDM3LTQyOGQ1M2JhLTNmOTgtNGNiYS04NzliLTU2ZDdmMmE0NjFmMC5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjUwMjEwJTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI1MDIxMFQwMTEwMDlaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT00NzdlNDMzZTVjNWI5NWE4MjQyYmQxYTUyMGExZmE1YjllNjhhOGZjYTFiZWZmOTk3ZTQzOWNkNTIxYTUyNzI1JlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCJ9.Md7CcwNiDwnuMUEo1f5XUuqIKwlj_e3CriQF-qR36W4)
When I select Internet & Web (sRGB) profile, the GLFW example also gets washed out, so it looks like GLFW is somehow respecting the current profile. I quickly skimmed through the code but didn't see anything special in the way the window was set up in GLFW.
Thank you!
The text was updated successfully, but these errors were encountered: