prepare for gpu rasterization
This commit is contained in:
parent
c1eaf3317d
commit
6907064be6
6 changed files with 415 additions and 37 deletions
|
@ -130,6 +130,8 @@ lyon = "1.0"
|
||||||
workspace-hack.workspace = true
|
workspace-hack.workspace = true
|
||||||
libc.workspace = true
|
libc.workspace = true
|
||||||
|
|
||||||
|
renderdoc = "0.12.1"
|
||||||
|
|
||||||
[target.'cfg(target_os = "macos")'.dependencies]
|
[target.'cfg(target_os = "macos")'.dependencies]
|
||||||
block = "0.1"
|
block = "0.1"
|
||||||
cocoa.workspace = true
|
cocoa.workspace = true
|
||||||
|
|
|
@ -40,6 +40,7 @@ pub(crate) fn swap_rgba_pa_to_bgra(color: &mut [u8]) {
|
||||||
|
|
||||||
/// An RGBA color
|
/// An RGBA color
|
||||||
#[derive(PartialEq, Clone, Copy, Default)]
|
#[derive(PartialEq, Clone, Copy, Default)]
|
||||||
|
#[repr(C)]
|
||||||
pub struct Rgba {
|
pub struct Rgba {
|
||||||
/// The red component of the color, in the range 0.0 to 1.0
|
/// The red component of the color, in the range 0.0 to 1.0
|
||||||
pub r: f32,
|
pub r: f32,
|
||||||
|
|
22
crates/gpui/src/platform/windows/color_text_raster.hlsl
Normal file
22
crates/gpui/src/platform/windows/color_text_raster.hlsl
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
|
||||||
|
struct RasterVertexInput {
|
||||||
|
float2 position : POSITION;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RasterVertexOutput {
|
||||||
|
float4 position : SV_Position;
|
||||||
|
};
|
||||||
|
|
||||||
|
RasterVertexOutput vertex(RasterVertexInput input) {
|
||||||
|
RasterVertexOutput output;
|
||||||
|
output.position = float4(input.position, 0.0, 1.0);
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct PixelInput {
|
||||||
|
float4 position: SV_Position;
|
||||||
|
};
|
||||||
|
|
||||||
|
float4 pixel(PixelInput input): SV_Target {
|
||||||
|
return float4(input.position.xy, 0.0, 1.0);
|
||||||
|
}
|
|
@ -9,7 +9,18 @@ use windows::{
|
||||||
Win32::{
|
Win32::{
|
||||||
Foundation::*,
|
Foundation::*,
|
||||||
Globalization::GetUserDefaultLocaleName,
|
Globalization::GetUserDefaultLocaleName,
|
||||||
Graphics::{DirectWrite::*, Dxgi::Common::*, Gdi::LOGFONTW, Imaging::*},
|
Graphics::{
|
||||||
|
Direct3D11::{
|
||||||
|
D3D11_BIND_SHADER_RESOURCE, D3D11_BUFFER_DESC, D3D11_CPU_ACCESS_WRITE,
|
||||||
|
D3D11_MAP_WRITE_DISCARD, D3D11_RESOURCE_MISC_BUFFER_STRUCTURED,
|
||||||
|
D3D11_TEXTURE2D_DESC, D3D11_USAGE_DEFAULT, D3D11_USAGE_DYNAMIC, ID3D11Device,
|
||||||
|
ID3D11DeviceContext, ID3D11ShaderResourceView, ID3D11Texture2D,
|
||||||
|
},
|
||||||
|
DirectWrite::*,
|
||||||
|
Dxgi::Common::*,
|
||||||
|
Gdi::LOGFONTW,
|
||||||
|
Imaging::*,
|
||||||
|
},
|
||||||
System::SystemServices::LOCALE_NAME_MAX_LENGTH,
|
System::SystemServices::LOCALE_NAME_MAX_LENGTH,
|
||||||
UI::WindowsAndMessaging::*,
|
UI::WindowsAndMessaging::*,
|
||||||
},
|
},
|
||||||
|
@ -44,7 +55,19 @@ struct GlyphRenderContext {
|
||||||
params: IDWriteRenderingParams3,
|
params: IDWriteRenderingParams3,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct GPUState {
|
||||||
|
device: ID3D11Device,
|
||||||
|
device_context: ID3D11DeviceContext,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Syncer<T>(T);
|
||||||
|
unsafe impl<T> Send for Syncer<T> {}
|
||||||
|
unsafe impl<T> Sync for Syncer<T> {}
|
||||||
|
|
||||||
struct DirectWriteState {
|
struct DirectWriteState {
|
||||||
|
gpu_state: GPUState,
|
||||||
|
#[cfg(feature = "enable-renderdoc")]
|
||||||
|
renderdoc: Syncer<Arc<RwLock<renderdoc::RenderDoc<renderdoc::V141>>>>,
|
||||||
components: DirectWriteComponent,
|
components: DirectWriteComponent,
|
||||||
system_ui_font_name: SharedString,
|
system_ui_font_name: SharedString,
|
||||||
system_font_collection: IDWriteFontCollection1,
|
system_font_collection: IDWriteFontCollection1,
|
||||||
|
@ -118,7 +141,10 @@ impl GlyphRenderContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DirectWriteTextSystem {
|
impl DirectWriteTextSystem {
|
||||||
pub(crate) fn new(bitmap_factory: &IWICImagingFactory) -> Result<Self> {
|
pub(crate) fn new(
|
||||||
|
gpu_context: &DirectXDevices,
|
||||||
|
bitmap_factory: &IWICImagingFactory,
|
||||||
|
) -> Result<Self> {
|
||||||
let components = DirectWriteComponent::new(bitmap_factory)?;
|
let components = DirectWriteComponent::new(bitmap_factory)?;
|
||||||
let system_font_collection = unsafe {
|
let system_font_collection = unsafe {
|
||||||
let mut result = std::mem::zeroed();
|
let mut result = std::mem::zeroed();
|
||||||
|
@ -135,7 +161,15 @@ impl DirectWriteTextSystem {
|
||||||
};
|
};
|
||||||
let system_ui_font_name = get_system_ui_font_name();
|
let system_ui_font_name = get_system_ui_font_name();
|
||||||
|
|
||||||
|
let gpu_state = GPUState {
|
||||||
|
device: gpu_context.device.clone(),
|
||||||
|
device_context: gpu_context.device_context.clone(),
|
||||||
|
};
|
||||||
|
|
||||||
Ok(Self(RwLock::new(DirectWriteState {
|
Ok(Self(RwLock::new(DirectWriteState {
|
||||||
|
gpu_state,
|
||||||
|
#[cfg(feature = "enable-renderdoc")]
|
||||||
|
renderdoc: Syncer(Arc::new(RwLock::new(renderdoc::RenderDoc::new().unwrap()))),
|
||||||
components,
|
components,
|
||||||
system_ui_font_name,
|
system_ui_font_name,
|
||||||
system_font_collection,
|
system_font_collection,
|
||||||
|
@ -803,21 +837,32 @@ impl DirectWriteState {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut bitmap_data;
|
let mut bitmap_data: Vec<u8>;
|
||||||
if params.is_emoji {
|
if params.is_emoji {
|
||||||
// todo: support more glyph image formats for more exotic fonts, for now it should fallback to monochrome rendering
|
bitmap_data = vec![0u8; texture_width as usize * texture_height as usize * 4];
|
||||||
let color_enumerator = unsafe {
|
|
||||||
self.components.factory.TranslateColorGlyphRun(
|
self.rasterize_color(
|
||||||
Vector2::new(baseline_origin_x, baseline_origin_y),
|
&glyph_run,
|
||||||
&glyph_run,
|
rendering_mode,
|
||||||
None,
|
measuring_mode,
|
||||||
DWRITE_GLYPH_IMAGE_FORMATS_COLR
|
&transform,
|
||||||
| DWRITE_GLYPH_IMAGE_FORMATS_PREMULTIPLIED_B8G8R8A8,
|
point(baseline_origin_x, baseline_origin_y),
|
||||||
measuring_mode,
|
size(DevicePixels(0), DevicePixels(0)),
|
||||||
Some(&transform),
|
size(0, 0),
|
||||||
0,
|
);
|
||||||
)
|
// // todo: support more glyph image formats for more exotic fonts, for now it should fallback to monochrome rendering
|
||||||
};
|
// let color_enumerator = unsafe {
|
||||||
|
// self.components.factory.TranslateColorGlyphRun(
|
||||||
|
// Vector2::new(baseline_origin_x, baseline_origin_y),
|
||||||
|
// &glyph_run,
|
||||||
|
// None,
|
||||||
|
// DWRITE_GLYPH_IMAGE_FORMATS_COLR
|
||||||
|
// | DWRITE_GLYPH_IMAGE_FORMATS_PREMULTIPLIED_B8G8R8A8,
|
||||||
|
// measuring_mode,
|
||||||
|
// Some(&transform),
|
||||||
|
// 0,
|
||||||
|
// )
|
||||||
|
// };
|
||||||
|
|
||||||
// if let Ok(color_enumerator) = color_enumerator {
|
// if let Ok(color_enumerator) = color_enumerator {
|
||||||
// loop {
|
// loop {
|
||||||
|
@ -954,18 +999,36 @@ impl DirectWriteState {
|
||||||
// break;
|
// break;
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
// // bitmap_data.chunks_mut(4).for_each(|chunk| {
|
||||||
|
// // let tmp = chunk[2];
|
||||||
|
// // chunk[2] = chunk[0];
|
||||||
|
// // chunk[0] = tmp;
|
||||||
|
// // });
|
||||||
|
|
||||||
|
// std::fs::write(
|
||||||
|
// &format!(
|
||||||
|
// "{}x{}_{}_color.raw",
|
||||||
|
// texture_width, texture_height, params.glyph_id.0
|
||||||
|
// ),
|
||||||
|
// &bitmap_data,
|
||||||
|
// )
|
||||||
|
// .unwrap();
|
||||||
// } else {
|
// } else {
|
||||||
|
// let monochrome_data = Self::rasterize_monochrome(
|
||||||
|
// &glyph_analysis,
|
||||||
|
// bitmap_size,
|
||||||
|
// size(texture_width, texture_height),
|
||||||
|
// &texture_bounds,
|
||||||
|
// )?;
|
||||||
|
// // todo: monochrome emojis should be handled gracefully by the renderer
|
||||||
|
// // currently they just get drawn as their reported color because it assumes they are always colored
|
||||||
|
// // but in reality monochrome emojis should be colored the same as text is
|
||||||
|
// bitmap_data = monochrome_data
|
||||||
|
// .into_iter()
|
||||||
|
// .flat_map(|e| [0, 0, 0, e])
|
||||||
|
// .collect::<Vec<u8>>();
|
||||||
// }
|
// }
|
||||||
let monochrome_data = Self::rasterize_monochrome(
|
|
||||||
&glyph_analysis,
|
|
||||||
bitmap_size,
|
|
||||||
size(texture_width, texture_height),
|
|
||||||
&texture_bounds,
|
|
||||||
)?;
|
|
||||||
bitmap_data = monochrome_data
|
|
||||||
.into_iter()
|
|
||||||
.flat_map(|e| [e, e, e, 255])
|
|
||||||
.collect::<Vec<u8>>();
|
|
||||||
} else {
|
} else {
|
||||||
bitmap_data = Self::rasterize_monochrome(
|
bitmap_data = Self::rasterize_monochrome(
|
||||||
&glyph_analysis,
|
&glyph_analysis,
|
||||||
|
@ -1025,6 +1088,214 @@ impl DirectWriteState {
|
||||||
Ok(bitmap_data)
|
Ok(bitmap_data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn rasterize_color(
|
||||||
|
&self,
|
||||||
|
glyph_run: &DWRITE_GLYPH_RUN,
|
||||||
|
rendering_mode: DWRITE_RENDERING_MODE1,
|
||||||
|
measuring_mode: DWRITE_MEASURING_MODE,
|
||||||
|
transform: &DWRITE_MATRIX,
|
||||||
|
baseline_origin: Point<f32>,
|
||||||
|
bitmap_size: Size<DevicePixels>,
|
||||||
|
texture_size: Size<u32>,
|
||||||
|
) -> Result<Vec<u8>> {
|
||||||
|
let color_enumerator = unsafe {
|
||||||
|
self.components.factory.TranslateColorGlyphRun(
|
||||||
|
Vector2::new(baseline_origin.x, baseline_origin.y),
|
||||||
|
glyph_run,
|
||||||
|
None,
|
||||||
|
DWRITE_GLYPH_IMAGE_FORMATS_COLR | DWRITE_GLYPH_IMAGE_FORMATS_PREMULTIPLIED_B8G8R8A8,
|
||||||
|
measuring_mode,
|
||||||
|
Some(transform),
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
}?;
|
||||||
|
|
||||||
|
let mut glyph_layers = Vec::new();
|
||||||
|
loop {
|
||||||
|
let color_run = unsafe { color_enumerator.GetCurrentRun() }?;
|
||||||
|
let color_run = unsafe { &*color_run };
|
||||||
|
|
||||||
|
let color_analysis = unsafe {
|
||||||
|
self.components.factory.CreateGlyphRunAnalysis(
|
||||||
|
&color_run.Base.glyphRun as *const _,
|
||||||
|
Some(transform),
|
||||||
|
rendering_mode,
|
||||||
|
measuring_mode,
|
||||||
|
DWRITE_GRID_FIT_MODE_DEFAULT,
|
||||||
|
DWRITE_TEXT_ANTIALIAS_MODE_CLEARTYPE,
|
||||||
|
baseline_origin.x,
|
||||||
|
baseline_origin.y,
|
||||||
|
)
|
||||||
|
}?;
|
||||||
|
|
||||||
|
let color_bounds =
|
||||||
|
unsafe { color_analysis.GetAlphaTextureBounds(DWRITE_TEXTURE_CLEARTYPE_3x1) }?;
|
||||||
|
|
||||||
|
let color_size = size(
|
||||||
|
color_bounds.right - color_bounds.left,
|
||||||
|
color_bounds.bottom - color_bounds.top,
|
||||||
|
);
|
||||||
|
if color_size.width > 0 && color_size.height > 0 {
|
||||||
|
let mut alpha_data = vec![0u8; (color_size.width * color_size.height * 3) as usize];
|
||||||
|
unsafe {
|
||||||
|
color_analysis.CreateAlphaTexture(
|
||||||
|
DWRITE_TEXTURE_CLEARTYPE_3x1,
|
||||||
|
&color_bounds,
|
||||||
|
&mut alpha_data,
|
||||||
|
)
|
||||||
|
}?;
|
||||||
|
|
||||||
|
let run_color = {
|
||||||
|
let run_color = color_run.Base.runColor;
|
||||||
|
Rgba {
|
||||||
|
r: run_color.r,
|
||||||
|
g: run_color.g,
|
||||||
|
b: run_color.b,
|
||||||
|
a: run_color.a,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let bounds = bounds(point(color_bounds.left, color_bounds.top), color_size);
|
||||||
|
let alpha_data = alpha_data
|
||||||
|
.chunks_exact(3)
|
||||||
|
.flat_map(|chunk| [chunk[0], chunk[1], chunk[2], 255])
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
glyph_layers.push(GlyphLayerTexture::new(
|
||||||
|
&self.gpu_state,
|
||||||
|
run_color,
|
||||||
|
bounds,
|
||||||
|
&alpha_data,
|
||||||
|
)?);
|
||||||
|
}
|
||||||
|
|
||||||
|
let has_next = unsafe { color_enumerator.MoveNext() }
|
||||||
|
.map(|e| e.as_bool())
|
||||||
|
.unwrap_or(false);
|
||||||
|
if !has_next {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let params = glyph_layers
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(index, e)| GlyphLayerTextureParams {
|
||||||
|
run_color: e.run_color,
|
||||||
|
bounds: e.bounds,
|
||||||
|
alpha_texture_index: index as u32,
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let params_buffer = {
|
||||||
|
let desc = D3D11_BUFFER_DESC {
|
||||||
|
ByteWidth: (std::mem::size_of::<GlyphLayerTextureParams>() * params.len()) as u32,
|
||||||
|
Usage: D3D11_USAGE_DYNAMIC,
|
||||||
|
BindFlags: D3D11_BIND_SHADER_RESOURCE.0 as u32,
|
||||||
|
CPUAccessFlags: D3D11_CPU_ACCESS_WRITE.0 as u32,
|
||||||
|
MiscFlags: D3D11_RESOURCE_MISC_BUFFER_STRUCTURED.0 as u32,
|
||||||
|
StructureByteStride: std::mem::size_of::<GlyphLayerTextureParams>() as u32,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut buffer = None;
|
||||||
|
unsafe {
|
||||||
|
self.gpu_state
|
||||||
|
.device
|
||||||
|
.CreateBuffer(&desc, None, Some(&mut buffer))
|
||||||
|
}?;
|
||||||
|
buffer.unwrap()
|
||||||
|
};
|
||||||
|
let params_buffer_view = {
|
||||||
|
let mut view = None;
|
||||||
|
unsafe {
|
||||||
|
self.gpu_state.device.CreateShaderResourceView(
|
||||||
|
¶ms_buffer,
|
||||||
|
None,
|
||||||
|
Some(&mut view),
|
||||||
|
)
|
||||||
|
}?;
|
||||||
|
[view]
|
||||||
|
};
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let mut dest = std::mem::zeroed();
|
||||||
|
self.gpu_state.device_context.Map(
|
||||||
|
¶ms_buffer,
|
||||||
|
0,
|
||||||
|
D3D11_MAP_WRITE_DISCARD,
|
||||||
|
0,
|
||||||
|
Some(&mut dest),
|
||||||
|
)?;
|
||||||
|
std::ptr::copy_nonoverlapping(params.as_ptr(), dest.pData as *mut _, params.len());
|
||||||
|
self.gpu_state.device_context.Unmap(¶ms_buffer, 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
let textures = glyph_layers
|
||||||
|
.iter()
|
||||||
|
.map(|layer| Some(layer.texture_view.clone()))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let vertex_shader = {
|
||||||
|
let source =
|
||||||
|
shader_resources::build_shader_blob("color_text_raster", "vertex", "vs_5_0")?;
|
||||||
|
let bytes = unsafe {
|
||||||
|
std::slice::from_raw_parts(
|
||||||
|
source.GetBufferPointer() as *mut u8,
|
||||||
|
source.GetBufferSize(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
let mut shader = None;
|
||||||
|
unsafe {
|
||||||
|
self.gpu_state
|
||||||
|
.device
|
||||||
|
.CreateVertexShader(bytes, None, Some(&mut shader))
|
||||||
|
}?;
|
||||||
|
shader.unwrap()
|
||||||
|
};
|
||||||
|
|
||||||
|
let pixel_shader = {
|
||||||
|
let source =
|
||||||
|
shader_resources::build_shader_blob("color_text_raster", "pixel", "ps_5_0")?;
|
||||||
|
let bytes = unsafe {
|
||||||
|
std::slice::from_raw_parts(
|
||||||
|
source.GetBufferPointer() as *mut u8,
|
||||||
|
source.GetBufferSize(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
let mut shader = None;
|
||||||
|
unsafe {
|
||||||
|
self.gpu_state
|
||||||
|
.device
|
||||||
|
.CreatePixelShader(bytes, None, Some(&mut shader))
|
||||||
|
}?;
|
||||||
|
shader.unwrap()
|
||||||
|
};
|
||||||
|
|
||||||
|
#[cfg(feature = "enable-renderdoc")]
|
||||||
|
self.renderdoc
|
||||||
|
.0
|
||||||
|
.write()
|
||||||
|
.start_frame_capture(std::ptr::null(), std::ptr::null());
|
||||||
|
|
||||||
|
let device_context = &self.gpu_state.device_context;
|
||||||
|
unsafe { device_context.VSSetShaderResources(0, Some(textures.as_slice())) };
|
||||||
|
unsafe { device_context.PSSetShaderResources(0, Some(textures.as_slice())) };
|
||||||
|
unsafe { device_context.VSSetShaderResources(1, Some(¶ms_buffer_view)) };
|
||||||
|
unsafe { device_context.PSSetShaderResources(1, Some(¶ms_buffer_view)) };
|
||||||
|
unsafe { device_context.VSSetShader(&vertex_shader, None) };
|
||||||
|
unsafe { device_context.PSSetShader(&pixel_shader, None) };
|
||||||
|
|
||||||
|
unsafe { device_context.DrawInstanced(4, params.len() as u32, 0, 0) };
|
||||||
|
|
||||||
|
#[cfg(feature = "enable-renderdoc")]
|
||||||
|
self.renderdoc
|
||||||
|
.0
|
||||||
|
.write()
|
||||||
|
.end_frame_capture(std::ptr::null(), std::ptr::null());
|
||||||
|
|
||||||
|
println!("render finished");
|
||||||
|
|
||||||
|
Ok(Vec::new())
|
||||||
|
}
|
||||||
|
|
||||||
fn get_typographic_bounds(&self, font_id: FontId, glyph_id: GlyphId) -> Result<Bounds<f32>> {
|
fn get_typographic_bounds(&self, font_id: FontId, glyph_id: GlyphId) -> Result<Bounds<f32>> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let font = &self.fonts[font_id.0].font_face;
|
let font = &self.fonts[font_id.0].font_face;
|
||||||
|
@ -1096,6 +1367,84 @@ impl Drop for DirectWriteState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct GlyphLayerTexture {
|
||||||
|
run_color: Rgba,
|
||||||
|
bounds: Bounds<i32>,
|
||||||
|
texture: ID3D11Texture2D,
|
||||||
|
texture_view: ID3D11ShaderResourceView,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GlyphLayerTexture {
|
||||||
|
pub fn new(
|
||||||
|
gpu_state: &GPUState,
|
||||||
|
run_color: Rgba,
|
||||||
|
bounds: Bounds<i32>,
|
||||||
|
alpha_data: &[u8],
|
||||||
|
) -> Result<Self> {
|
||||||
|
let texture_size = bounds.size;
|
||||||
|
|
||||||
|
let desc = D3D11_TEXTURE2D_DESC {
|
||||||
|
Width: texture_size.width as u32,
|
||||||
|
Height: texture_size.height as u32,
|
||||||
|
MipLevels: 1,
|
||||||
|
ArraySize: 1,
|
||||||
|
Format: DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||||
|
SampleDesc: DXGI_SAMPLE_DESC {
|
||||||
|
Count: 1,
|
||||||
|
Quality: 0,
|
||||||
|
},
|
||||||
|
Usage: D3D11_USAGE_DEFAULT,
|
||||||
|
BindFlags: D3D11_BIND_SHADER_RESOURCE.0 as u32,
|
||||||
|
CPUAccessFlags: D3D11_CPU_ACCESS_WRITE.0 as u32,
|
||||||
|
MiscFlags: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
let texture = {
|
||||||
|
let mut texture: Option<ID3D11Texture2D> = None;
|
||||||
|
unsafe {
|
||||||
|
gpu_state
|
||||||
|
.device
|
||||||
|
.CreateTexture2D(&desc, None, Some(&mut texture))?
|
||||||
|
};
|
||||||
|
texture.unwrap()
|
||||||
|
};
|
||||||
|
let texture_view = {
|
||||||
|
let mut view: Option<ID3D11ShaderResourceView> = None;
|
||||||
|
unsafe {
|
||||||
|
gpu_state
|
||||||
|
.device
|
||||||
|
.CreateShaderResourceView(&texture, None, Some(&mut view))?
|
||||||
|
};
|
||||||
|
view.unwrap()
|
||||||
|
};
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
gpu_state.device_context.UpdateSubresource(
|
||||||
|
&texture,
|
||||||
|
0,
|
||||||
|
None,
|
||||||
|
alpha_data.as_ptr() as _,
|
||||||
|
(texture_size.width * 4) as u32,
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(GlyphLayerTexture {
|
||||||
|
run_color,
|
||||||
|
bounds,
|
||||||
|
texture,
|
||||||
|
texture_view,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
struct GlyphLayerTextureParams {
|
||||||
|
run_color: Rgba,
|
||||||
|
bounds: Bounds<i32>,
|
||||||
|
alpha_texture_index: u32,
|
||||||
|
}
|
||||||
|
|
||||||
struct TextRendererWrapper(pub IDWriteTextRenderer);
|
struct TextRendererWrapper(pub IDWriteTextRenderer);
|
||||||
|
|
||||||
impl TextRendererWrapper {
|
impl TextRendererWrapper {
|
||||||
|
|
|
@ -36,8 +36,8 @@ pub(crate) struct DirectXDevices {
|
||||||
dxgi_factory: IDXGIFactory6,
|
dxgi_factory: IDXGIFactory6,
|
||||||
#[cfg(not(feature = "enable-renderdoc"))]
|
#[cfg(not(feature = "enable-renderdoc"))]
|
||||||
dxgi_device: IDXGIDevice,
|
dxgi_device: IDXGIDevice,
|
||||||
device: ID3D11Device,
|
pub(crate) device: ID3D11Device,
|
||||||
device_context: ID3D11DeviceContext,
|
pub(crate) device_context: ID3D11DeviceContext,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct DirectXResources {
|
struct DirectXResources {
|
||||||
|
@ -630,7 +630,8 @@ impl<T> PipelineState<T> {
|
||||||
buffer_size: usize,
|
buffer_size: usize,
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
let vertex = {
|
let vertex = {
|
||||||
let shader_blob = shader_resources::build_shader_blob(vertex_entry, "vs_5_0")?;
|
let shader_blob =
|
||||||
|
shader_resources::build_shader_blob("shaders", vertex_entry, "vs_5_0")?;
|
||||||
let bytes = unsafe {
|
let bytes = unsafe {
|
||||||
std::slice::from_raw_parts(
|
std::slice::from_raw_parts(
|
||||||
shader_blob.GetBufferPointer() as *mut u8,
|
shader_blob.GetBufferPointer() as *mut u8,
|
||||||
|
@ -640,7 +641,8 @@ impl<T> PipelineState<T> {
|
||||||
create_vertex_shader(device, bytes)?
|
create_vertex_shader(device, bytes)?
|
||||||
};
|
};
|
||||||
let fragment = {
|
let fragment = {
|
||||||
let shader_blob = shader_resources::build_shader_blob(fragment_entry, "ps_5_0")?;
|
let shader_blob =
|
||||||
|
shader_resources::build_shader_blob("shaders", fragment_entry, "ps_5_0")?;
|
||||||
let bytes = unsafe {
|
let bytes = unsafe {
|
||||||
std::slice::from_raw_parts(
|
std::slice::from_raw_parts(
|
||||||
shader_blob.GetBufferPointer() as *mut u8,
|
shader_blob.GetBufferPointer() as *mut u8,
|
||||||
|
@ -740,7 +742,8 @@ impl<T> PipelineState<T> {
|
||||||
impl PathsPipelineState {
|
impl PathsPipelineState {
|
||||||
fn new(device: &ID3D11Device) -> Result<Self> {
|
fn new(device: &ID3D11Device) -> Result<Self> {
|
||||||
let (vertex, vertex_shader) = {
|
let (vertex, vertex_shader) = {
|
||||||
let shader_blob = shader_resources::build_shader_blob("paths_vertex", "vs_5_0")?;
|
let shader_blob =
|
||||||
|
shader_resources::build_shader_blob("shaders", "paths_vertex", "vs_5_0")?;
|
||||||
let bytes = unsafe {
|
let bytes = unsafe {
|
||||||
std::slice::from_raw_parts(
|
std::slice::from_raw_parts(
|
||||||
shader_blob.GetBufferPointer() as *mut u8,
|
shader_blob.GetBufferPointer() as *mut u8,
|
||||||
|
@ -750,7 +753,8 @@ impl PathsPipelineState {
|
||||||
(create_vertex_shader(device, bytes)?, shader_blob)
|
(create_vertex_shader(device, bytes)?, shader_blob)
|
||||||
};
|
};
|
||||||
let fragment = {
|
let fragment = {
|
||||||
let shader_blob = shader_resources::build_shader_blob("paths_fragment", "ps_5_0")?;
|
let shader_blob =
|
||||||
|
shader_resources::build_shader_blob("shaders", "paths_fragment", "ps_5_0")?;
|
||||||
let bytes = unsafe {
|
let bytes = unsafe {
|
||||||
std::slice::from_raw_parts(
|
std::slice::from_raw_parts(
|
||||||
shader_blob.GetBufferPointer() as *mut u8,
|
shader_blob.GetBufferPointer() as *mut u8,
|
||||||
|
@ -1314,7 +1318,7 @@ fn set_pipeline_state(
|
||||||
|
|
||||||
const BUFFER_COUNT: usize = 3;
|
const BUFFER_COUNT: usize = 3;
|
||||||
|
|
||||||
mod shader_resources {
|
pub(crate) mod shader_resources {
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use windows::Win32::Graphics::Direct3D::{
|
use windows::Win32::Graphics::Direct3D::{
|
||||||
Fxc::{D3DCOMPILE_DEBUG, D3DCOMPILE_SKIP_OPTIMIZATION, D3DCompileFromFile},
|
Fxc::{D3DCOMPILE_DEBUG, D3DCOMPILE_SKIP_OPTIMIZATION, D3DCompileFromFile},
|
||||||
|
@ -1322,14 +1326,14 @@ mod shader_resources {
|
||||||
};
|
};
|
||||||
use windows_core::{HSTRING, PCSTR};
|
use windows_core::{HSTRING, PCSTR};
|
||||||
|
|
||||||
pub(super) fn build_shader_blob(entry: &str, target: &str) -> Result<ID3DBlob> {
|
pub(crate) fn build_shader_blob(filename: &str, entry: &str, target: &str) -> Result<ID3DBlob> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut entry = entry.to_owned();
|
let mut entry = entry.to_owned();
|
||||||
let mut target = target.to_owned();
|
let mut target = target.to_owned();
|
||||||
let mut compile_blob = None;
|
let mut compile_blob = None;
|
||||||
let mut error_blob = None;
|
let mut error_blob = None;
|
||||||
let shader_path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
let shader_path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
||||||
.join("src/platform/windows/shaders.hlsl")
|
.join(&format!("src/platform/windows/{}.hlsl", filename))
|
||||||
.canonicalize()
|
.canonicalize()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
entry.push_str("\0");
|
entry.push_str("\0");
|
||||||
|
|
|
@ -96,12 +96,13 @@ impl WindowsPlatform {
|
||||||
));
|
));
|
||||||
let background_executor = BackgroundExecutor::new(dispatcher.clone());
|
let background_executor = BackgroundExecutor::new(dispatcher.clone());
|
||||||
let foreground_executor = ForegroundExecutor::new(dispatcher);
|
let foreground_executor = ForegroundExecutor::new(dispatcher);
|
||||||
|
let directx_devices = DirectXDevices::new().context("Unable to init directx devices.")?;
|
||||||
let bitmap_factory = ManuallyDrop::new(unsafe {
|
let bitmap_factory = ManuallyDrop::new(unsafe {
|
||||||
CoCreateInstance(&CLSID_WICImagingFactory, None, CLSCTX_INPROC_SERVER)
|
CoCreateInstance(&CLSID_WICImagingFactory, None, CLSCTX_INPROC_SERVER)
|
||||||
.context("Error creating bitmap factory.")?
|
.context("Error creating bitmap factory.")?
|
||||||
});
|
});
|
||||||
let text_system = Arc::new(
|
let text_system = Arc::new(
|
||||||
DirectWriteTextSystem::new(&bitmap_factory)
|
DirectWriteTextSystem::new(&directx_devices, &bitmap_factory)
|
||||||
.context("Error creating DirectWriteTextSystem")?,
|
.context("Error creating DirectWriteTextSystem")?,
|
||||||
);
|
);
|
||||||
let drop_target_helper: IDropTargetHelper = unsafe {
|
let drop_target_helper: IDropTargetHelper = unsafe {
|
||||||
|
@ -111,7 +112,6 @@ impl WindowsPlatform {
|
||||||
let icon = load_icon().unwrap_or_default();
|
let icon = load_icon().unwrap_or_default();
|
||||||
let state = RefCell::new(WindowsPlatformState::new());
|
let state = RefCell::new(WindowsPlatformState::new());
|
||||||
let raw_window_handles = RwLock::new(SmallVec::new());
|
let raw_window_handles = RwLock::new(SmallVec::new());
|
||||||
let directx_devices = DirectXDevices::new().context("Unable to init directx devices.")?;
|
|
||||||
let windows_version = WindowsVersion::new().context("Error retrieve windows version")?;
|
let windows_version = WindowsVersion::new().context("Error retrieve windows version")?;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue