From 5ff9114b18d342129581d5d62f59c7100f5bdadd Mon Sep 17 00:00:00 2001 From: Junkui Zhang <364772080@qq.com> Date: Fri, 18 Jul 2025 17:43:01 +0800 Subject: [PATCH] add runtime shader --- crates/gpui/build.rs | 1 + .../src/platform/windows/directx_renderer.rs | 88 ++++++++++++------- 2 files changed, 56 insertions(+), 33 deletions(-) diff --git a/crates/gpui/build.rs b/crates/gpui/build.rs index f8f756cc532ee3f2922dcbe5ca45d52fc89b3907..a7f323277a56de7db107603cfe66955162047c57 100644 --- a/crates/gpui/build.rs +++ b/crates/gpui/build.rs @@ -254,6 +254,7 @@ mod windows { link_amd_ags(); // Compile HLSL shaders + #[cfg(not(debug_assertions))] compile_shaders(); // Embed the Windows manifest and resource file diff --git a/crates/gpui/src/platform/windows/directx_renderer.rs b/crates/gpui/src/platform/windows/directx_renderer.rs index 7959e2d90f04ebf45ce0c117d1edd0ce9d18d866..acc3faa91b2043bb084ebb7c6e6188f6190d16d9 100644 --- a/crates/gpui/src/platform/windows/directx_renderer.rs +++ b/crates/gpui/src/platform/windows/directx_renderer.rs @@ -1282,11 +1282,15 @@ const BUFFER_COUNT: usize = 3; mod shader_resources { use anyhow::Result; - // use windows::Win32::Graphics::Direct3D::{ - // Fxc::{D3DCOMPILE_DEBUG, D3DCOMPILE_SKIP_OPTIMIZATION, D3DCompileFromFile}, - // ID3DBlob, - // }; - // use windows_core::{HSTRING, PCSTR}; + + #[cfg(debug_assertions)] + use windows::{ + Win32::Graphics::Direct3D::{ + Fxc::{D3DCOMPILE_DEBUG, D3DCOMPILE_SKIP_OPTIMIZATION, D3DCompileFromFile}, + ID3DBlob, + }, + core::{HSTRING, PCSTR}, + }; #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub(super) enum ShaderModule { @@ -1306,17 +1310,35 @@ mod shader_resources { pub(super) struct RawShaderBytes<'t> { inner: &'t [u8], + + #[cfg(debug_assertions)] + _blob: ID3DBlob, } impl<'t> RawShaderBytes<'t> { pub(super) fn new(module: ShaderModule, target: ShaderTarget) -> Result { - Ok(Self::from_bytes(module, target)) + #[cfg(not(debug_assertions))] + { + Ok(Self::from_bytes(module, target)) + } + #[cfg(debug_assertions)] + { + let blob = build_shader_blob(module, target)?; + let inner = unsafe { + std::slice::from_raw_parts( + blob.GetBufferPointer() as *const u8, + blob.GetBufferSize(), + ) + }; + Ok(Self { inner, _blob: blob }) + } } - pub(super) fn as_bytes(&self) -> &'t [u8] { + pub(super) fn as_bytes(&'t self) -> &'t [u8] { self.inner } + #[cfg(not(debug_assertions))] fn from_bytes(module: ShaderModule, target: ShaderTarget) -> Self { let bytes = match module { ShaderModule::Quad => match target { @@ -1348,32 +1370,38 @@ mod shader_resources { } } - #[cfg(not(debug_assertions))] - pub(super) fn build_shader_blob(entry: &str, target: &str) -> Result { + #[cfg(debug_assertions)] + pub(super) fn build_shader_blob(entry: ShaderModule, target: ShaderTarget) -> Result { unsafe { - let mut entry = entry.to_owned(); - let mut target = target.to_owned(); + let entry = format!( + "{}_{}\0", + entry.as_str(), + match target { + ShaderTarget::Vertex => "vertex", + ShaderTarget::Fragment => "fragment", + } + ); + let target = match target { + ShaderTarget::Vertex => "vs_5_0\0", + ShaderTarget::Fragment => "ps_5_0\0", + }; + let mut compile_blob = None; let mut error_blob = None; let shader_path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")) .join("src/platform/windows/shaders.hlsl") - .canonicalize() - .unwrap(); - entry.push_str("\0"); - target.push_str("\0"); + .canonicalize()?; + let entry_point = PCSTR::from_raw(entry.as_ptr()); let target_cstr = PCSTR::from_raw(target.as_ptr()); - #[cfg(debug_assertions)] - let compile_flag = D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION; - #[cfg(not(debug_assertions))] - let compile_flag = 0; + let ret = D3DCompileFromFile( &HSTRING::from(shader_path.to_str().unwrap()), None, None, entry_point, target_cstr, - compile_flag, + D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION, 0, &mut compile_blob, Some(&mut error_blob), @@ -1382,13 +1410,10 @@ mod shader_resources { let Some(error_blob) = error_blob else { return Err(anyhow::anyhow!("{ret:?}")); }; - let string_len = error_blob.GetBufferSize(); - let error_string_encode = Vec::from_raw_parts( - error_blob.GetBufferPointer() as *mut u8, - string_len, - string_len, - ); - let error_string = String::from_utf8_lossy(&error_string_encode).to_string(); + + let error_string = + std::ffi::CStr::from_ptr(error_blob.GetBufferPointer() as *const i8) + .to_string_lossy(); log::error!("Shader compile error: {}", error_string); return Err(anyhow::anyhow!("Compile error: {}", error_string)); } @@ -1396,10 +1421,12 @@ mod shader_resources { } } + #[cfg(not(debug_assertions))] include!(concat!(env!("OUT_DIR"), "/shaders_bytes.rs")); + #[cfg(debug_assertions)] impl ShaderModule { - pub fn as_str(&self) -> &'static str { + pub fn as_str(&self) -> &str { match self { ShaderModule::Quad => "quad", ShaderModule::Shadow => "shadow", @@ -1410,11 +1437,6 @@ mod shader_resources { } } } - - // pub fn quad_vertex_shader() -> &'static [u8] { - // unsafe { - // std::slice::from_raw_parts(g_quad_vertex.as_ptr() as *const u8, g_quad_vertex.len()) - // } } mod nvidia {