renderer/vulkan: real bg_color UBO renders configured theme color
Drop the diagnostic purple shader; the bg_color pipeline now reads the configured background color out of the Globals UBO and the window paints the actual theme color (e.g. #192742 for the user that triggered this work). Two pieces had to land together: 1. Real shaders + UBO descriptor wiring. The bg_color fragment source goes back to the include-expanded `bg_color.f.glsl`, and the full-screen vertex source goes back to `full_screen.v.glsl` (`vulkanizeGlsl` rewrites `gl_VertexID` → `gl_VertexIndex` at compile time so it works under glslang's Vulkan client). The pipeline is built with the descriptor pool + bg_color descriptor set layout again, so `RenderPass.step` can update the UBO binding each frame with `frame.uniforms.buffer`. 2. sRGB render target + premultiplied QImage. The shader emits linear premultiplied alpha (`load_color` linearizes then premultiplies). Without sRGB encoding on the framebuffer write, the bytes in memory are linear premultiplied and any consumer that assumes sRGB premultiplied (e.g. Qt's `Format_ARGB32_Premultiplied`) renders the colors far too dark. Render targets and the custom-shader back_texture now use `VK_FORMAT_B8G8R8A8_SRGB`; the bg_color pipeline's `color_format` follows. On the Qt side the QImage import switches from `Format_ARGB32` to `Format_ARGB32_Premultiplied` so Qt interprets the bytes correctly. The DRM fourcc the host sees is still `AR24` — sRGB encoding is a Vulkan-side framebuffer-write concern; the dmabuf byte layout is identical. Co-Authored-By: claude-flow <ruv@ruv.net>pull/12846/head
parent
98dcdf5307
commit
5f54571aff
|
|
@ -1333,21 +1333,25 @@ void GhosttySurface::presentVulkanDmabuf(
|
|||
return;
|
||||
}
|
||||
// QImage holds the pixel data by copying when constructed with
|
||||
// `Format_ARGB32` from a buffer with explicit stride. We then
|
||||
// detach (copy()) so the QImage survives the unmap.
|
||||
// `Format_ARGB32_Premultiplied` from a buffer with explicit stride.
|
||||
// We then detach (copy()) so the QImage survives the unmap.
|
||||
//
|
||||
// drm_format ARGB8888 (0x34325241 = "AR24") matches QImage's
|
||||
// Format_ARGB32 byte order on little-endian (B,G,R,A in memory).
|
||||
// We unconditionally use ARGB32 here because the renderer currently
|
||||
// emits BGRA only — extend with a format switch when other formats
|
||||
// come online.
|
||||
// ARGB32 byte order on little-endian (B,G,R,A in memory).
|
||||
//
|
||||
// We use the *premultiplied* variant because the renderer's
|
||||
// fragment shaders output premultiplied alpha and the render
|
||||
// target is `VK_FORMAT_B8G8R8A8_SRGB` (hardware gamma-encodes the
|
||||
// linear shader output at framebuffer-write time). The bytes
|
||||
// landing in this buffer are therefore sRGB-encoded premultiplied
|
||||
// ARGB — exactly what Format_ARGB32_Premultiplied expects.
|
||||
(void)drm_format;
|
||||
const QImage stamped(
|
||||
static_cast<const uchar *>(mapped),
|
||||
static_cast<int>(width),
|
||||
static_cast<int>(height),
|
||||
static_cast<int>(stride),
|
||||
QImage::Format_ARGB32);
|
||||
QImage::Format_ARGB32_Premultiplied);
|
||||
QImage owned = stamped.copy();
|
||||
::munmap(mapped, bytes);
|
||||
|
||||
|
|
|
|||
|
|
@ -255,9 +255,17 @@ pub fn initShaders(
|
|||
|
||||
pub fn initTarget(self: *const Vulkan, width: usize, height: usize) !Target {
|
||||
_ = self;
|
||||
// SRGB format so the hardware gamma-encodes the linear premultiplied
|
||||
// shader output at framebuffer-write time. The renderer's shaders
|
||||
// produce linear premultiplied alpha; without an sRGB format the
|
||||
// bytes in memory would be linear and Qt (which expects sRGB
|
||||
// premultiplied) would render them as if they were already gamma
|
||||
// encoded — colors would look way too dark. The DRM fourcc the
|
||||
// host sees is still ARGB8888; SRGB encoding is a Vulkan-side
|
||||
// concern only.
|
||||
return try Target.init(.{
|
||||
.device = devicePtr(),
|
||||
.format = vk.VK_FORMAT_B8G8R8A8_UNORM,
|
||||
.format = vk.VK_FORMAT_B8G8R8A8_SRGB,
|
||||
.width = @intCast(width),
|
||||
.height = @intCast(height),
|
||||
});
|
||||
|
|
@ -400,11 +408,11 @@ pub fn textureOptions(_: *const Vulkan) Texture.Options {
|
|||
// back_texture (which is BOTH sampled AND a render target).
|
||||
// We hand back the wider usage set so both work. The format
|
||||
// matches the renderer's `initTarget` choice
|
||||
// (`B8G8R8A8_UNORM`) so a render → sample → render chain
|
||||
// (`B8G8R8A8_SRGB`) so a render → sample → render chain
|
||||
// through the custom-shader pass keeps the same color format.
|
||||
return .{
|
||||
.device = devicePtr(),
|
||||
.format = vk.VK_FORMAT_B8G8R8A8_UNORM,
|
||||
.format = vk.VK_FORMAT_B8G8R8A8_SRGB,
|
||||
.usage = vk.VK_IMAGE_USAGE_SAMPLED_BIT |
|
||||
vk.VK_IMAGE_USAGE_TRANSFER_DST_BIT |
|
||||
vk.VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
|
||||
|
|
|
|||
|
|
@ -46,35 +46,13 @@ pub const source = struct {
|
|||
// include contents inline — same approach `opengl/shaders.zig`
|
||||
// uses via its `loadShaderCode`.
|
||||
|
||||
// DIAGNOSTIC: override bg_color.f.glsl with a hardcoded purple
|
||||
// color so we can verify the pipeline + descriptor binding +
|
||||
// draw recording work end-to-end without depending on the
|
||||
// Uniforms.bg_color data path being correct. Once a colored
|
||||
// window confirms the pipeline runs, revert to the real
|
||||
// include-expanded source.
|
||||
pub const bg_color_frag: [:0]const u8 =
|
||||
\\#version 450
|
||||
\\layout(location = 0) out vec4 out_FragColor;
|
||||
\\void main() {
|
||||
\\ out_FragColor = vec4(0.5, 0.0, 0.5, 1.0); // debug: opaque purple
|
||||
\\}
|
||||
;
|
||||
pub const bg_color_frag_real = processIncludes(@embedFile("../shaders/glsl/bg_color.f.glsl"));
|
||||
pub const bg_color_frag = processIncludes(@embedFile("../shaders/glsl/bg_color.f.glsl"));
|
||||
pub const bg_image_frag = processIncludes(@embedFile("../shaders/glsl/bg_image.f.glsl"));
|
||||
pub const bg_image_vert = processIncludes(@embedFile("../shaders/glsl/bg_image.v.glsl"));
|
||||
pub const cell_bg_frag = processIncludes(@embedFile("../shaders/glsl/cell_bg.f.glsl"));
|
||||
pub const cell_text_frag = processIncludes(@embedFile("../shaders/glsl/cell_text.f.glsl"));
|
||||
pub const cell_text_vert = processIncludes(@embedFile("../shaders/glsl/cell_text.v.glsl"));
|
||||
// DIAGNOSTIC: inline a known-good fullscreen-triangle vertex
|
||||
// shader to rule out any vulkanizeGlsl rewrite issues.
|
||||
pub const full_screen_vert: [:0]const u8 =
|
||||
\\#version 450
|
||||
\\void main() {
|
||||
\\ vec2 pos[3] = vec2[3](vec2(-1.0, -1.0), vec2(3.0, -1.0), vec2(-1.0, 3.0));
|
||||
\\ gl_Position = vec4(pos[gl_VertexIndex], 0.0, 1.0);
|
||||
\\}
|
||||
;
|
||||
pub const full_screen_vert_real = processIncludes(@embedFile("../shaders/glsl/full_screen.v.glsl"));
|
||||
pub const full_screen_vert = processIncludes(@embedFile("../shaders/glsl/full_screen.v.glsl"));
|
||||
pub const image_frag = processIncludes(@embedFile("../shaders/glsl/image.f.glsl"));
|
||||
pub const image_vert = processIncludes(@embedFile("../shaders/glsl/image.v.glsl"));
|
||||
};
|
||||
|
|
@ -565,17 +543,15 @@ pub const Shaders = struct {
|
|||
}
|
||||
errdefer device.dispatch.destroyDescriptorSetLayout(device.device, bg_color_dsl, null);
|
||||
|
||||
// DIAGNOSTIC: the debug bg_color shader has no inputs, so
|
||||
// build the pipeline WITHOUT a descriptor set layout. The
|
||||
// `bg_color_dsl` is still kept around — it gets stored in
|
||||
// `Shaders.bg_color_set_layout` and torn down on deinit.
|
||||
const bg_color_dsls = [_]vk.VkDescriptorSetLayout{bg_color_dsl};
|
||||
const bg_color_pipeline = try Pipeline.init(.{
|
||||
.device = device,
|
||||
.descriptor_pool = &pool,
|
||||
.vertex_module = modules.full_screen_vert.handle,
|
||||
.fragment_module = modules.bg_color_frag.handle,
|
||||
.vertex_input = null,
|
||||
.descriptor_set_layouts = &.{},
|
||||
.color_format = vk.VK_FORMAT_B8G8R8A8_UNORM,
|
||||
.descriptor_set_layouts = &bg_color_dsls,
|
||||
.color_format = vk.VK_FORMAT_B8G8R8A8_SRGB,
|
||||
.blending_enabled = false,
|
||||
.topology = vk.VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in New Issue