From 62d1b7e36f2af320f1de4061123ab6360bcb7821 Mon Sep 17 00:00:00 2001 From: Junkui Zhang <364772080@qq.com> Date: Tue, 29 Jul 2025 14:05:38 +0800 Subject: [PATCH] fix `PathRasterization` pipeline --- .../src/platform/windows/directx_renderer.rs | 363 ++++++++---------- crates/gpui/src/platform/windows/shaders.hlsl | 96 ++--- 2 files changed, 201 insertions(+), 258 deletions(-) diff --git a/crates/gpui/src/platform/windows/directx_renderer.rs b/crates/gpui/src/platform/windows/directx_renderer.rs index e731a74553a7bd4125a15c88aa960c52ac044380..80195bf93e18cce59a2d923488bdd4cc61aa7308 100644 --- a/crates/gpui/src/platform/windows/directx_renderer.rs +++ b/crates/gpui/src/platform/windows/directx_renderer.rs @@ -68,7 +68,8 @@ struct DirectXResources { struct DirectXRenderPipelines { shadow_pipeline: PipelineState, quad_pipeline: PipelineState, - path_rasterization_pipeline: PathRasterizationPipelineState, + // path_rasterization_pipeline: PathRasterizationPipelineState, + path_rasterization_pipeline: PipelineState, path_sprite_pipeline: PipelineState, underline_pipeline: PipelineState, mono_sprites: PipelineState, @@ -341,6 +342,8 @@ impl DirectXRenderer { &self.devices.device_context, &self.resources.viewport, &self.globals.global_params_buffer, + D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, + 4, shadows.len() as u32, ) } @@ -358,6 +361,8 @@ impl DirectXRenderer { &self.devices.device_context, &self.resources.viewport, &self.globals.global_params_buffer, + D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, + 4, quads.len() as u32, ) } @@ -383,35 +388,29 @@ impl DirectXRenderer { // Collect all vertices and sprites for a single draw call let mut vertices = Vec::new(); - let mut sprites = Vec::new(); - for (path_index, path) in paths.iter().enumerate() { - vertices.extend(path.vertices.iter().map(|v| DirectXPathVertex { + for path in paths { + vertices.extend(path.vertices.iter().map(|v| PathRasterizationSprite { xy_position: v.xy_position, st_position: v.st_position, - path_index: path_index as u32, - })); - - sprites.push(PathRasterizationSprite { - bounds: path.bounds.intersect(&path.content_mask.bounds), color: path.color, - }); + bounds: path.bounds.intersect(&path.content_mask.bounds), + })); } - if !vertices.is_empty() { - self.pipelines.path_rasterization_pipeline.update_buffer( - &self.devices.device, - &self.devices.device_context, - &sprites, - &vertices, - )?; - self.pipelines.path_rasterization_pipeline.draw( - &self.devices.device_context, - vertices.len() as u32, - &self.resources.viewport, - &self.globals.global_params_buffer, - )?; - } + self.pipelines.path_rasterization_pipeline.update_buffer( + &self.devices.device, + &self.devices.device_context, + &vertices, + )?; + self.pipelines.path_rasterization_pipeline.draw( + &self.devices.device_context, + &self.resources.viewport, + &self.globals.global_params_buffer, + D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST, + vertices.len() as u32, + 1, + )?; // Resolve MSAA to non-MSAA intermediate texture unsafe { @@ -490,6 +489,8 @@ impl DirectXRenderer { &self.devices.device_context, &self.resources.viewport, &self.globals.global_params_buffer, + D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, + 4, underlines.len() as u32, ) } @@ -655,7 +656,12 @@ impl DirectXRenderPipelines { let shadow_pipeline = PipelineState::new(device, "shadow_pipeline", ShaderModule::Shadow, 4)?; let quad_pipeline = PipelineState::new(device, "quad_pipeline", ShaderModule::Quad, 64)?; - let path_rasterization_pipeline = PathRasterizationPipelineState::new(device)?; + let path_rasterization_pipeline = PipelineState::new( + device, + "path_rasterization_pipeline", + ShaderModule::PathRasterization, + 32, + )?; let path_sprite_pipeline = PipelineState::new(device, "path_sprite_pipeline", ShaderModule::PathSprite, 1)?; let underline_pipeline = @@ -769,16 +775,16 @@ struct PipelineState { _marker: std::marker::PhantomData, } -struct PathRasterizationPipelineState { - vertex: ID3D11VertexShader, - fragment: ID3D11PixelShader, - buffer: ID3D11Buffer, - buffer_size: usize, - view: [Option; 1], - vertex_buffer: Option, - vertex_buffer_size: usize, - input_layout: ID3D11InputLayout, -} +// struct PathRasterizationPipelineState { +// vertex: ID3D11VertexShader, +// fragment: ID3D11PixelShader, +// buffer: ID3D11Buffer, +// buffer_size: usize, +// view: [Option; 1], +// vertex_buffer: Option, +// vertex_buffer_size: usize, +// input_layout: ID3D11InputLayout, +// } impl PipelineState { fn new( @@ -837,19 +843,21 @@ impl PipelineState { device_context: &ID3D11DeviceContext, viewport: &[D3D11_VIEWPORT], global_params: &[Option], + topology: D3D_PRIMITIVE_TOPOLOGY, + vertex_count: u32, instance_count: u32, ) -> Result<()> { set_pipeline_state( device_context, &self.view, - D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, + topology, viewport, &self.vertex, &self.fragment, global_params, ); unsafe { - device_context.DrawInstanced(4, instance_count, 0, 0); + device_context.DrawInstanced(vertex_count, instance_count, 0, 0); } Ok(()) } @@ -883,175 +891,130 @@ impl PipelineState { } } -impl PathRasterizationPipelineState { - fn new(device: &ID3D11Device) -> Result { - let (vertex, vertex_shader) = { - let raw_vertex_shader = - RawShaderBytes::new(ShaderModule::PathRasterization, ShaderTarget::Vertex)?; - ( - create_vertex_shader(device, raw_vertex_shader.as_bytes())?, - raw_vertex_shader, - ) - }; - let fragment = { - let raw_shader = - RawShaderBytes::new(ShaderModule::PathRasterization, ShaderTarget::Fragment)?; - create_fragment_shader(device, raw_shader.as_bytes())? - }; - let buffer = create_buffer(device, std::mem::size_of::(), 32)?; - let view = create_buffer_view(device, &buffer)?; - let vertex_buffer = Some(create_buffer( - device, - std::mem::size_of::(), - 32, - )?); - - let input_layout = unsafe { - let mut layout = None; - device.CreateInputLayout( - &[ - D3D11_INPUT_ELEMENT_DESC { - SemanticName: windows::core::s!("POSITION"), - SemanticIndex: 0, - Format: DXGI_FORMAT_R32G32_FLOAT, - InputSlot: 0, - AlignedByteOffset: 0, - InputSlotClass: D3D11_INPUT_PER_VERTEX_DATA, - InstanceDataStepRate: 0, - }, - D3D11_INPUT_ELEMENT_DESC { - SemanticName: windows::core::s!("TEXCOORD"), - SemanticIndex: 0, - Format: DXGI_FORMAT_R32G32_FLOAT, - InputSlot: 0, - AlignedByteOffset: 8, - InputSlotClass: D3D11_INPUT_PER_VERTEX_DATA, - InstanceDataStepRate: 0, - }, - D3D11_INPUT_ELEMENT_DESC { - SemanticName: windows::core::s!("TEXCOORD"), - SemanticIndex: 1, - Format: DXGI_FORMAT_R32_UINT, - InputSlot: 0, - AlignedByteOffset: 16, - InputSlotClass: D3D11_INPUT_PER_VERTEX_DATA, - InstanceDataStepRate: 0, - }, - ], - vertex_shader.as_bytes(), - Some(&mut layout), - )?; - layout.unwrap() - }; - - Ok(Self { - vertex, - fragment, - buffer, - buffer_size: 32, - view, - vertex_buffer, - vertex_buffer_size: 32, - input_layout, - }) - } - - fn update_buffer( - &mut self, - device: &ID3D11Device, - device_context: &ID3D11DeviceContext, - sprites: &[PathRasterizationSprite], - vertices_data: &[DirectXPathVertex], - ) -> Result<()> { - if self.buffer_size < sprites.len() { - let new_buffer_size = sprites.len().next_power_of_two(); - log::info!( - "Updating Paths Pipeline buffer size from {} to {}", - self.buffer_size, - new_buffer_size - ); - let buffer = create_buffer( - device, - std::mem::size_of::(), - new_buffer_size, - )?; - let view = create_buffer_view(device, &buffer)?; - self.buffer = buffer; - self.view = view; - self.buffer_size = new_buffer_size; - } - update_buffer(device_context, &self.buffer, sprites)?; - - if self.vertex_buffer_size < vertices_data.len() { - let new_vertex_buffer_size = vertices_data.len().next_power_of_two(); - log::info!( - "Updating Paths Pipeline vertex buffer size from {} to {}", - self.vertex_buffer_size, - new_vertex_buffer_size - ); - let vertex_buffer = create_buffer( - device, - std::mem::size_of::(), - new_vertex_buffer_size, - )?; - self.vertex_buffer = Some(vertex_buffer); - self.vertex_buffer_size = new_vertex_buffer_size; - } - update_buffer( - device_context, - self.vertex_buffer.as_ref().unwrap(), - vertices_data, - )?; - - Ok(()) - } - - fn draw( - &self, - device_context: &ID3D11DeviceContext, - vertex_count: u32, - viewport: &[D3D11_VIEWPORT], - global_params: &[Option], - ) -> Result<()> { - set_pipeline_state( - device_context, - &self.view, - D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST, - viewport, - &self.vertex, - &self.fragment, - global_params, - ); - unsafe { - const STRIDE: u32 = std::mem::size_of::() as u32; - const OFFSET: u32 = 0; - device_context.IASetInputLayout(&self.input_layout); - device_context.IASetVertexBuffers( - 0, - 1, - Some(&self.vertex_buffer), - Some(&STRIDE), - Some(&OFFSET), - ); - device_context.Draw(vertex_count, 0); - } - Ok(()) - } -} +// impl PathRasterizationPipelineState { +// fn new(device: &ID3D11Device) -> Result { +// let (vertex, vertex_shader) = { +// let raw_vertex_shader = +// RawShaderBytes::new(ShaderModule::PathRasterization, ShaderTarget::Vertex)?; +// ( +// create_vertex_shader(device, raw_vertex_shader.as_bytes())?, +// raw_vertex_shader, +// ) +// }; +// let fragment = { +// let raw_shader = +// RawShaderBytes::new(ShaderModule::PathRasterization, ShaderTarget::Fragment)?; +// create_fragment_shader(device, raw_shader.as_bytes())? +// }; +// let buffer = create_buffer(device, std::mem::size_of::(), 32)?; +// let view = create_buffer_view(device, &buffer)?; +// let vertex_buffer = Some(create_buffer( +// device, +// std::mem::size_of::(), +// 32, +// )?); + +// Ok(Self { +// vertex, +// fragment, +// buffer, +// buffer_size: 32, +// view, +// vertex_buffer, +// vertex_buffer_size: 32, +// }) +// } + +// fn update_buffer( +// &mut self, +// device: &ID3D11Device, +// device_context: &ID3D11DeviceContext, +// sprites: &[PathRasterizationSprite], +// vertices_data: &[DirectXPathVertex], +// ) -> Result<()> { +// if self.buffer_size < sprites.len() { +// let new_buffer_size = sprites.len().next_power_of_two(); +// log::info!( +// "Updating Paths Pipeline buffer size from {} to {}", +// self.buffer_size, +// new_buffer_size +// ); +// let buffer = create_buffer( +// device, +// std::mem::size_of::(), +// new_buffer_size, +// )?; +// let view = create_buffer_view(device, &buffer)?; +// self.buffer = buffer; +// self.view = view; +// self.buffer_size = new_buffer_size; +// } +// update_buffer(device_context, &self.buffer, sprites)?; + +// if self.vertex_buffer_size < vertices_data.len() { +// let new_vertex_buffer_size = vertices_data.len().next_power_of_two(); +// log::info!( +// "Updating Paths Pipeline vertex buffer size from {} to {}", +// self.vertex_buffer_size, +// new_vertex_buffer_size +// ); +// let vertex_buffer = create_buffer( +// device, +// std::mem::size_of::(), +// new_vertex_buffer_size, +// )?; +// self.vertex_buffer = Some(vertex_buffer); +// self.vertex_buffer_size = new_vertex_buffer_size; +// } +// update_buffer( +// device_context, +// self.vertex_buffer.as_ref().unwrap(), +// vertices_data, +// )?; + +// Ok(()) +// } + +// fn draw( +// &self, +// device_context: &ID3D11DeviceContext, +// vertex_count: u32, +// viewport: &[D3D11_VIEWPORT], +// global_params: &[Option], +// ) -> Result<()> { +// set_pipeline_state( +// device_context, +// &self.view, +// D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST, +// viewport, +// &self.vertex, +// &self.fragment, +// global_params, +// ); +// unsafe { +// const STRIDE: u32 = std::mem::size_of::() as u32; +// const OFFSET: u32 = 0; +// device_context.IASetInputLayout(&self.input_layout); +// device_context.IASetVertexBuffers( +// 0, +// 1, +// Some(&self.vertex_buffer), +// Some(&STRIDE), +// Some(&OFFSET), +// ); +// device_context.Draw(vertex_count, 0); +// } +// Ok(()) +// } +// } #[derive(Clone, Copy)] #[repr(C)] -struct DirectXPathVertex { +struct PathRasterizationSprite { xy_position: Point, st_position: Point, - path_index: u32, -} - -#[derive(Clone, Copy)] -#[repr(C)] -struct PathRasterizationSprite { - bounds: Bounds, color: Background, + bounds: Bounds, } #[derive(Clone, Copy)] diff --git a/crates/gpui/src/platform/windows/shaders.hlsl b/crates/gpui/src/platform/windows/shaders.hlsl index 5e42201f1c63eba9af9d1f9ac95ee7751fe9fa4e..954040c4c3950fdb62d4ba8c17cfdd566e224706 100644 --- a/crates/gpui/src/platform/windows/shaders.hlsl +++ b/crates/gpui/src/platform/windows/shaders.hlsl @@ -876,18 +876,10 @@ float4 shadow_fragment(ShadowFragmentInput input): SV_TARGET { ** */ -struct PathVertex { - float2 xy_position: POSITION; - float2 st_position: TEXCOORD0; - uint path_index: TEXCOORD1; -}; - struct PathRasterizationSprite { - Bounds bounds; + float2 xy_position; + float2 st_position; Background color; -}; - -struct PathSprite { Bounds bounds; }; @@ -896,68 +888,52 @@ StructuredBuffer path_rasterization_sprites: register(t struct PathVertexOutput { float4 position: SV_Position; float2 st_position: TEXCOORD0; - nointerpolation uint tag: TEXCOORD1; - nointerpolation uint color_space: TEXCOORD2; - nointerpolation float gradient_angle: TEXCOORD3; - nointerpolation float4 solid_color: COLOR0; - nointerpolation float4 color0: COLOR1; - nointerpolation float4 color1: COLOR2; - nointerpolation float2 stop_percentages: COLOR3; - nointerpolation Bounds bounds: BOUNDS; + nointerpolation uint vertex_id: TEXCOORD1; + float4 clip_distance: SV_ClipDistance; }; struct PathFragmentInput { float4 position: SV_Position; float2 st_position: TEXCOORD0; - nointerpolation uint tag: TEXCOORD1; - nointerpolation uint color_space: TEXCOORD2; - nointerpolation float gradient_angle: TEXCOORD3; - nointerpolation float4 solid_color: COLOR0; - nointerpolation float4 color0: COLOR1; - nointerpolation float4 color1: COLOR2; - nointerpolation float2 stop_percentages: COLOR3; - nointerpolation Bounds bounds: BOUNDS; + nointerpolation uint vertex_id: TEXCOORD1; }; -PathVertexOutput path_rasterization_vertex(PathVertex input) { - PathRasterizationSprite sprite = path_rasterization_sprites[input.path_index]; +PathVertexOutput path_rasterization_vertex(uint vertex_id: SV_VertexID) { + PathRasterizationSprite sprite = path_rasterization_sprites[vertex_id]; PathVertexOutput output; - output.position = to_device_position_impl(input.xy_position); - output.st_position = input.st_position; - output.bounds = sprite.bounds; - output.tag = sprite.color.tag; - output.color_space = sprite.color.color_space; - output.gradient_angle = sprite.color.gradient_angle_or_pattern_height; - output.stop_percentages = float2(sprite.color.colors[0].percentage, sprite.color.colors[1].percentage); - - GradientColor gradient = prepare_gradient_color( - sprite.color.tag, - sprite.color.color_space, - sprite.color.solid, - sprite.color.colors - ); - output.solid_color = gradient.solid; - output.color0 = gradient.color0; - output.color1 = gradient.color1; + output.position = to_device_position_impl(sprite.xy_position); + output.st_position = sprite.st_position; + output.vertex_id = vertex_id; + output.clip_distance = distance_from_clip_rect_impl(sprite.xy_position, sprite.bounds); return output; } float4 path_rasterization_fragment(PathFragmentInput input): SV_Target { - Background background; - background.tag = input.tag; - background.color_space = input.color_space; - background.solid = (Hsla)0; // Not used when tag != 0 - background.gradient_angle_or_pattern_height = input.gradient_angle; - background.colors[0].color = (Hsla)0; // Not used when colors are pre-computed - background.colors[0].percentage = input.stop_percentages.x; - background.colors[1].color = (Hsla)0; // Not used when colors are pre-computed - background.colors[1].percentage = input.stop_percentages.y; - - float4 color = gradient_color(background, input.position.xy, input.bounds, - input.solid_color, input.color0, input.color1); - return color; + float2 dx = ddx(input.st_position); + float2 dy = ddy(input.st_position); + PathRasterizationSprite sprite = path_rasterization_sprites[input.vertex_id]; + + Background background = sprite.color; + Bounds bounds = sprite.bounds; + + float alpha; + if (length(float2(dx.x, dy.x))) { + alpha = 1.0; + } else { + float2 gradient = 2.0 * input.st_position.xx * float2(dx.x, dy.x) - float2(dx.y, dy.y); + float f = input.st_position.x * input.st_position.x - input.st_position.y; + float distance = f / length(gradient); + alpha = saturate(0.5 - distance); + } + + GradientColor gradient = prepare_gradient_color( + background.tag, background.color_space, background.solid, background.colors); + + float4 color = gradient_color(background, input.position.xy, bounds, + gradient.solid, gradient.color0, gradient.color1); + return float4(color.rgb * color.a * alpha, alpha * color.a); } /* @@ -966,6 +942,10 @@ float4 path_rasterization_fragment(PathFragmentInput input): SV_Target { ** */ +struct PathSprite { + Bounds bounds; +}; + struct PathSpriteVertexOutput { float4 position: SV_Position; float2 texture_coords: TEXCOORD0;