get the blending state a bit closer to vulkan

Kate created

still looks bad :(

Change summary

crates/gpui/src/platform/windows/directx_atlas.rs    |  4 +-
crates/gpui/src/platform/windows/directx_renderer.rs | 13 ++++++-
crates/gpui/src/platform/windows/shaders.hlsl        | 22 ++++++++++---
3 files changed, 29 insertions(+), 10 deletions(-)

Detailed changes

crates/gpui/src/platform/windows/directx_atlas.rs 🔗

@@ -7,7 +7,7 @@ use windows::Win32::Graphics::{
         D3D11_USAGE_DEFAULT, ID3D11Device, ID3D11DeviceContext, ID3D11ShaderResourceView,
         ID3D11Texture2D,
     },
-    Dxgi::Common::{DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_SAMPLE_DESC},
+    Dxgi::Common::*,
 };
 
 use crate::{
@@ -167,7 +167,7 @@ impl DirectXAtlasState {
         let bytes_per_pixel;
         match kind {
             AtlasTextureKind::Monochrome => {
-                pixel_format = DXGI_FORMAT_A8_UNORM;
+                pixel_format = DXGI_FORMAT_R8_UNORM;
                 bind_flag = D3D11_BIND_SHADER_RESOURCE;
                 bytes_per_pixel = 1;
             }

crates/gpui/src/platform/windows/directx_renderer.rs 🔗

@@ -149,6 +149,11 @@ impl DirectXRenderer {
     }
 
     fn pre_draw(&self) -> Result<()> {
+        #[cfg(not(feature = "enable-renderdoc"))]
+        let premultiplied_alpha = 1;
+        #[cfg(feature = "enable-renderdoc")]
+        let premultiplied_alpha = 0;
+
         update_buffer(
             &self.devices.device_context,
             self.globals.global_params_buffer[0].as_ref().unwrap(),
@@ -157,6 +162,7 @@ impl DirectXRenderer {
                     self.resources.viewport[0].Width,
                     self.resources.viewport[0].Height,
                 ],
+                premultiplied_alpha,
                 ..Default::default()
             }],
         )?;
@@ -667,7 +673,8 @@ impl DirectXGlobalElements {
 #[repr(C)]
 struct GlobalParams {
     viewport_size: [f32; 2],
-    _pad: u64,
+    premultiplied_alpha: u32,
+    _pad: u32,
 }
 
 struct PipelineState<T> {
@@ -1093,7 +1100,7 @@ fn create_swap_chain(
         // Composition SwapChains only support the DXGI_SCALING_STRETCH Scaling.
         Scaling: DXGI_SCALING_STRETCH,
         SwapEffect: DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL,
-        AlphaMode: DXGI_ALPHA_MODE_PREMULTIPLIED,
+        AlphaMode: DXGI_ALPHA_MODE_IGNORE,
         Flags: 0,
     };
     Ok(unsafe { dxgi_factory.CreateSwapChainForComposition(device, &desc, None)? })
@@ -1262,7 +1269,7 @@ fn create_blend_state(device: &ID3D11Device) -> Result<ID3D11BlendState> {
     desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
     desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
     desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
-    desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ONE;
+    desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
     desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL.0 as u8;
     unsafe {
         let mut state = None;

crates/gpui/src/platform/windows/shaders.hlsl 🔗

@@ -1,6 +1,7 @@
 cbuffer GlobalParams: register(b0) {
     float2 global_viewport_size;
-    uint2 _global_pad;
+    uint premultiplied_alpha;
+    uint _pad;
 };
 
 Texture2D<float4> t_sprite: register(t0);
@@ -256,7 +257,7 @@ float pick_corner_radius(float2 center_to_point, Corners corner_radii) {
     }
 }
 
-float4 to_device_position_transformed(float2 unit_vertex, Bounds bounds, 
+float4 to_device_position_transformed(float2 unit_vertex, Bounds bounds,
                                       TransformationMatrix transformation) {
     float2 position = unit_vertex * bounds.size + bounds.origin;
     float2 transformed = mul(position, transformation.rotation_scale) + transformation.translation;
@@ -970,7 +971,7 @@ UnderlineVertexOutput underline_vertex(uint vertex_id: SV_VertexID, uint underli
     float2 unit_vertex = float2(float(vertex_id & 1u), 0.5 * float(vertex_id & 2u));
     Underline underline = underlines[underline_id];
     float4 device_position = to_device_position(unit_vertex, underline.bounds);
-    float4 clip_distance = distance_from_clip_rect(unit_vertex, underline.bounds, 
+    float4 clip_distance = distance_from_clip_rect(unit_vertex, underline.bounds,
                                                     underline.content_mask);
     float4 color = hsla_to_rgba(underline.color);
 
@@ -1031,6 +1032,7 @@ struct MonochromeSpriteFragmentInput {
     float4 position: SV_Position;
     float2 tile_position: POSITION;
     nointerpolation float4 color: COLOR;
+    float4 clip_distance: SV_ClipDistance;
 };
 
 StructuredBuffer<MonochromeSprite> mono_sprites: register(t1);
@@ -1052,11 +1054,21 @@ MonochromeSpriteVertexOutput monochrome_sprite_vertex(uint vertex_id: SV_VertexI
     return output;
 }
 
+float4 blend_color(float4 color, float alpha_factor) {
+    float alpha = color.a * alpha_factor;
+    float multiplier = premultiplied_alpha != 0 ? alpha : 1.0;
+    return float4(color.rgb * multiplier, alpha);
+}
+
 float4 monochrome_sprite_fragment(MonochromeSpriteFragmentInput input): SV_Target {
-    float4 sample = t_sprite.Sample(s_sprite, input.tile_position);
+    float sample = t_sprite.Sample(s_sprite, input.tile_position).r;
     float4 color = input.color;
-    color.a *= sample.a;
+    color.a *= sample;
     return color;
+    // if (any(input.clip_distance < 0.0)) {
+    //     return float4(0.0, 0.0, 0.0, 0.0);
+    // }
+    // return blend_color(input.color, sample);
 }
 
 /*