This commit is contained in:
Junkui Zhang 2025-07-16 14:04:49 +08:00
parent f715acc92a
commit 2017ce3699

View file

@ -45,12 +45,12 @@ struct DirectXContext {
}
struct DirectXRenderPipelines {
shadow_pipeline: PipelineState,
quad_pipeline: PipelineState,
shadow_pipeline: PipelineState<Shadow>,
quad_pipeline: PipelineState<Quad>,
paths_pipeline: PathsPipelineState,
underline_pipeline: PipelineState,
mono_sprites: PipelineState,
poly_sprites: PipelineState,
underline_pipeline: PipelineState<Underline>,
mono_sprites: PipelineState<MonochromeSprite>,
poly_sprites: PipelineState<PolychromeSprite>,
}
struct DirectXGlobalElements {
@ -225,16 +225,9 @@ impl DirectXRenderer {
if shadows.is_empty() {
return Ok(());
}
update_buffer_capacity(
&self.pipelines.shadow_pipeline,
std::mem::size_of::<Shadow>(),
shadows.len(),
self.pipelines.shadow_pipeline.update_buffer(
&self.devices.device,
)
.map(|input| update_pipeline(&mut self.pipelines.shadow_pipeline, input));
update_buffer(
&self.devices.device_context,
&self.pipelines.shadow_pipeline.buffer,
shadows,
)?;
draw_normal(
@ -252,16 +245,9 @@ impl DirectXRenderer {
if quads.is_empty() {
return Ok(());
}
update_buffer_capacity(
&self.pipelines.quad_pipeline,
std::mem::size_of::<Quad>(),
quads.len(),
self.pipelines.quad_pipeline.update_buffer(
&self.devices.device,
)
.map(|input| update_pipeline(&mut self.pipelines.quad_pipeline, input));
update_buffer(
&self.devices.device_context,
&self.pipelines.quad_pipeline.buffer,
quads,
)?;
draw_normal(
@ -364,16 +350,9 @@ impl DirectXRenderer {
if underlines.is_empty() {
return Ok(());
}
update_buffer_capacity(
&self.pipelines.underline_pipeline,
std::mem::size_of::<Underline>(),
underlines.len(),
self.pipelines.underline_pipeline.update_buffer(
&self.devices.device,
)
.map(|input| update_pipeline(&mut self.pipelines.underline_pipeline, input));
update_buffer(
&self.devices.device_context,
&self.pipelines.underline_pipeline.buffer,
underlines,
)?;
draw_normal(
@ -395,19 +374,12 @@ impl DirectXRenderer {
if sprites.is_empty() {
return Ok(());
}
let texture_view = self.atlas.get_texture_view(texture_id);
update_buffer_capacity(
&self.pipelines.mono_sprites,
std::mem::size_of::<MonochromeSprite>(),
sprites.len(),
self.pipelines.mono_sprites.update_buffer(
&self.devices.device,
)
.map(|input| update_pipeline(&mut self.pipelines.mono_sprites, input));
update_buffer(
&self.devices.device_context,
&self.pipelines.mono_sprites.buffer,
sprites,
)?;
let texture_view = self.atlas.get_texture_view(texture_id);
draw_with_texture(
&self.devices.device_context,
&self.pipelines.mono_sprites,
@ -427,19 +399,12 @@ impl DirectXRenderer {
if sprites.is_empty() {
return Ok(());
}
let texture_view = self.atlas.get_texture_view(texture_id);
update_buffer_capacity(
&self.pipelines.poly_sprites,
std::mem::size_of::<PolychromeSprite>(),
sprites.len(),
self.pipelines.poly_sprites.update_buffer(
&self.devices.device,
)
.map(|input| update_pipeline(&mut self.pipelines.poly_sprites, input));
update_buffer(
&self.devices.device_context,
&self.pipelines.poly_sprites.buffer,
sprites,
)?;
let texture_view = self.atlas.get_texture_view(texture_id);
draw_with_texture(
&self.devices.device_context,
&self.pipelines.poly_sprites,
@ -490,47 +455,35 @@ impl DirectXContext {
impl DirectXRenderPipelines {
pub fn new(device: &ID3D11Device) -> Result<Self> {
let shadow_pipeline = create_pipieline(
let shadow_pipeline = PipelineState::new(
device,
"shadow_pipeline",
"shadow_vertex",
"shadow_fragment",
std::mem::size_of::<Shadow>(),
32,
)?;
let quad_pipeline = create_pipieline(
device,
"quad_vertex",
"quad_fragment",
std::mem::size_of::<Quad>(),
32,
)?;
// let paths_pipeline = create_pipieline(
// device,
// "paths_vertex",
// "paths_fragment",
// std::mem::size_of::<PathSprite>(),
// 32,
// )?;
let quad_pipeline =
PipelineState::new(device, "quad_pipeline", "quad_vertex", "quad_fragment", 32)?;
let paths_pipeline = PathsPipelineState::new(device)?;
let underline_pipeline = create_pipieline(
let underline_pipeline = PipelineState::new(
device,
"underline_pipeline",
"underline_vertex",
"underline_fragment",
std::mem::size_of::<Underline>(),
32,
)?;
let mono_sprites = create_pipieline(
let mono_sprites = PipelineState::new(
device,
"monochrome_sprite_pipeline",
"monochrome_sprite_vertex",
"monochrome_sprite_fragment",
std::mem::size_of::<MonochromeSprite>(),
32,
)?;
let poly_sprites = create_pipieline(
let poly_sprites = PipelineState::new(
device,
"polychrome_sprite_pipeline",
"polychrome_sprite_vertex",
"polychrome_sprite_fragment",
std::mem::size_of::<PolychromeSprite>(),
32,
)?;
@ -619,12 +572,14 @@ struct GlobalParams {
_pad: u64,
}
struct PipelineState {
struct PipelineState<T> {
label: &'static str,
vertex: ID3D11VertexShader,
fragment: ID3D11PixelShader,
buffer: ID3D11Buffer,
buffer_size: usize,
view: [Option<ID3D11ShaderResourceView>; 1],
_marker: std::marker::PhantomData<T>,
}
struct PathsPipelineState {
@ -640,6 +595,71 @@ struct PathsPipelineState {
view: [Option<ID3D11ShaderResourceView>; 1],
}
impl<T> PipelineState<T> {
fn new(
device: &ID3D11Device,
label: &'static str,
vertex_entry: &str,
fragment_entry: &str,
buffer_size: usize,
) -> Result<Self> {
let vertex = {
let shader_blob = shader_resources::build_shader_blob(vertex_entry, "vs_5_0")?;
let bytes = unsafe {
std::slice::from_raw_parts(
shader_blob.GetBufferPointer() as *mut u8,
shader_blob.GetBufferSize(),
)
};
create_vertex_shader(device, bytes)?
};
let fragment = {
let shader_blob = shader_resources::build_shader_blob(fragment_entry, "ps_5_0")?;
let bytes = unsafe {
std::slice::from_raw_parts(
shader_blob.GetBufferPointer() as *mut u8,
shader_blob.GetBufferSize(),
)
};
create_fragment_shader(device, bytes)?
};
let buffer = create_buffer(device, std::mem::size_of::<T>(), buffer_size)?;
let view = create_buffer_view(device, &buffer)?;
Ok(PipelineState {
label,
vertex,
fragment,
buffer,
buffer_size,
view,
_marker: std::marker::PhantomData,
})
}
fn update_buffer(
&mut self,
device: &ID3D11Device,
device_context: &ID3D11DeviceContext,
data: &[T],
) -> Result<()> {
if self.buffer_size < data.len() {
let new_buffer_size = data.len().next_power_of_two();
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;
}
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(())
}
}
impl PathsPipelineState {
fn new(device: &ID3D11Device) -> Result<Self> {
let (vertex, vertex_shader) = {
@ -933,44 +953,6 @@ fn create_blend_state(device: &ID3D11Device) -> Result<ID3D11BlendState> {
}
}
fn create_pipieline(
device: &ID3D11Device,
vertex_entry: &str,
fragment_entry: &str,
element_size: usize,
buffer_size: usize,
) -> Result<PipelineState> {
let vertex = {
let shader_blob = shader_resources::build_shader_blob(vertex_entry, "vs_5_0")?;
let bytes = unsafe {
std::slice::from_raw_parts(
shader_blob.GetBufferPointer() as *mut u8,
shader_blob.GetBufferSize(),
)
};
create_vertex_shader(device, bytes)?
};
let fragment = {
let shader_blob = shader_resources::build_shader_blob(fragment_entry, "ps_5_0")?;
let bytes = unsafe {
std::slice::from_raw_parts(
shader_blob.GetBufferPointer() as *mut u8,
shader_blob.GetBufferSize(),
)
};
create_fragment_shader(device, bytes)?
};
let buffer = create_buffer(device, element_size, buffer_size)?;
let view = create_buffer_view(device, &buffer)?;
Ok(PipelineState {
vertex,
fragment,
buffer,
buffer_size,
view,
})
}
fn create_vertex_shader(device: &ID3D11Device, bytes: &[u8]) -> Result<ID3D11VertexShader> {
unsafe {
let mut shader = None;
@ -1068,21 +1050,6 @@ fn pre_draw(
Ok(())
}
fn update_buffer_capacity(
pipeline: &PipelineState,
element_size: usize,
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, element_size, buffer_size).unwrap();
let view = create_buffer_view(device, &buffer).unwrap();
Some((buffer, buffer_size, view))
}
fn update_paths_buffer_capacity(
pipeline: &PathsPipelineState,
data_size: usize,
@ -1128,15 +1095,6 @@ fn update_indirect_buffer_capacity(
Some((buffer, buffer_size))
}
fn update_pipeline(
pipeline: &mut PipelineState,
input: (ID3D11Buffer, usize, [Option<ID3D11ShaderResourceView>; 1]),
) {
pipeline.buffer = input.0;
pipeline.buffer_size = input.1;
pipeline.view = input.2;
}
fn update_paths_pipeline_buffer(
pipeline: &mut PathsPipelineState,
input: (ID3D11Buffer, usize, [Option<ID3D11ShaderResourceView>; 1]),
@ -1209,9 +1167,9 @@ fn draw_indirect(
}
}
fn draw_normal(
fn draw_normal<T>(
device_context: &ID3D11DeviceContext,
pipeline: &PipelineState,
pipeline: &PipelineState<T>,
viewport: &[D3D11_VIEWPORT],
global_params: &[Option<ID3D11Buffer>],
topology: D3D_PRIMITIVE_TOPOLOGY,
@ -1233,9 +1191,9 @@ fn draw_normal(
Ok(())
}
fn draw_with_texture(
fn draw_with_texture<T>(
device_context: &ID3D11DeviceContext,
pipeline: &PipelineState,
pipeline: &PipelineState<T>,
texture: &[Option<ID3D11ShaderResourceView>],
viewport: &[D3D11_VIEWPORT],
global_params: &[Option<ID3D11Buffer>],