Вулкано шейдерная компиляция во время выполнения возможна? - PullRequest
0 голосов
/ 01 ноября 2018

Я использую Vulkano для создания простой 3D-графики. Как правило, я люблю писать свои шейдеры GLSL в тексте и перезапускать мою программу, или даже менять шейдеры во время работы программы. Представленные в Vulkano примеры, по-видимому, используют макрос для преобразования GLSL в некую форму шейдера на основе SPIR-V с прикрепленными функциями ржавчины, но GLSL фактически компилируется в двоичный файл (даже при использовании пути к файлу).

Мне удалось получить шейдерный ящик для сборки моего SPIR-V на лету:

let mut f = File::open("src/grafx/vert.glsl")
         .expect("Can't find file src/bin/runtime-shader/vert.glsl 
                This example needs to be run from the root of the example crate.");

 let mut source = String::new();
 f.read_to_string(&mut source);

 //let source = "#version 310 es\n void EP() {}";
 let mut compiler = shaderc::Compiler::new().unwrap();
 let mut options = shaderc::CompileOptions::new().unwrap();
 options.add_macro_definition("EP", Some("main"));
 let binary_result = compiler.compile_into_spirv(
 &source, shaderc::ShaderKind::Vertex,
 "shader.glsl", "main", Some(&options)).unwrap();
 assert_eq!(Some(&0x07230203), binary_result.as_binary().first());

 let text_result = compiler.compile_into_spirv_assembly(
     &source, shaderc::ShaderKind::Vertex,
     "shader.glsl", "main", Some(&options)).unwrap();

 assert!(text_result.as_text().starts_with("; SPIR-V\n"));
 //println!("Compiled Vertex Shader: {}", text_result.as_text());

 let vert_spirv = { 
     unsafe { ShaderModule::new(device.clone(), binary_result.as_binary_u8()) }.unwrap()
 };
vert_spirv

Пока все хорошо, у нас есть ShaderModule , который кажется первым шагом. Однако нам на самом деле нужен GraphicsEntryPoint , который мы можем затем вставить в нашу GraphicsPipeline . Очевидно, GraphicsPipeline - это то место, где мы объединяем наши шейдеры, треугольники и карты глубины и все эти прекрасные вещи.

Проблема в том, что я понятия не имею, что происходит с кодом, который выполняет это умение:

pub fn shade_vertex <'a, S> (vert_spirv: &'a Arc<ShaderModule>) ->

 GraphicsEntryPoint<'a, S, VertInput, VertOutput, VertLayout>  {
 let tn = unsafe {
     vert_spirv.graphics_entry_point(
         CStr::from_bytes_with_nul_unchecked(b"main\0"),
         VertInput,
         VertOutput,
         VertLayout(ShaderStages { vertex: true, ..ShaderStages::none() }),
         GraphicsShaderType::Vertex
     )
 };
 tn
}

В частности, что такое VertInput и VertOutput ? Я скопировал их из примера здесь: https://github.com/vulkano-rs/vulkano/blob/master/examples/src/bin/runtime-shader/main.rs

Это самый близкий пример, который я могу найти, который касается загрузки шейдеров на лету. Он выглядит как вход и выход ищут точки входа в SPIR-V или что-то в этом роде, но я понятия не имею, что с этим делать. Я надеюсь, что где-то в существующем макросе есть функция, которая позаботится об этом за меня. Я зашел так далеко, но я немного застрял.

Кто-нибудь еще пробовал загружать шейдеры во время выполнения?

...