This commit is contained in:
Junkui Zhang 2025-07-16 15:36:24 +08:00
parent 667c19907a
commit b012246d2b

View file

@ -285,59 +285,19 @@ impl DirectXRenderer {
});
}
update_paths_buffer_capacity(
&self.pipelines.paths_pipeline,
sprites.len(),
self.pipelines.paths_pipeline.update_buffer(
&self.devices.device,
)
.map(|input| update_paths_pipeline_buffer(&mut self.pipelines.paths_pipeline, input));
update_buffer(
&self.devices.device_context,
&self.pipelines.paths_pipeline.buffer,
&sprites,
)?;
update_paths_vertex_capacity(
&mut self.pipelines.paths_pipeline,
vertices.len(),
&self.devices.device,
)
.map(|input| update_paths_pipeline_vertex(&mut self.pipelines.paths_pipeline, input));
update_buffer(
&self.devices.device_context,
self.pipelines
.paths_pipeline
.vertex_buffer
.as_ref()
.unwrap(),
&vertices,
)?;
update_indirect_buffer_capacity(
&self.pipelines.paths_pipeline,
draw_indirect_commands.len(),
&self.devices.device,
)
.map(|input| update_paths_indirect_buffer(&mut self.pipelines.paths_pipeline, input));
update_buffer(
&self.devices.device_context,
&self.pipelines.paths_pipeline.indirect_draw_buffer,
&draw_indirect_commands,
)?;
prepare_indirect_draws(
self.pipelines.paths_pipeline.draw(
&self.devices.device_context,
&self.pipelines.paths_pipeline,
paths.len(),
&self.context.viewport,
&self.globals.global_params_buffer,
D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST,
)?;
for i in 0..paths.len() {
draw_indirect(
&self.devices.device_context,
&self.pipelines.paths_pipeline.indirect_draw_buffer,
(i * std::mem::size_of::<DrawInstancedIndirectArgs>()) as u32,
);
}
Ok(())
)
}
fn draw_underlines(&mut self, underlines: &[Underline]) -> Result<()> {
@ -634,18 +594,19 @@ impl<T> PipelineState<T> {
) -> Result<()> {
if self.buffer_size < data.len() {
let new_buffer_size = data.len().next_power_of_two();
log::info!(
"Updating {} buffer size from {} to {}",
self.label,
self.buffer_size,
new_buffer_size
);
let buffer = create_buffer(device, std::mem::size_of::<T>(), new_buffer_size)?;
let view = create_buffer_view(device, &buffer)?;
self.buffer = buffer;
self.view = view;
self.buffer_size = new_buffer_size;
}
unsafe {
let mut dest = std::mem::zeroed();
device_context.Map(&self.buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, Some(&mut dest))?;
std::ptr::copy_nonoverlapping(data.as_ptr(), dest.pData as _, data.len());
device_context.Unmap(&self.buffer, 0);
}
Ok(())
update_buffer(device_context, &self.buffer, data)
}
fn draw(
@ -784,6 +745,101 @@ impl PathsPipelineState {
view,
})
}
fn update_buffer(
&mut self,
device: &ID3D11Device,
device_context: &ID3D11DeviceContext,
buffer_data: &[PathSprite],
vertices_data: &[PathVertex<ScaledPixels>],
draw_commands: &[DrawInstancedIndirectArgs],
) -> Result<()> {
if self.buffer_size < buffer_data.len() {
let new_buffer_size = buffer_data.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::<PathSprite>(), 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, buffer_data)?;
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::<PathVertex<ScaledPixels>>(),
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,
)?;
if self.indirect_buffer_size < draw_commands.len() {
let new_indirect_buffer_size = draw_commands.len().next_power_of_two();
log::info!(
"Updating Paths Pipeline indirect buffer size from {} to {}",
self.indirect_buffer_size,
new_indirect_buffer_size
);
let indirect_draw_buffer =
create_indirect_draw_buffer(device, new_indirect_buffer_size)?;
self.indirect_draw_buffer = indirect_draw_buffer;
self.indirect_buffer_size = new_indirect_buffer_size;
}
update_buffer(device_context, &self.indirect_draw_buffer, draw_commands)?;
Ok(())
}
fn draw(
&self,
device_context: &ID3D11DeviceContext,
count: usize,
viewport: &[D3D11_VIEWPORT],
global_params: &[Option<ID3D11Buffer>],
) -> Result<()> {
unsafe {
device_context.VSSetShaderResources(1, Some(&self.view));
device_context.PSSetShaderResources(1, Some(&self.view));
device_context.IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
device_context.RSSetViewports(Some(viewport));
device_context.VSSetShader(&self.vertex, None);
device_context.PSSetShader(&self.fragment, None);
device_context.VSSetConstantBuffers(0, Some(global_params));
device_context.PSSetConstantBuffers(0, Some(global_params));
const STRIDE: u32 = std::mem::size_of::<PathVertex<ScaledPixels>>() as u32;
device_context.IASetVertexBuffers(
0,
1,
Some(&self.vertex_buffer),
Some(&STRIDE),
Some(&0),
);
device_context.IASetInputLayout(&self.input_layout);
}
for i in 0..count {
unsafe {
device_context.DrawInstancedIndirect(
&self.indirect_draw_buffer,
(i * std::mem::size_of::<DrawInstancedIndirectArgs>()) as u32,
);
}
}
Ok(())
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
@ -1048,21 +1104,6 @@ fn create_indirect_draw_buffer(device: &ID3D11Device, buffer_size: usize) -> Res
Ok(buffer.unwrap())
}
fn update_global_params(
device_context: &ID3D11DeviceContext,
buffer: &[Option<ID3D11Buffer>; 1],
globals: GlobalParams,
) -> Result<()> {
let buffer = buffer[0].as_ref().unwrap();
unsafe {
let mut data = std::mem::zeroed();
device_context.Map(buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, Some(&mut data))?;
std::ptr::copy_nonoverlapping(&globals, data.pData as *mut _, 1);
device_context.Unmap(buffer, 0);
}
Ok(())
}
fn pre_draw(
device_context: &ID3D11DeviceContext,
global_params_buffer: &[Option<ID3D11Buffer>; 1],
@ -1071,13 +1112,14 @@ fn pre_draw(
clear_color: [f32; 4],
blend_state: &ID3D11BlendState,
) -> Result<()> {
update_global_params(
let global_params = global_params_buffer[0].as_ref().unwrap();
update_buffer(
device_context,
global_params_buffer,
GlobalParams {
global_params,
&[GlobalParams {
viewport_size: [view_port[0].Width, view_port[0].Height],
..Default::default()
},
}],
)?;
unsafe {
device_context.RSSetViewports(Some(view_port));
@ -1088,70 +1130,6 @@ fn pre_draw(
Ok(())
}
fn update_paths_buffer_capacity(
pipeline: &PathsPipelineState,
data_size: usize,
device: &ID3D11Device,
) -> Option<(ID3D11Buffer, usize, [Option<ID3D11ShaderResourceView>; 1])> {
if pipeline.buffer_size >= data_size {
return None;
}
let buffer_size = data_size.next_power_of_two();
let buffer = create_buffer(device, std::mem::size_of::<PathSprite>(), buffer_size).unwrap();
let view = create_buffer_view(device, &buffer).unwrap();
Some((buffer, buffer_size, view))
}
fn update_paths_vertex_capacity(
pipeline: &PathsPipelineState,
vertex_size: usize,
device: &ID3D11Device,
) -> Option<(ID3D11Buffer, usize)> {
if pipeline.vertex_buffer_size >= vertex_size {
return None;
}
let vertex_size = vertex_size.next_power_of_two();
let buffer = create_buffer(
device,
std::mem::size_of::<PathVertex<ScaledPixels>>(),
vertex_size,
)
.unwrap();
Some((buffer, vertex_size))
}
fn update_indirect_buffer_capacity(
pipeline: &PathsPipelineState,
data_size: usize,
device: &ID3D11Device,
) -> Option<(ID3D11Buffer, usize)> {
if pipeline.indirect_buffer_size >= data_size {
return None;
}
let buffer_size = data_size.next_power_of_two();
let buffer = create_indirect_draw_buffer(device, data_size).unwrap();
Some((buffer, buffer_size))
}
fn update_paths_pipeline_buffer(
pipeline: &mut PathsPipelineState,
input: (ID3D11Buffer, usize, [Option<ID3D11ShaderResourceView>; 1]),
) {
pipeline.buffer = input.0;
pipeline.buffer_size = input.1;
pipeline.view = input.2;
}
fn update_paths_pipeline_vertex(pipeline: &mut PathsPipelineState, input: (ID3D11Buffer, usize)) {
pipeline.vertex_buffer = Some(input.0);
pipeline.vertex_buffer_size = input.1;
}
fn update_paths_indirect_buffer(pipeline: &mut PathsPipelineState, input: (ID3D11Buffer, usize)) {
pipeline.indirect_draw_buffer = input.0;
pipeline.indirect_buffer_size = input.1;
}
fn update_buffer<T>(
device_context: &ID3D11DeviceContext,
buffer: &ID3D11Buffer,
@ -1166,45 +1144,6 @@ fn update_buffer<T>(
Ok(())
}
fn prepare_indirect_draws(
device_context: &ID3D11DeviceContext,
pipeline: &PathsPipelineState,
viewport: &[D3D11_VIEWPORT],
global_params: &[Option<ID3D11Buffer>],
topology: D3D_PRIMITIVE_TOPOLOGY,
) -> Result<()> {
unsafe {
device_context.VSSetShaderResources(1, Some(&pipeline.view));
device_context.PSSetShaderResources(1, Some(&pipeline.view));
device_context.IASetPrimitiveTopology(topology);
device_context.RSSetViewports(Some(viewport));
device_context.VSSetShader(&pipeline.vertex, None);
device_context.PSSetShader(&pipeline.fragment, None);
device_context.VSSetConstantBuffers(0, Some(global_params));
device_context.PSSetConstantBuffers(0, Some(global_params));
const STRIDE: u32 = std::mem::size_of::<PathVertex<ScaledPixels>>() as u32;
device_context.IASetVertexBuffers(
0,
1,
Some(&pipeline.vertex_buffer),
Some(&STRIDE),
Some(&0),
);
device_context.IASetInputLayout(&pipeline.input_layout);
}
Ok(())
}
fn draw_indirect(
device_context: &ID3D11DeviceContext,
indirect_draw_buffer: &ID3D11Buffer,
offset: u32,
) {
unsafe {
device_context.DrawInstancedIndirect(indirect_draw_buffer, offset);
}
}
const BUFFER_COUNT: usize = 3;
mod shader_resources {