fmt: run cargo fmt
This commit is contained in:
parent
47b5625095
commit
48321d997b
|
@ -158,8 +158,9 @@ impl LibrashaderError {
|
||||||
LibrashaderError::InvalidPath(_) => LIBRA_ERRNO::INVALID_PATH,
|
LibrashaderError::InvalidPath(_) => LIBRA_ERRNO::INVALID_PATH,
|
||||||
LibrashaderError::PresetError(_) => LIBRA_ERRNO::PRESET_ERROR,
|
LibrashaderError::PresetError(_) => LIBRA_ERRNO::PRESET_ERROR,
|
||||||
LibrashaderError::PreprocessError(_) => LIBRA_ERRNO::PREPROCESS_ERROR,
|
LibrashaderError::PreprocessError(_) => LIBRA_ERRNO::PREPROCESS_ERROR,
|
||||||
LibrashaderError::ShaderCompileError(_)
|
LibrashaderError::ShaderCompileError(_) | LibrashaderError::ShaderReflectError(_) => {
|
||||||
| LibrashaderError::ShaderReflectError(_) => LIBRA_ERRNO::RUNTIME_ERROR,
|
LIBRA_ERRNO::RUNTIME_ERROR
|
||||||
|
}
|
||||||
#[cfg(feature = "runtime-opengl")]
|
#[cfg(feature = "runtime-opengl")]
|
||||||
LibrashaderError::OpenGlFilterError(_) => LIBRA_ERRNO::RUNTIME_ERROR,
|
LibrashaderError::OpenGlFilterError(_) => LIBRA_ERRNO::RUNTIME_ERROR,
|
||||||
#[cfg(feature = "runtime-d3d11")]
|
#[cfg(feature = "runtime-d3d11")]
|
||||||
|
|
|
@ -44,5 +44,5 @@ pub mod ctypes;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
mod ffi;
|
mod ffi;
|
||||||
pub mod presets;
|
pub mod presets;
|
||||||
pub mod runtime;
|
|
||||||
pub mod reflect;
|
pub mod reflect;
|
||||||
|
pub mod runtime;
|
||||||
|
|
|
@ -1,13 +1,18 @@
|
||||||
use std::error::Error;
|
use crate::error;
|
||||||
use librashader::preprocess::ShaderSource;
|
use librashader::preprocess::ShaderSource;
|
||||||
use librashader::presets::{ShaderPassConfig, ShaderPreset, TextureConfig};
|
use librashader::presets::{ShaderPassConfig, ShaderPreset, TextureConfig};
|
||||||
use librashader::reflect::{CompilerBackend, CompileShader, FromCompilation, GlslangCompilation, ReflectShader, ShaderCompilerOutput, ShaderReflection};
|
use librashader::reflect::image::{Image, UVDirection, RGBA8};
|
||||||
use librashader::reflect::image::{Image, RGBA8, UVDirection};
|
use librashader::reflect::semantics::{
|
||||||
use librashader::reflect::semantics::{Semantic, ShaderSemantics, TextureSemantics, UniformSemantic, UniqueSemantics};
|
Semantic, ShaderSemantics, TextureSemantics, UniformSemantic, UniqueSemantics,
|
||||||
|
};
|
||||||
use librashader::reflect::targets::SpirV;
|
use librashader::reflect::targets::SpirV;
|
||||||
|
use librashader::reflect::{
|
||||||
|
CompileShader, CompilerBackend, FromCompilation, GlslangCompilation, ReflectShader,
|
||||||
|
ShaderCompilerOutput, ShaderReflection,
|
||||||
|
};
|
||||||
use librashader::{FilterMode, WrapMode};
|
use librashader::{FilterMode, WrapMode};
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use crate::error;
|
use std::error::Error;
|
||||||
|
|
||||||
pub(crate) struct LookupTexture {
|
pub(crate) struct LookupTexture {
|
||||||
wrap_mode: WrapMode,
|
wrap_mode: WrapMode,
|
||||||
|
@ -16,22 +21,25 @@ pub(crate) struct LookupTexture {
|
||||||
/// Whether or not to generate mipmaps for this texture.
|
/// Whether or not to generate mipmaps for this texture.
|
||||||
mipmap: bool,
|
mipmap: bool,
|
||||||
/// The image data of the texture
|
/// The image data of the texture
|
||||||
image: Image
|
image: Image,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct PassReflection {
|
pub(crate) struct PassReflection {
|
||||||
reflection: ShaderReflection,
|
reflection: ShaderReflection,
|
||||||
config: ShaderPassConfig,
|
config: ShaderPassConfig,
|
||||||
spirv: ShaderCompilerOutput<Vec<u32>>
|
spirv: ShaderCompilerOutput<Vec<u32>>,
|
||||||
}
|
}
|
||||||
pub(crate) struct FilterReflection {
|
pub(crate) struct FilterReflection {
|
||||||
semantics: ShaderSemantics,
|
semantics: ShaderSemantics,
|
||||||
passes: Vec<PassReflection>,
|
passes: Vec<PassReflection>,
|
||||||
textures: Vec<LookupTexture>
|
textures: Vec<LookupTexture>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FilterReflection {
|
impl FilterReflection {
|
||||||
pub fn load_from_preset(preset: ShaderPreset, direction: UVDirection) -> Result<FilterReflection, error::LibrashaderError>{
|
pub fn load_from_preset(
|
||||||
|
preset: ShaderPreset,
|
||||||
|
direction: UVDirection,
|
||||||
|
) -> Result<FilterReflection, error::LibrashaderError> {
|
||||||
let (passes, textures) = (preset.shaders, preset.textures);
|
let (passes, textures) = (preset.shaders, preset.textures);
|
||||||
let mut uniform_semantics: FxHashMap<String, UniformSemantic> = Default::default();
|
let mut uniform_semantics: FxHashMap<String, UniformSemantic> = Default::default();
|
||||||
let mut texture_semantics: FxHashMap<String, Semantic<TextureSemantics>> =
|
let mut texture_semantics: FxHashMap<String, Semantic<TextureSemantics>> =
|
||||||
|
@ -59,7 +67,10 @@ impl FilterReflection {
|
||||||
Ok::<_, error::LibrashaderError>((shader, source, reflect))
|
Ok::<_, error::LibrashaderError>((shader, source, reflect))
|
||||||
})
|
})
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect::<Result<Vec<(ShaderPassConfig, ShaderSource, CompilerBackend<_>)>, error::LibrashaderError>>()?;
|
.collect::<Result<
|
||||||
|
Vec<(ShaderPassConfig, ShaderSource, CompilerBackend<_>)>,
|
||||||
|
error::LibrashaderError,
|
||||||
|
>>()?;
|
||||||
|
|
||||||
for details in &passes {
|
for details in &passes {
|
||||||
librashader::runtime::helper::insert_pass_semantics(
|
librashader::runtime::helper::insert_pass_semantics(
|
||||||
|
@ -80,7 +91,6 @@ impl FilterReflection {
|
||||||
texture_semantics,
|
texture_semantics,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
let mut reflects = Vec::new();
|
let mut reflects = Vec::new();
|
||||||
|
|
||||||
for (index, (config, _source, mut compiler)) in passes.into_iter().enumerate() {
|
for (index, (config, _source, mut compiler)) in passes.into_iter().enumerate() {
|
||||||
|
@ -89,21 +99,24 @@ impl FilterReflection {
|
||||||
reflects.push(PassReflection {
|
reflects.push(PassReflection {
|
||||||
reflection,
|
reflection,
|
||||||
config,
|
config,
|
||||||
spirv: words
|
spirv: words,
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let textures = textures.into_iter().map(|texture| {
|
let textures = textures
|
||||||
let lut = Image::<RGBA8>::load(&texture.path, direction)
|
.into_iter()
|
||||||
.map_err(|e| error::LibrashaderError::UnknownError(Box::new(e)))?;
|
.map(|texture| {
|
||||||
Ok(LookupTexture {
|
let lut = Image::<RGBA8>::load(&texture.path, direction)
|
||||||
wrap_mode: texture.wrap_mode,
|
.map_err(|e| error::LibrashaderError::UnknownError(Box::new(e)))?;
|
||||||
filter_mode: texture.filter_mode,
|
Ok(LookupTexture {
|
||||||
mipmap: texture.mipmap,
|
wrap_mode: texture.wrap_mode,
|
||||||
image: lut,
|
filter_mode: texture.filter_mode,
|
||||||
|
mipmap: texture.mipmap,
|
||||||
|
image: lut,
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}).into_iter().collect::<Result<Vec<LookupTexture>, error::LibrashaderError>>()?;
|
.into_iter()
|
||||||
|
.collect::<Result<Vec<LookupTexture>, error::LibrashaderError>>()?;
|
||||||
|
|
||||||
Ok(FilterReflection {
|
Ok(FilterReflection {
|
||||||
semantics,
|
semantics,
|
||||||
|
@ -111,4 +124,4 @@ impl FilterReflection {
|
||||||
textures,
|
textures,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -123,22 +123,20 @@ impl From<&vk::Viewport> for Size<u32> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl From<FilterMode> for vk::Filter {
|
impl From<FilterMode> for vk::Filter {
|
||||||
fn from(value: FilterMode) -> Self {
|
fn from(value: FilterMode) -> Self {
|
||||||
match value {
|
match value {
|
||||||
FilterMode::Linear => vk::Filter::LINEAR,
|
FilterMode::Linear => vk::Filter::LINEAR,
|
||||||
FilterMode::Nearest => vk::Filter::NEAREST
|
FilterMode::Nearest => vk::Filter::NEAREST,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl From<FilterMode> for vk::SamplerMipmapMode {
|
impl From<FilterMode> for vk::SamplerMipmapMode {
|
||||||
fn from(value: FilterMode) -> Self {
|
fn from(value: FilterMode) -> Self {
|
||||||
match value {
|
match value {
|
||||||
FilterMode::Linear => vk::SamplerMipmapMode::LINEAR,
|
FilterMode::Linear => vk::SamplerMipmapMode::LINEAR,
|
||||||
FilterMode::Nearest => vk::SamplerMipmapMode::NEAREST
|
FilterMode::Nearest => vk::SamplerMipmapMode::NEAREST,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -149,7 +147,7 @@ impl From<WrapMode> for vk::SamplerAddressMode {
|
||||||
WrapMode::ClampToBorder => vk::SamplerAddressMode::CLAMP_TO_BORDER,
|
WrapMode::ClampToBorder => vk::SamplerAddressMode::CLAMP_TO_BORDER,
|
||||||
WrapMode::ClampToEdge => vk::SamplerAddressMode::CLAMP_TO_EDGE,
|
WrapMode::ClampToEdge => vk::SamplerAddressMode::CLAMP_TO_EDGE,
|
||||||
WrapMode::Repeat => vk::SamplerAddressMode::REPEAT,
|
WrapMode::Repeat => vk::SamplerAddressMode::REPEAT,
|
||||||
WrapMode::MirroredRepeat => vk::SamplerAddressMode::MIRRORED_REPEAT
|
WrapMode::MirroredRepeat => vk::SamplerAddressMode::MIRRORED_REPEAT,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use ash::vk;
|
|
||||||
use crate::error;
|
use crate::error;
|
||||||
use crate::vulkan_primitives::VulkanBuffer;
|
use crate::vulkan_primitives::VulkanBuffer;
|
||||||
|
use ash::vk;
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
static VBO_OFFSCREEN: &[f32; 16] = &[
|
static VBO_OFFSCREEN: &[f32; 16] = &[
|
||||||
|
@ -22,39 +22,55 @@ static VBO_DEFAULT_FINAL: &[f32; 16] = &[
|
||||||
|
|
||||||
pub enum VboType {
|
pub enum VboType {
|
||||||
Offscreen,
|
Offscreen,
|
||||||
Final
|
Final,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DrawQuad {
|
pub struct DrawQuad {
|
||||||
buffer: VulkanBuffer,
|
buffer: VulkanBuffer,
|
||||||
device: ash::Device
|
device: ash::Device,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DrawQuad {
|
impl DrawQuad {
|
||||||
pub fn new(device: &ash::Device, mem_props: &vk::PhysicalDeviceMemoryProperties) -> error::Result<DrawQuad> {
|
pub fn new(
|
||||||
let mut buffer = VulkanBuffer::new(device, mem_props, vk::BufferUsageFlags::VERTEX_BUFFER, 2 * std::mem::size_of::<[f32; 16]>())?;
|
device: &ash::Device,
|
||||||
|
mem_props: &vk::PhysicalDeviceMemoryProperties,
|
||||||
|
) -> error::Result<DrawQuad> {
|
||||||
|
let mut buffer = VulkanBuffer::new(
|
||||||
|
device,
|
||||||
|
mem_props,
|
||||||
|
vk::BufferUsageFlags::VERTEX_BUFFER,
|
||||||
|
2 * std::mem::size_of::<[f32; 16]>(),
|
||||||
|
)?;
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut map = buffer.map()?;
|
let mut map = buffer.map()?;
|
||||||
unsafe {
|
unsafe {
|
||||||
map.copy_from(0, bytemuck::cast_slice(VBO_OFFSCREEN));
|
map.copy_from(0, bytemuck::cast_slice(VBO_OFFSCREEN));
|
||||||
map.copy_from(std::mem::size_of::<[f32; 16]>(), bytemuck::cast_slice(VBO_DEFAULT_FINAL));
|
map.copy_from(
|
||||||
|
std::mem::size_of::<[f32; 16]>(),
|
||||||
|
bytemuck::cast_slice(VBO_DEFAULT_FINAL),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(DrawQuad {
|
Ok(DrawQuad {
|
||||||
buffer,
|
buffer,
|
||||||
device: device.clone()
|
device: device.clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bind_vbo(&self, cmd: &vk::CommandBuffer, vbo: VboType) {
|
pub fn bind_vbo(&self, cmd: &vk::CommandBuffer, vbo: VboType) {
|
||||||
let offset = match vbo {
|
let offset = match vbo {
|
||||||
VboType::Offscreen => 0,
|
VboType::Offscreen => 0,
|
||||||
VboType::Final => std::mem::size_of::<[f32; 16]>()
|
VboType::Final => std::mem::size_of::<[f32; 16]>(),
|
||||||
};
|
};
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
self.device.cmd_bind_vertex_buffers(*cmd, 0, &[self.buffer.handle], &[offset as vk::DeviceSize])
|
self.device.cmd_bind_vertex_buffers(
|
||||||
|
*cmd,
|
||||||
|
0,
|
||||||
|
&[self.buffer.handle],
|
||||||
|
&[offset as vk::DeviceSize],
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
use crate::error;
|
use crate::error;
|
||||||
use crate::filter_pass::FilterPass;
|
use crate::filter_pass::FilterPass;
|
||||||
use crate::luts::LutTexture;
|
use crate::luts::LutTexture;
|
||||||
|
use crate::samplers::SamplerSet;
|
||||||
|
use crate::texture::VulkanImage;
|
||||||
|
use crate::ubo_ring::VkUboRing;
|
||||||
use crate::vulkan_state::VulkanGraphicsPipeline;
|
use crate::vulkan_state::VulkanGraphicsPipeline;
|
||||||
use ash::vk::{CommandPoolCreateFlags, PFN_vkGetInstanceProcAddr, Queue, StaticFn};
|
use ash::vk::{CommandPoolCreateFlags, PFN_vkGetInstanceProcAddr, Queue, StaticFn};
|
||||||
use ash::{vk, Device};
|
use ash::{vk, Device};
|
||||||
|
@ -19,9 +22,6 @@ use librashader_runtime::uniforms::UniformStorage;
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use crate::samplers::SamplerSet;
|
|
||||||
use crate::texture::VulkanImage;
|
|
||||||
use crate::ubo_ring::VkUboRing;
|
|
||||||
|
|
||||||
pub struct Vulkan {
|
pub struct Vulkan {
|
||||||
// physical_device: vk::PhysicalDevice,
|
// physical_device: vk::PhysicalDevice,
|
||||||
|
@ -149,7 +149,7 @@ pub type FilterChainOptionsVulkan = ();
|
||||||
impl FilterChainVulkan {
|
impl FilterChainVulkan {
|
||||||
/// Load the shader preset at the given path into a filter chain.
|
/// Load the shader preset at the given path into a filter chain.
|
||||||
pub fn load_from_path(
|
pub fn load_from_path(
|
||||||
vulkan: impl TryInto<Vulkan, Error=Box<dyn Error>>,
|
vulkan: impl TryInto<Vulkan, Error = Box<dyn Error>>,
|
||||||
path: impl AsRef<Path>,
|
path: impl AsRef<Path>,
|
||||||
options: Option<&FilterChainOptionsVulkan>,
|
options: Option<&FilterChainOptionsVulkan>,
|
||||||
) -> error::Result<FilterChainVulkan> {
|
) -> error::Result<FilterChainVulkan> {
|
||||||
|
@ -159,7 +159,7 @@ impl FilterChainVulkan {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_from_preset(
|
pub fn load_from_preset(
|
||||||
vulkan: impl TryInto<Vulkan, Error=Box<dyn Error>>,
|
vulkan: impl TryInto<Vulkan, Error = Box<dyn Error>>,
|
||||||
preset: ShaderPreset,
|
preset: ShaderPreset,
|
||||||
options: Option<&FilterChainOptionsVulkan>,
|
options: Option<&FilterChainOptionsVulkan>,
|
||||||
) -> error::Result<FilterChainVulkan> {
|
) -> error::Result<FilterChainVulkan> {
|
||||||
|
@ -172,7 +172,6 @@ impl FilterChainVulkan {
|
||||||
let luts = FilterChainVulkan::load_luts(&device, &preset.textures)?;
|
let luts = FilterChainVulkan::load_luts(&device, &preset.textures)?;
|
||||||
let samplers = SamplerSet::new(&device.device)?;
|
let samplers = SamplerSet::new(&device.device)?;
|
||||||
|
|
||||||
|
|
||||||
eprintln!("filters initialized ok.");
|
eprintln!("filters initialized ok.");
|
||||||
Ok(FilterChainVulkan {
|
Ok(FilterChainVulkan {
|
||||||
common: FilterCommon {
|
common: FilterCommon {
|
||||||
|
@ -188,7 +187,7 @@ impl FilterChainVulkan {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
passes: filters,
|
passes: filters,
|
||||||
vulkan: device
|
vulkan: device,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,7 +220,8 @@ impl FilterChainVulkan {
|
||||||
Ok::<_, Box<dyn Error>>((shader, source, reflect))
|
Ok::<_, Box<dyn Error>>((shader, source, reflect))
|
||||||
})
|
})
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect::<error::Result<Vec<(ShaderPassConfig, ShaderSource, CompilerBackend<_>)>>>()?;
|
.collect::<error::Result<Vec<(ShaderPassConfig, ShaderSource, CompilerBackend<_>)>>>(
|
||||||
|
)?;
|
||||||
|
|
||||||
for details in &passes {
|
for details in &passes {
|
||||||
librashader_runtime::semantics::insert_pass_semantics(
|
librashader_runtime::semantics::insert_pass_semantics(
|
||||||
|
@ -262,7 +262,8 @@ impl FilterChainVulkan {
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|ubo| ubo.size as usize)
|
.map(|ubo| ubo.size as usize)
|
||||||
.unwrap_or(0);
|
.unwrap_or(0);
|
||||||
let uniform_storage = UniformStorage::new(ubo_size,
|
let uniform_storage = UniformStorage::new(
|
||||||
|
ubo_size,
|
||||||
reflection
|
reflection
|
||||||
.push_constant
|
.push_constant
|
||||||
.as_ref()
|
.as_ref()
|
||||||
|
@ -298,7 +299,12 @@ impl FilterChainVulkan {
|
||||||
images,
|
images,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let ubo_ring = VkUboRing::new(&vulkan.device, &vulkan.memory_properties, images as usize, ubo_size)?;
|
let ubo_ring = VkUboRing::new(
|
||||||
|
&vulkan.device,
|
||||||
|
&vulkan.memory_properties,
|
||||||
|
images as usize,
|
||||||
|
ubo_size,
|
||||||
|
)?;
|
||||||
// shader_vulkan: 2026
|
// shader_vulkan: 2026
|
||||||
filters.push(FilterPass {
|
filters.push(FilterPass {
|
||||||
device: vulkan.device.clone(),
|
device: vulkan.device.clone(),
|
||||||
|
@ -374,7 +380,7 @@ impl FilterChainVulkan {
|
||||||
viewport: &vk::Viewport,
|
viewport: &vk::Viewport,
|
||||||
input: &VulkanImage,
|
input: &VulkanImage,
|
||||||
options: Option<()>,
|
options: Option<()>,
|
||||||
command_buffer: vk::CommandBuffer
|
command_buffer: vk::CommandBuffer,
|
||||||
) -> error::Result<()> {
|
) -> error::Result<()> {
|
||||||
// limit number of passes to those enabled.
|
// limit number of passes to those enabled.
|
||||||
let passes = &mut self.passes[0..self.common.config.passes_enabled];
|
let passes = &mut self.passes[0..self.common.config.passes_enabled];
|
||||||
|
@ -394,6 +400,5 @@ impl FilterChainVulkan {
|
||||||
// }
|
// }
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,21 @@
|
||||||
use ash::vk;
|
|
||||||
use crate::vulkan_state::VulkanGraphicsPipeline;
|
|
||||||
use librashader_preprocess::ShaderSource;
|
|
||||||
use librashader_presets::ShaderPassConfig;
|
|
||||||
use librashader_reflect::back::ShaderCompilerOutput;
|
|
||||||
use librashader_reflect::reflect::semantics::{MemberOffset, TextureBinding, TextureSemantics, UniformBinding, UniqueSemantics};
|
|
||||||
use librashader_runtime::uniforms::UniformStorage;
|
|
||||||
use rustc_hash::FxHashMap;
|
|
||||||
use librashader_common::Size;
|
|
||||||
use librashader_reflect::reflect::ShaderReflection;
|
|
||||||
use crate::error;
|
use crate::error;
|
||||||
use crate::filter_chain::FilterCommon;
|
use crate::filter_chain::FilterCommon;
|
||||||
use crate::rendertarget::RenderTarget;
|
use crate::rendertarget::RenderTarget;
|
||||||
use crate::texture::Texture;
|
|
||||||
use crate::samplers::{SamplerSet, VulkanSampler};
|
use crate::samplers::{SamplerSet, VulkanSampler};
|
||||||
|
use crate::texture::Texture;
|
||||||
use crate::ubo_ring::VkUboRing;
|
use crate::ubo_ring::VkUboRing;
|
||||||
|
use crate::vulkan_state::VulkanGraphicsPipeline;
|
||||||
|
use ash::vk;
|
||||||
|
use librashader_common::Size;
|
||||||
|
use librashader_preprocess::ShaderSource;
|
||||||
|
use librashader_presets::ShaderPassConfig;
|
||||||
|
use librashader_reflect::back::ShaderCompilerOutput;
|
||||||
|
use librashader_reflect::reflect::semantics::{
|
||||||
|
MemberOffset, TextureBinding, TextureSemantics, UniformBinding, UniqueSemantics,
|
||||||
|
};
|
||||||
|
use librashader_reflect::reflect::ShaderReflection;
|
||||||
|
use librashader_runtime::uniforms::UniformStorage;
|
||||||
|
use rustc_hash::FxHashMap;
|
||||||
|
|
||||||
pub struct FilterPass {
|
pub struct FilterPass {
|
||||||
pub device: ash::Device,
|
pub device: ash::Device,
|
||||||
|
@ -24,18 +26,18 @@ pub struct FilterPass {
|
||||||
pub source: ShaderSource,
|
pub source: ShaderSource,
|
||||||
pub config: ShaderPassConfig,
|
pub config: ShaderPassConfig,
|
||||||
pub graphics_pipeline: VulkanGraphicsPipeline,
|
pub graphics_pipeline: VulkanGraphicsPipeline,
|
||||||
pub ubo_ring: VkUboRing
|
pub ubo_ring: VkUboRing,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl FilterPass {
|
impl FilterPass {
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn bind_texture(device: &ash::Device,
|
fn bind_texture(
|
||||||
samplers: &SamplerSet,
|
device: &ash::Device,
|
||||||
descriptor_set: vk::DescriptorSet,
|
samplers: &SamplerSet,
|
||||||
binding: &TextureBinding,
|
descriptor_set: vk::DescriptorSet,
|
||||||
texture: &Texture) {
|
binding: &TextureBinding,
|
||||||
|
texture: &Texture,
|
||||||
|
) {
|
||||||
let sampler = samplers.get(texture.wrap_mode, texture.filter_mode, texture.mip_filter);
|
let sampler = samplers.get(texture.wrap_mode, texture.filter_mode, texture.mip_filter);
|
||||||
let image_info = [vk::DescriptorImageInfo::builder()
|
let image_info = [vk::DescriptorImageInfo::builder()
|
||||||
.sampler(sampler.handle)
|
.sampler(sampler.handle)
|
||||||
|
@ -53,7 +55,6 @@ impl FilterPass {
|
||||||
unsafe {
|
unsafe {
|
||||||
device.update_descriptor_sets(&write_desc, &[]);
|
device.update_descriptor_sets(&write_desc, &[]);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn draw(
|
pub(crate) fn draw(
|
||||||
|
@ -70,13 +71,24 @@ impl FilterPass {
|
||||||
) -> error::Result<()> {
|
) -> error::Result<()> {
|
||||||
let descriptor = *&self.graphics_pipeline.layout.descriptor_sets[0];
|
let descriptor = *&self.graphics_pipeline.layout.descriptor_sets[0];
|
||||||
|
|
||||||
self.build_semantics(pass_index, parent, &output.mvp, frame_count, frame_direction, output.output.size,
|
self.build_semantics(
|
||||||
viewport.into(),&descriptor, original, source);
|
pass_index,
|
||||||
|
parent,
|
||||||
|
&output.mvp,
|
||||||
|
frame_count,
|
||||||
|
frame_direction,
|
||||||
|
output.output.size,
|
||||||
|
viewport.into(),
|
||||||
|
&descriptor,
|
||||||
|
original,
|
||||||
|
source,
|
||||||
|
);
|
||||||
|
|
||||||
if let Some(ubo) = &self.reflection.ubo {
|
if let Some(ubo) = &self.reflection.ubo {
|
||||||
// shader_vulkan: 2554 (ra uses uses one big buffer)
|
// shader_vulkan: 2554 (ra uses uses one big buffer)
|
||||||
// itll be simpler for us if we just use a RingBuffer<vk::Buffer> tbh.
|
// itll be simpler for us if we just use a RingBuffer<vk::Buffer> tbh.
|
||||||
self.ubo_ring.bind_to_descriptor_set(descriptor, ubo.binding, &self.uniform_storage)?;
|
self.ubo_ring
|
||||||
|
.bind_to_descriptor_set(descriptor, ubo.binding, &self.uniform_storage)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -172,7 +184,7 @@ impl FilterPass {
|
||||||
&parent.samplers,
|
&parent.samplers,
|
||||||
*descriptor_set,
|
*descriptor_set,
|
||||||
binding,
|
binding,
|
||||||
source
|
source,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -301,12 +313,12 @@ impl FilterPass {
|
||||||
|
|
||||||
// bind float parameters
|
// bind float parameters
|
||||||
for (id, offset) in
|
for (id, offset) in
|
||||||
self.uniform_bindings
|
self.uniform_bindings
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|(binding, value)| match binding {
|
.filter_map(|(binding, value)| match binding {
|
||||||
UniformBinding::Parameter(id) => Some((id, value)),
|
UniformBinding::Parameter(id) => Some((id, value)),
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
let id = id.as_str();
|
let id = id.as_str();
|
||||||
|
|
||||||
|
@ -351,4 +363,4 @@ impl FilterPass {
|
||||||
|
|
||||||
// (textures, samplers)
|
// (textures, samplers)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
use crate::error;
|
use crate::error;
|
||||||
use crate::renderpass::VulkanRenderPass;
|
|
||||||
use ash::vk;
|
|
||||||
use ash::vk::{
|
|
||||||
ImageAspectFlags,
|
|
||||||
ImageViewType,
|
|
||||||
};
|
|
||||||
use librashader_common::Size;
|
|
||||||
use crate::filter_chain::Vulkan;
|
use crate::filter_chain::Vulkan;
|
||||||
|
use crate::renderpass::VulkanRenderPass;
|
||||||
use crate::texture::OwnedTexture;
|
use crate::texture::OwnedTexture;
|
||||||
|
use ash::vk;
|
||||||
|
use ash::vk::{ImageAspectFlags, ImageViewType};
|
||||||
|
use librashader_common::Size;
|
||||||
|
|
||||||
pub struct VulkanFramebuffer {
|
pub struct VulkanFramebuffer {
|
||||||
pub device: ash::Device,
|
pub device: ash::Device,
|
||||||
|
@ -74,7 +71,6 @@ pub(crate) struct OutputFramebuffer {
|
||||||
pub viewport: vk::Viewport,
|
pub viewport: vk::Viewport,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// pub struct OutputFramebuffer<'a> {
|
// pub struct OutputFramebuffer<'a> {
|
||||||
// device: ash::Device,
|
// device: ash::Device,
|
||||||
|
@ -147,4 +143,4 @@ pub(crate) struct OutputFramebuffer {
|
||||||
//
|
//
|
||||||
// builder.build()
|
// builder.build()
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
use ash::prelude::VkResult;
|
|
||||||
use ash::vk;
|
|
||||||
use crate::hello_triangle::physicaldevice::find_queue_family;
|
use crate::hello_triangle::physicaldevice::find_queue_family;
|
||||||
use crate::hello_triangle::vulkan_base::VulkanBase;
|
use crate::hello_triangle::vulkan_base::VulkanBase;
|
||||||
|
use ash::prelude::VkResult;
|
||||||
|
use ash::vk;
|
||||||
|
|
||||||
pub struct VulkanCommandPool {
|
pub struct VulkanCommandPool {
|
||||||
pool: vk::CommandPool,
|
pool: vk::CommandPool,
|
||||||
device: ash::Device,
|
device: ash::Device,
|
||||||
pub buffers: Vec<vk::CommandBuffer>
|
pub buffers: Vec<vk::CommandBuffer>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VulkanCommandPool {
|
impl VulkanCommandPool {
|
||||||
|
@ -34,5 +34,4 @@ impl VulkanCommandPool {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|
|
@ -5,11 +5,15 @@ use ash::vk::{DebugUtilsMessengerEXT, PFN_vkDebugUtilsMessengerCallbackEXT};
|
||||||
|
|
||||||
pub struct VulkanDebug {
|
pub struct VulkanDebug {
|
||||||
loader: DebugUtils,
|
loader: DebugUtils,
|
||||||
messenger: DebugUtilsMessengerEXT
|
messenger: DebugUtilsMessengerEXT,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VulkanDebug {
|
impl VulkanDebug {
|
||||||
pub fn new(entry: &ash::Entry, instance: &ash::Instance, callback: PFN_vkDebugUtilsMessengerCallbackEXT) -> VkResult<VulkanDebug>{
|
pub fn new(
|
||||||
|
entry: &ash::Entry,
|
||||||
|
instance: &ash::Instance,
|
||||||
|
callback: PFN_vkDebugUtilsMessengerCallbackEXT,
|
||||||
|
) -> VkResult<VulkanDebug> {
|
||||||
let debug_info = vk::DebugUtilsMessengerCreateInfoEXT::builder()
|
let debug_info = vk::DebugUtilsMessengerCreateInfoEXT::builder()
|
||||||
.message_severity(
|
.message_severity(
|
||||||
vk::DebugUtilsMessageSeverityFlagsEXT::ERROR
|
vk::DebugUtilsMessageSeverityFlagsEXT::ERROR
|
||||||
|
@ -26,12 +30,12 @@ impl VulkanDebug {
|
||||||
let debug_utils_loader = DebugUtils::new(entry, instance);
|
let debug_utils_loader = DebugUtils::new(entry, instance);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let debug_call_back = debug_utils_loader
|
let debug_call_back =
|
||||||
.create_debug_utils_messenger(&debug_info, None)?;
|
debug_utils_loader.create_debug_utils_messenger(&debug_info, None)?;
|
||||||
|
|
||||||
Ok(VulkanDebug {
|
Ok(VulkanDebug {
|
||||||
loader: debug_utils_loader,
|
loader: debug_utils_loader,
|
||||||
messenger: debug_call_back
|
messenger: debug_call_back,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,7 +44,8 @@ impl VulkanDebug {
|
||||||
impl Drop for VulkanDebug {
|
impl Drop for VulkanDebug {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
self.loader.destroy_debug_utils_messenger(self.messenger, None);
|
self.loader
|
||||||
|
.destroy_debug_utils_messenger(self.messenger, None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,19 @@
|
||||||
|
use crate::hello_triangle::swapchain::VulkanSwapchain;
|
||||||
use ash::prelude::VkResult;
|
use ash::prelude::VkResult;
|
||||||
use ash::vk;
|
use ash::vk;
|
||||||
use crate::hello_triangle::swapchain::VulkanSwapchain;
|
|
||||||
|
|
||||||
pub struct VulkanFramebuffer {
|
pub struct VulkanFramebuffer {
|
||||||
pub framebuffer: vk::Framebuffer,
|
pub framebuffer: vk::Framebuffer,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VulkanFramebuffer {
|
impl VulkanFramebuffer {
|
||||||
pub fn new(device: &ash::Device, image_view: &vk::ImageView, render_pass: &vk::RenderPass, width: u32, height: u32) -> VkResult<VulkanFramebuffer> {
|
pub fn new(
|
||||||
|
device: &ash::Device,
|
||||||
|
image_view: &vk::ImageView,
|
||||||
|
render_pass: &vk::RenderPass,
|
||||||
|
width: u32,
|
||||||
|
height: u32,
|
||||||
|
) -> VkResult<VulkanFramebuffer> {
|
||||||
let attachments = &[*image_view];
|
let attachments = &[*image_view];
|
||||||
let framebuffer_info = vk::FramebufferCreateInfo::builder()
|
let framebuffer_info = vk::FramebufferCreateInfo::builder()
|
||||||
.render_pass(*render_pass)
|
.render_pass(*render_pass)
|
||||||
|
@ -19,9 +25,7 @@ impl VulkanFramebuffer {
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let framebuffer = device.create_framebuffer(&framebuffer_info, None)?;
|
let framebuffer = device.create_framebuffer(&framebuffer_info, None)?;
|
||||||
Ok(VulkanFramebuffer {
|
Ok(VulkanFramebuffer { framebuffer })
|
||||||
framebuffer
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,13 @@
|
||||||
pub mod vulkan_base;
|
mod command;
|
||||||
mod debug;
|
mod debug;
|
||||||
|
mod framebuffer;
|
||||||
mod physicaldevice;
|
mod physicaldevice;
|
||||||
|
mod pipeline;
|
||||||
mod surface;
|
mod surface;
|
||||||
mod swapchain;
|
mod swapchain;
|
||||||
mod pipeline;
|
|
||||||
mod framebuffer;
|
|
||||||
mod command;
|
|
||||||
mod syncobjects;
|
mod syncobjects;
|
||||||
|
pub mod vulkan_base;
|
||||||
|
|
||||||
use ash::vk;
|
|
||||||
use ash::vk::RenderingInfo;
|
|
||||||
use winit::event::{Event, VirtualKeyCode, ElementState, KeyboardInput, WindowEvent};
|
|
||||||
use winit::event_loop::{EventLoop, ControlFlow, EventLoopBuilder};
|
|
||||||
use winit::platform::windows::EventLoopBuilderExtWindows;
|
|
||||||
use crate::filter_chain::{FilterChainVulkan, Vulkan};
|
use crate::filter_chain::{FilterChainVulkan, Vulkan};
|
||||||
use crate::hello_triangle::command::VulkanCommandPool;
|
use crate::hello_triangle::command::VulkanCommandPool;
|
||||||
use crate::hello_triangle::framebuffer::VulkanFramebuffer;
|
use crate::hello_triangle::framebuffer::VulkanFramebuffer;
|
||||||
|
@ -22,6 +17,11 @@ use crate::hello_triangle::swapchain::VulkanSwapchain;
|
||||||
use crate::hello_triangle::syncobjects::SyncObjects;
|
use crate::hello_triangle::syncobjects::SyncObjects;
|
||||||
use crate::hello_triangle::vulkan_base::VulkanBase;
|
use crate::hello_triangle::vulkan_base::VulkanBase;
|
||||||
use crate::util;
|
use crate::util;
|
||||||
|
use ash::vk;
|
||||||
|
use ash::vk::RenderingInfo;
|
||||||
|
use winit::event::{ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent};
|
||||||
|
use winit::event_loop::{ControlFlow, EventLoop, EventLoopBuilder};
|
||||||
|
use winit::platform::windows::EventLoopBuilderExtWindows;
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
const WINDOW_TITLE: &'static str = "librashader Vulkan";
|
const WINDOW_TITLE: &'static str = "librashader Vulkan";
|
||||||
|
@ -40,49 +40,49 @@ impl VulkanWindow {
|
||||||
.expect("Failed to create window.")
|
.expect("Failed to create window.")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn main_loop(event_loop: EventLoop<()>, window: winit::window::Window, vulkan: VulkanDraw, mut filter_chain: FilterChainVulkan) {
|
pub fn main_loop(
|
||||||
event_loop.run(move |event, _, control_flow| {
|
event_loop: EventLoop<()>,
|
||||||
match event {
|
window: winit::window::Window,
|
||||||
| Event::WindowEvent { event, .. } => {
|
vulkan: VulkanDraw,
|
||||||
match event {
|
mut filter_chain: FilterChainVulkan,
|
||||||
| WindowEvent::CloseRequested => {
|
) {
|
||||||
|
event_loop.run(move |event, _, control_flow| match event {
|
||||||
|
Event::WindowEvent { event, .. } => match event {
|
||||||
|
WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
|
||||||
|
WindowEvent::KeyboardInput { input, .. } => match input {
|
||||||
|
KeyboardInput {
|
||||||
|
virtual_keycode,
|
||||||
|
state,
|
||||||
|
..
|
||||||
|
} => match (virtual_keycode, state) {
|
||||||
|
(Some(VirtualKeyCode::Escape), ElementState::Pressed) => {
|
||||||
*control_flow = ControlFlow::Exit
|
*control_flow = ControlFlow::Exit
|
||||||
},
|
}
|
||||||
| WindowEvent::KeyboardInput { input, .. } => {
|
_ => {}
|
||||||
match input {
|
},
|
||||||
| KeyboardInput { virtual_keycode, state, .. } => {
|
|
||||||
match (virtual_keycode, state) {
|
|
||||||
| (Some(VirtualKeyCode::Escape), ElementState::Pressed) => {
|
|
||||||
*control_flow = ControlFlow::Exit
|
|
||||||
},
|
|
||||||
| _ => {},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
| _ => {},
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
| Event::MainEventsCleared => {
|
_ => {}
|
||||||
window.request_redraw();
|
},
|
||||||
},
|
Event::MainEventsCleared => {
|
||||||
| Event::RedrawRequested(_window_id) => {
|
window.request_redraw();
|
||||||
VulkanWindow::draw_frame(&vulkan, &mut filter_chain);
|
|
||||||
},
|
|
||||||
_ => (),
|
|
||||||
}
|
}
|
||||||
|
Event::RedrawRequested(_window_id) => {
|
||||||
|
VulkanWindow::draw_frame(&vulkan, &mut filter_chain);
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn record_command_buffer(vulkan: &VulkanDraw, framebuffer: vk::Framebuffer, cmd: vk::CommandBuffer) {
|
unsafe fn record_command_buffer(
|
||||||
let clear_values = [
|
vulkan: &VulkanDraw,
|
||||||
vk::ClearValue {
|
framebuffer: vk::Framebuffer,
|
||||||
color: vk::ClearColorValue {
|
cmd: vk::CommandBuffer,
|
||||||
float32: [0.3, 0.3, 0.5, 0.0],
|
) {
|
||||||
},
|
let clear_values = [vk::ClearValue {
|
||||||
|
color: vk::ClearColorValue {
|
||||||
|
float32: [0.3, 0.3, 0.5, 0.0],
|
||||||
},
|
},
|
||||||
];
|
}];
|
||||||
|
|
||||||
let render_pass_begin = vk::RenderPassBeginInfo::builder()
|
let render_pass_begin = vk::RenderPassBeginInfo::builder()
|
||||||
.render_pass(vulkan.pipeline.renderpass)
|
.render_pass(vulkan.pipeline.renderpass)
|
||||||
|
@ -94,51 +94,76 @@ impl VulkanWindow {
|
||||||
.clear_values(&clear_values)
|
.clear_values(&clear_values)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
vulkan
|
||||||
vulkan.base.device.reset_command_buffer(cmd, vk::CommandBufferResetFlags::empty())
|
.base
|
||||||
|
.device
|
||||||
|
.reset_command_buffer(cmd, vk::CommandBufferResetFlags::empty())
|
||||||
.expect("could not reset command buffer");
|
.expect("could not reset command buffer");
|
||||||
|
|
||||||
vulkan.base.device.begin_command_buffer(cmd, &vk::CommandBufferBeginInfo::default())
|
vulkan
|
||||||
|
.base
|
||||||
|
.device
|
||||||
|
.begin_command_buffer(cmd, &vk::CommandBufferBeginInfo::default())
|
||||||
.expect("failed to begin command buffer");
|
.expect("failed to begin command buffer");
|
||||||
|
|
||||||
vulkan.base.device
|
vulkan.base.device.cmd_begin_render_pass(
|
||||||
.cmd_begin_render_pass(cmd,
|
cmd,
|
||||||
&render_pass_begin, vk::SubpassContents::INLINE);
|
&render_pass_begin,
|
||||||
|
vk::SubpassContents::INLINE,
|
||||||
|
);
|
||||||
|
|
||||||
vulkan.base.device
|
vulkan.base.device.cmd_bind_pipeline(
|
||||||
.cmd_bind_pipeline(cmd, vk::PipelineBindPoint::GRAPHICS, vulkan.pipeline.graphic_pipeline);
|
cmd,
|
||||||
|
vk::PipelineBindPoint::GRAPHICS,
|
||||||
|
vulkan.pipeline.graphic_pipeline,
|
||||||
|
);
|
||||||
|
|
||||||
vulkan.base.device
|
vulkan.base.device.cmd_set_viewport(
|
||||||
.cmd_set_viewport(cmd, 0, &[vk::Viewport {
|
cmd,
|
||||||
|
0,
|
||||||
|
&[vk::Viewport {
|
||||||
max_depth: 1.0,
|
max_depth: 1.0,
|
||||||
width: vulkan.swapchain.extent.width as f32,
|
width: vulkan.swapchain.extent.width as f32,
|
||||||
height: vulkan.swapchain.extent.height as f32,
|
height: vulkan.swapchain.extent.height as f32,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}]);
|
}],
|
||||||
|
);
|
||||||
|
|
||||||
vulkan.base.device
|
vulkan.base.device.cmd_set_scissor(
|
||||||
.cmd_set_scissor(cmd, 0, &[vk::Rect2D {
|
cmd,
|
||||||
|
0,
|
||||||
|
&[vk::Rect2D {
|
||||||
offset: Default::default(),
|
offset: Default::default(),
|
||||||
extent: vulkan.swapchain.extent
|
extent: vulkan.swapchain.extent,
|
||||||
}]);
|
}],
|
||||||
|
);
|
||||||
|
|
||||||
vulkan.base.device.cmd_draw(cmd, 3, 1, 0, 0);
|
vulkan.base.device.cmd_draw(cmd, 3, 1, 0, 0);
|
||||||
vulkan.base.device.cmd_end_render_pass(cmd);
|
vulkan.base.device.cmd_end_render_pass(cmd);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_frame(vulkan: &VulkanDraw, filter: &mut FilterChainVulkan) {
|
fn draw_frame(vulkan: &VulkanDraw, filter: &mut FilterChainVulkan) {
|
||||||
unsafe {
|
unsafe {
|
||||||
vulkan.base.device.wait_for_fences(&[vulkan.sync.in_flight], true, u64::MAX)
|
vulkan
|
||||||
|
.base
|
||||||
|
.device
|
||||||
|
.wait_for_fences(&[vulkan.sync.in_flight], true, u64::MAX)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
vulkan.base.device.reset_fences(&[vulkan.sync.in_flight])
|
vulkan
|
||||||
|
.base
|
||||||
|
.device
|
||||||
|
.reset_fences(&[vulkan.sync.in_flight])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
let (swapchain_index, _) = vulkan
|
||||||
let (swapchain_index, _) = vulkan.swapchain.loader.acquire_next_image(vulkan.swapchain.swapchain, u64::MAX, vulkan.sync.image_available, vk::Fence::null())
|
.swapchain
|
||||||
|
.loader
|
||||||
|
.acquire_next_image(
|
||||||
|
vulkan.swapchain.swapchain,
|
||||||
|
u64::MAX,
|
||||||
|
vulkan.sync.image_available,
|
||||||
|
vk::Fence::null(),
|
||||||
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let cmd = vulkan.render_command_pool.buffers[swapchain_index as usize];
|
let cmd = vulkan.render_command_pool.buffers[swapchain_index as usize];
|
||||||
|
@ -148,21 +173,22 @@ impl VulkanWindow {
|
||||||
|
|
||||||
Self::record_command_buffer(vulkan, framebuffer, cmd);
|
Self::record_command_buffer(vulkan, framebuffer, cmd);
|
||||||
|
|
||||||
util::vulkan_image_layout_transition_levels(&vulkan.base.device,
|
util::vulkan_image_layout_transition_levels(
|
||||||
|
&vulkan.base.device,
|
||||||
cmd,
|
cmd,
|
||||||
framebuffer_image,
|
framebuffer_image,
|
||||||
1,
|
1,
|
||||||
vk::ImageLayout::UNDEFINED,
|
vk::ImageLayout::UNDEFINED,
|
||||||
vk::ImageLayout::TRANSFER_SRC_OPTIMAL,
|
vk::ImageLayout::TRANSFER_SRC_OPTIMAL,
|
||||||
vk::AccessFlags::COLOR_ATTACHMENT_WRITE,
|
vk::AccessFlags::COLOR_ATTACHMENT_WRITE,
|
||||||
vk::AccessFlags::TRANSFER_READ,
|
vk::AccessFlags::TRANSFER_READ,
|
||||||
vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT,
|
vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT,
|
||||||
vk::PipelineStageFlags::TRANSFER,
|
vk::PipelineStageFlags::TRANSFER,
|
||||||
vk::QUEUE_FAMILY_IGNORED,
|
vk::QUEUE_FAMILY_IGNORED,
|
||||||
vk::QUEUE_FAMILY_IGNORED
|
vk::QUEUE_FAMILY_IGNORED,
|
||||||
);
|
);
|
||||||
|
|
||||||
let blit_subresource =vk::ImageSubresourceLayers::builder()
|
let blit_subresource = vk::ImageSubresourceLayers::builder()
|
||||||
.layer_count(1)
|
.layer_count(1)
|
||||||
.aspect_mask(vk::ImageAspectFlags::COLOR)
|
.aspect_mask(vk::ImageAspectFlags::COLOR)
|
||||||
.build();
|
.build();
|
||||||
|
@ -184,8 +210,11 @@ impl VulkanWindow {
|
||||||
z: 1,
|
z: 1,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
vulkan.base.device.cmd_blit_image(cmd, framebuffer_image, vk::ImageLayout::TRANSFER_SRC_OPTIMAL,
|
vulkan.base.device.cmd_blit_image(
|
||||||
swapchain_image,
|
cmd,
|
||||||
|
framebuffer_image,
|
||||||
|
vk::ImageLayout::TRANSFER_SRC_OPTIMAL,
|
||||||
|
swapchain_image,
|
||||||
vk::ImageLayout::TRANSFER_DST_OPTIMAL,
|
vk::ImageLayout::TRANSFER_DST_OPTIMAL,
|
||||||
&[vk::ImageBlit {
|
&[vk::ImageBlit {
|
||||||
src_subresource: blit_subresource,
|
src_subresource: blit_subresource,
|
||||||
|
@ -193,25 +222,29 @@ impl VulkanWindow {
|
||||||
dst_subresource: blit_subresource,
|
dst_subresource: blit_subresource,
|
||||||
dst_offsets,
|
dst_offsets,
|
||||||
}],
|
}],
|
||||||
vk::Filter::LINEAR
|
vk::Filter::LINEAR,
|
||||||
);
|
);
|
||||||
|
|
||||||
util::vulkan_image_layout_transition_levels(&vulkan.base.device,
|
util::vulkan_image_layout_transition_levels(
|
||||||
cmd,
|
&vulkan.base.device,
|
||||||
swapchain_image,
|
cmd,
|
||||||
1,
|
swapchain_image,
|
||||||
vk::ImageLayout::UNDEFINED,
|
1,
|
||||||
vk::ImageLayout::PRESENT_SRC_KHR,
|
vk::ImageLayout::UNDEFINED,
|
||||||
vk::AccessFlags::empty(),
|
vk::ImageLayout::PRESENT_SRC_KHR,
|
||||||
vk::AccessFlags::TRANSFER_READ,
|
vk::AccessFlags::empty(),
|
||||||
vk::PipelineStageFlags::TRANSFER,
|
vk::AccessFlags::TRANSFER_READ,
|
||||||
vk::PipelineStageFlags::TRANSFER,
|
vk::PipelineStageFlags::TRANSFER,
|
||||||
vk::QUEUE_FAMILY_IGNORED,
|
vk::PipelineStageFlags::TRANSFER,
|
||||||
vk::QUEUE_FAMILY_IGNORED
|
vk::QUEUE_FAMILY_IGNORED,
|
||||||
|
vk::QUEUE_FAMILY_IGNORED,
|
||||||
);
|
);
|
||||||
|
|
||||||
vulkan.base.device.end_command_buffer(cmd).expect("failed to record commandbuffer");
|
vulkan
|
||||||
|
.base
|
||||||
|
.device
|
||||||
|
.end_command_buffer(cmd)
|
||||||
|
.expect("failed to record commandbuffer");
|
||||||
|
|
||||||
let submit_info = vk::SubmitInfo::builder()
|
let submit_info = vk::SubmitInfo::builder()
|
||||||
.wait_dst_stage_mask(&[vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT])
|
.wait_dst_stage_mask(&[vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT])
|
||||||
|
@ -220,7 +253,14 @@ impl VulkanWindow {
|
||||||
.command_buffers(&[cmd])
|
.command_buffers(&[cmd])
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
vulkan.base.device.queue_submit(vulkan.base.graphics_queue, &[submit_info], vulkan.sync.in_flight)
|
vulkan
|
||||||
|
.base
|
||||||
|
.device
|
||||||
|
.queue_submit(
|
||||||
|
vulkan.base.graphics_queue,
|
||||||
|
&[submit_info],
|
||||||
|
vulkan.sync.in_flight,
|
||||||
|
)
|
||||||
.expect("failed to submit queue");
|
.expect("failed to submit queue");
|
||||||
|
|
||||||
let present_info = vk::PresentInfoKHR::builder()
|
let present_info = vk::PresentInfoKHR::builder()
|
||||||
|
@ -229,9 +269,11 @@ impl VulkanWindow {
|
||||||
.image_indices(&[swapchain_index])
|
.image_indices(&[swapchain_index])
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
vulkan.swapchain.loader.queue_present(vulkan.base.graphics_queue, &present_info)
|
vulkan
|
||||||
|
.swapchain
|
||||||
|
.loader
|
||||||
|
.queue_present(vulkan.base.graphics_queue, &present_info)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -251,7 +293,6 @@ pub fn find_memorytype_index(
|
||||||
.map(|(index, _memory_type)| index as _)
|
.map(|(index, _memory_type)| index as _)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub struct VulkanDraw {
|
pub struct VulkanDraw {
|
||||||
surface: VulkanSurface,
|
surface: VulkanSurface,
|
||||||
base: VulkanBase,
|
base: VulkanBase,
|
||||||
|
@ -271,32 +312,44 @@ pub fn main(vulkan: VulkanBase, filter_chain: FilterChainVulkan) {
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let window = VulkanWindow::init_window(&event_loop);
|
let window = VulkanWindow::init_window(&event_loop);
|
||||||
let surface = VulkanSurface::new(&vulkan, &window)
|
let surface = VulkanSurface::new(&vulkan, &window).unwrap();
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let swapchain = VulkanSwapchain::new(&vulkan, &surface, WINDOW_WIDTH, WINDOW_HEIGHT)
|
let swapchain = VulkanSwapchain::new(&vulkan, &surface, WINDOW_WIDTH, WINDOW_HEIGHT).unwrap();
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let pipeline = unsafe { VulkanPipeline::new(&vulkan, &swapchain) }
|
let pipeline = unsafe { VulkanPipeline::new(&vulkan, &swapchain) }.unwrap();
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let mut swapchain_framebuffers = vec![];
|
let mut swapchain_framebuffers = vec![];
|
||||||
for image in &swapchain.swapchain_image_views {
|
for image in &swapchain.swapchain_image_views {
|
||||||
swapchain_framebuffers.push(VulkanFramebuffer::new(&vulkan.device, image, &pipeline.renderpass, WINDOW_WIDTH, WINDOW_HEIGHT).unwrap())
|
swapchain_framebuffers.push(
|
||||||
|
VulkanFramebuffer::new(
|
||||||
|
&vulkan.device,
|
||||||
|
image,
|
||||||
|
&pipeline.renderpass,
|
||||||
|
WINDOW_WIDTH,
|
||||||
|
WINDOW_HEIGHT,
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut render_framebuffers = vec![];
|
let mut render_framebuffers = vec![];
|
||||||
for image in &swapchain.render_image_views {
|
for image in &swapchain.render_image_views {
|
||||||
render_framebuffers.push(VulkanFramebuffer::new(&vulkan.device, image, &pipeline.renderpass, WINDOW_WIDTH, WINDOW_HEIGHT).unwrap())
|
render_framebuffers.push(
|
||||||
|
VulkanFramebuffer::new(
|
||||||
|
&vulkan.device,
|
||||||
|
image,
|
||||||
|
&pipeline.renderpass,
|
||||||
|
WINDOW_WIDTH,
|
||||||
|
WINDOW_HEIGHT,
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
let swapchain_command_pool = VulkanCommandPool::new(&vulkan, 3)
|
let swapchain_command_pool = VulkanCommandPool::new(&vulkan, 3).unwrap();
|
||||||
.unwrap();
|
let render_command_pool = VulkanCommandPool::new(&vulkan, 3).unwrap();
|
||||||
let render_command_pool = VulkanCommandPool::new(&vulkan, 3)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let sync = SyncObjects::new(&vulkan.device)
|
let sync = SyncObjects::new(&vulkan.device).unwrap();
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let vulkan = VulkanDraw {
|
let vulkan = VulkanDraw {
|
||||||
surface,
|
surface,
|
||||||
|
@ -311,4 +364,4 @@ pub fn main(vulkan: VulkanBase, filter_chain: FilterChainVulkan) {
|
||||||
};
|
};
|
||||||
|
|
||||||
VulkanWindow::main_loop(event_loop, window, vulkan, filter_chain);
|
VulkanWindow::main_loop(event_loop, window, vulkan, filter_chain);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use std::ffi::CStr;
|
|
||||||
use ash::vk;
|
use ash::vk;
|
||||||
|
use std::ffi::CStr;
|
||||||
|
|
||||||
pub struct QueueFamilyIndices {
|
pub struct QueueFamilyIndices {
|
||||||
graphics_family: Option<u32>,
|
graphics_family: Option<u32>,
|
||||||
|
@ -62,16 +62,12 @@ fn is_physical_device_suitable(
|
||||||
device_name, device_properties.device_id, device_type
|
device_name, device_properties.device_id, device_type
|
||||||
);
|
);
|
||||||
|
|
||||||
println!(
|
println!("\tAPI Version: {}", device_properties.api_version);
|
||||||
"\tAPI Version: {}",
|
|
||||||
device_properties.api_version
|
|
||||||
);
|
|
||||||
|
|
||||||
println!("\tSupport Queue Family: {}", device_queue_families.len());
|
println!("\tSupport Queue Family: {}", device_queue_families.len());
|
||||||
println!("\t\tQueue Count | Graphics, Compute, Transfer, Sparse Binding");
|
println!("\t\tQueue Count | Graphics, Compute, Transfer, Sparse Binding");
|
||||||
for queue_family in device_queue_families.iter() {
|
for queue_family in device_queue_families.iter() {
|
||||||
let is_graphics_support = if queue_family.queue_flags.contains(vk::QueueFlags::GRAPHICS)
|
let is_graphics_support = if queue_family.queue_flags.contains(vk::QueueFlags::GRAPHICS) {
|
||||||
{
|
|
||||||
"support"
|
"support"
|
||||||
} else {
|
} else {
|
||||||
"unsupport"
|
"unsupport"
|
||||||
|
@ -81,8 +77,7 @@ fn is_physical_device_suitable(
|
||||||
} else {
|
} else {
|
||||||
"unsupport"
|
"unsupport"
|
||||||
};
|
};
|
||||||
let is_transfer_support = if queue_family.queue_flags.contains(vk::QueueFlags::TRANSFER)
|
let is_transfer_support = if queue_family.queue_flags.contains(vk::QueueFlags::TRANSFER) {
|
||||||
{
|
|
||||||
"support"
|
"support"
|
||||||
} else {
|
} else {
|
||||||
"unsupport"
|
"unsupport"
|
||||||
|
@ -148,4 +143,4 @@ pub fn find_queue_family(
|
||||||
}
|
}
|
||||||
|
|
||||||
queue_family_indices
|
queue_family_indices
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
use std::ffi::CStr;
|
|
||||||
use std::io::Cursor;
|
|
||||||
use std::mem::align_of;
|
|
||||||
use ash::prelude::VkResult;
|
|
||||||
use ash::util::{Align, read_spv};
|
|
||||||
use ash::vk;
|
|
||||||
use bytemuck::offset_of;
|
|
||||||
use crate::hello_triangle::find_memorytype_index;
|
use crate::hello_triangle::find_memorytype_index;
|
||||||
use crate::hello_triangle::surface::VulkanSurface;
|
use crate::hello_triangle::surface::VulkanSurface;
|
||||||
use crate::hello_triangle::swapchain::VulkanSwapchain;
|
use crate::hello_triangle::swapchain::VulkanSwapchain;
|
||||||
use crate::hello_triangle::vulkan_base::VulkanBase;
|
use crate::hello_triangle::vulkan_base::VulkanBase;
|
||||||
|
use ash::prelude::VkResult;
|
||||||
|
use ash::util::{read_spv, Align};
|
||||||
|
use ash::vk;
|
||||||
|
use bytemuck::offset_of;
|
||||||
|
use std::ffi::CStr;
|
||||||
|
use std::io::Cursor;
|
||||||
|
use std::mem::align_of;
|
||||||
|
|
||||||
#[derive(Default, Clone, Debug, Copy)]
|
#[derive(Default, Clone, Debug, Copy)]
|
||||||
struct Vertex {
|
struct Vertex {
|
||||||
|
@ -38,7 +38,7 @@ impl VulkanPipeline {
|
||||||
&base.mem_props,
|
&base.mem_props,
|
||||||
vk::MemoryPropertyFlags::HOST_VISIBLE | vk::MemoryPropertyFlags::HOST_COHERENT,
|
vk::MemoryPropertyFlags::HOST_VISIBLE | vk::MemoryPropertyFlags::HOST_COHERENT,
|
||||||
)
|
)
|
||||||
.expect("Unable to find suitable memorytype for the index buffer.");
|
.expect("Unable to find suitable memorytype for the index buffer.");
|
||||||
|
|
||||||
let index_allocate_info = vk::MemoryAllocateInfo {
|
let index_allocate_info = vk::MemoryAllocateInfo {
|
||||||
allocation_size: index_buffer_memory_req.size,
|
allocation_size: index_buffer_memory_req.size,
|
||||||
|
@ -90,7 +90,7 @@ impl VulkanPipeline {
|
||||||
&base.mem_props,
|
&base.mem_props,
|
||||||
vk::MemoryPropertyFlags::HOST_VISIBLE | vk::MemoryPropertyFlags::HOST_COHERENT,
|
vk::MemoryPropertyFlags::HOST_VISIBLE | vk::MemoryPropertyFlags::HOST_COHERENT,
|
||||||
)
|
)
|
||||||
.expect("Unable to find suitable memorytype for the vertex buffer.");
|
.expect("Unable to find suitable memorytype for the vertex buffer.");
|
||||||
|
|
||||||
let vertex_buffer_allocate_info = vk::MemoryAllocateInfo {
|
let vertex_buffer_allocate_info = vk::MemoryAllocateInfo {
|
||||||
allocation_size: vertex_input_buffer_memory_req.size,
|
allocation_size: vertex_input_buffer_memory_req.size,
|
||||||
|
@ -141,9 +141,9 @@ impl VulkanPipeline {
|
||||||
.bind_buffer_memory(vertex_input_buffer, vertex_input_buffer_memory, 0)
|
.bind_buffer_memory(vertex_input_buffer, vertex_input_buffer_memory, 0)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|
||||||
// create pipeline
|
// create pipeline
|
||||||
let mut vertex_spv_file = Cursor::new(&include_bytes!("../../shader/triangle_simple/vert.spv")[..]);
|
let mut vertex_spv_file =
|
||||||
|
Cursor::new(&include_bytes!("../../shader/triangle_simple/vert.spv")[..]);
|
||||||
let vertex_code =
|
let vertex_code =
|
||||||
read_spv(&mut vertex_spv_file).expect("Failed to read vertex shader spv file");
|
read_spv(&mut vertex_spv_file).expect("Failed to read vertex shader spv file");
|
||||||
let vertex_shader_info = ShaderModule::new(&base.device, vertex_code)?;
|
let vertex_shader_info = ShaderModule::new(&base.device, vertex_code)?;
|
||||||
|
@ -153,8 +153,8 @@ impl VulkanPipeline {
|
||||||
.name(CStr::from_bytes_with_nul_unchecked(b"main\0"))
|
.name(CStr::from_bytes_with_nul_unchecked(b"main\0"))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
let mut frag_spv_file =
|
||||||
let mut frag_spv_file = Cursor::new(&include_bytes!("../../shader/triangle_simple/frag.spv")[..]);
|
Cursor::new(&include_bytes!("../../shader/triangle_simple/frag.spv")[..]);
|
||||||
let frag_code =
|
let frag_code =
|
||||||
read_spv(&mut frag_spv_file).expect("Failed to read fragment shader spv file");
|
read_spv(&mut frag_spv_file).expect("Failed to read fragment shader spv file");
|
||||||
let frag_shader_info = ShaderModule::new(&base.device, frag_code)?;
|
let frag_shader_info = ShaderModule::new(&base.device, frag_code)?;
|
||||||
|
@ -194,7 +194,6 @@ impl VulkanPipeline {
|
||||||
.create_pipeline_layout(&layout_create_info, None)
|
.create_pipeline_layout(&layout_create_info, None)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|
||||||
let dynamic_state = vk::PipelineDynamicStateCreateInfo::builder()
|
let dynamic_state = vk::PipelineDynamicStateCreateInfo::builder()
|
||||||
.dynamic_states(&[vk::DynamicState::VIEWPORT, vk::DynamicState::SCISSOR])
|
.dynamic_states(&[vk::DynamicState::VIEWPORT, vk::DynamicState::SCISSOR])
|
||||||
.build();
|
.build();
|
||||||
|
@ -244,16 +243,14 @@ impl VulkanPipeline {
|
||||||
.logic_op(vk::LogicOp::COPY)
|
.logic_op(vk::LogicOp::COPY)
|
||||||
.attachments(&color_blend_attachment);
|
.attachments(&color_blend_attachment);
|
||||||
|
|
||||||
let renderpass_attachments = [
|
let renderpass_attachments = [vk::AttachmentDescription {
|
||||||
vk::AttachmentDescription {
|
format: swapchain.format.format,
|
||||||
format: swapchain.format.format,
|
samples: vk::SampleCountFlags::TYPE_1,
|
||||||
samples: vk::SampleCountFlags::TYPE_1,
|
load_op: vk::AttachmentLoadOp::CLEAR,
|
||||||
load_op: vk::AttachmentLoadOp::CLEAR,
|
store_op: vk::AttachmentStoreOp::STORE,
|
||||||
store_op: vk::AttachmentStoreOp::STORE,
|
final_layout: vk::ImageLayout::PRESENT_SRC_KHR,
|
||||||
final_layout: vk::ImageLayout::PRESENT_SRC_KHR,
|
..Default::default()
|
||||||
..Default::default()
|
}];
|
||||||
},
|
|
||||||
];
|
|
||||||
let color_attachment_refs = [vk::AttachmentReference {
|
let color_attachment_refs = [vk::AttachmentReference {
|
||||||
attachment: 0,
|
attachment: 0,
|
||||||
layout: vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL,
|
layout: vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL,
|
||||||
|
@ -295,7 +292,6 @@ impl VulkanPipeline {
|
||||||
.layout(pipeline_layout)
|
.layout(pipeline_layout)
|
||||||
.render_pass(renderpass);
|
.render_pass(renderpass);
|
||||||
|
|
||||||
|
|
||||||
let graphics_pipelines = base
|
let graphics_pipelines = base
|
||||||
.device
|
.device
|
||||||
.create_graphics_pipelines(
|
.create_graphics_pipelines(
|
||||||
|
@ -305,13 +301,12 @@ impl VulkanPipeline {
|
||||||
)
|
)
|
||||||
.expect("Unable to create graphics pipeline");
|
.expect("Unable to create graphics pipeline");
|
||||||
|
|
||||||
|
|
||||||
let graphic_pipeline = graphics_pipelines[0];
|
let graphic_pipeline = graphics_pipelines[0];
|
||||||
|
|
||||||
Ok(VulkanPipeline {
|
Ok(VulkanPipeline {
|
||||||
graphic_pipeline,
|
graphic_pipeline,
|
||||||
renderpass,
|
renderpass,
|
||||||
pipeline_layout
|
pipeline_layout,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -323,18 +318,13 @@ pub struct ShaderModule {
|
||||||
|
|
||||||
impl ShaderModule {
|
impl ShaderModule {
|
||||||
pub fn new(device: &ash::Device, spirv: Vec<u32>) -> VkResult<ShaderModule> {
|
pub fn new(device: &ash::Device, spirv: Vec<u32>) -> VkResult<ShaderModule> {
|
||||||
let create_info = vk::ShaderModuleCreateInfo::builder()
|
let create_info = vk::ShaderModuleCreateInfo::builder().code(&spirv).build();
|
||||||
.code(&spirv)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
|
let module = unsafe { device.create_shader_module(&create_info, None)? };
|
||||||
let module = unsafe {
|
|
||||||
device.create_shader_module(&create_info, None)?
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(ShaderModule {
|
Ok(ShaderModule {
|
||||||
module,
|
module,
|
||||||
device: device.clone()
|
device: device.clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -346,4 +336,3 @@ impl Drop for ShaderModule {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,18 +1,16 @@
|
||||||
|
use crate::hello_triangle::vulkan_base::VulkanBase;
|
||||||
use ash::prelude::VkResult;
|
use ash::prelude::VkResult;
|
||||||
use ash::vk;
|
use ash::vk;
|
||||||
use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle};
|
use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle};
|
||||||
use crate::hello_triangle::vulkan_base::VulkanBase;
|
|
||||||
|
|
||||||
pub struct VulkanSurface {
|
pub struct VulkanSurface {
|
||||||
surface_loader: ash::extensions::khr::Surface,
|
surface_loader: ash::extensions::khr::Surface,
|
||||||
pub surface: vk::SurfaceKHR,
|
pub surface: vk::SurfaceKHR,
|
||||||
pub present_queue: vk::Queue
|
pub present_queue: vk::Queue,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VulkanSurface {
|
impl VulkanSurface {
|
||||||
pub fn new(base: &VulkanBase,
|
pub fn new(base: &VulkanBase, window: &winit::window::Window) -> VkResult<VulkanSurface> {
|
||||||
window: &winit::window::Window) -> VkResult<VulkanSurface>
|
|
||||||
{
|
|
||||||
let surface = unsafe {
|
let surface = unsafe {
|
||||||
ash_window::create_surface(
|
ash_window::create_surface(
|
||||||
&base.entry,
|
&base.entry,
|
||||||
|
@ -26,7 +24,8 @@ impl VulkanSurface {
|
||||||
let surface_loader = ash::extensions::khr::Surface::new(&base.entry, &base.instance);
|
let surface_loader = ash::extensions::khr::Surface::new(&base.entry, &base.instance);
|
||||||
|
|
||||||
let present_queue = unsafe {
|
let present_queue = unsafe {
|
||||||
let queue_family = base.instance
|
let queue_family = base
|
||||||
|
.instance
|
||||||
.get_physical_device_queue_family_properties(base.physical_device)
|
.get_physical_device_queue_family_properties(base.physical_device)
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
|
@ -34,12 +33,12 @@ impl VulkanSurface {
|
||||||
let supports_graphic_and_surface =
|
let supports_graphic_and_surface =
|
||||||
info.queue_flags.contains(vk::QueueFlags::GRAPHICS)
|
info.queue_flags.contains(vk::QueueFlags::GRAPHICS)
|
||||||
&& surface_loader
|
&& surface_loader
|
||||||
.get_physical_device_surface_support(
|
.get_physical_device_surface_support(
|
||||||
base.physical_device,
|
base.physical_device,
|
||||||
index as u32,
|
index as u32,
|
||||||
surface,
|
surface,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
if supports_graphic_and_surface {
|
if supports_graphic_and_surface {
|
||||||
Some(index)
|
Some(index)
|
||||||
} else {
|
} else {
|
||||||
|
@ -53,13 +52,15 @@ impl VulkanSurface {
|
||||||
Ok(VulkanSurface {
|
Ok(VulkanSurface {
|
||||||
surface,
|
surface,
|
||||||
surface_loader,
|
surface_loader,
|
||||||
present_queue
|
present_queue,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn choose_format(&self, base: &VulkanBase) -> VkResult<vk::SurfaceFormatKHR> {
|
pub fn choose_format(&self, base: &VulkanBase) -> VkResult<vk::SurfaceFormatKHR> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let available_formats = self.surface_loader.get_physical_device_surface_formats(base.physical_device, self.surface)?;
|
let available_formats = self
|
||||||
|
.surface_loader
|
||||||
|
.get_physical_device_surface_formats(base.physical_device, self.surface)?;
|
||||||
for available_format in available_formats.iter() {
|
for available_format in available_formats.iter() {
|
||||||
if available_format.format == vk::Format::B8G8R8A8_SRGB
|
if available_format.format == vk::Format::B8G8R8A8_SRGB
|
||||||
&& available_format.color_space == vk::ColorSpaceKHR::SRGB_NONLINEAR
|
&& available_format.color_space == vk::ColorSpaceKHR::SRGB_NONLINEAR
|
||||||
|
@ -74,17 +75,26 @@ impl VulkanSurface {
|
||||||
|
|
||||||
pub fn choose_present_mode(&self, base: &VulkanBase) -> VkResult<vk::PresentModeKHR> {
|
pub fn choose_present_mode(&self, base: &VulkanBase) -> VkResult<vk::PresentModeKHR> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let available_formats = self.surface_loader.get_physical_device_surface_present_modes(base.physical_device, self.surface)?;
|
let available_formats = self
|
||||||
|
.surface_loader
|
||||||
|
.get_physical_device_surface_present_modes(base.physical_device, self.surface)?;
|
||||||
|
|
||||||
Ok(if available_formats.contains(&vk::PresentModeKHR::MAILBOX) {
|
Ok(
|
||||||
vk::PresentModeKHR::MAILBOX
|
if available_formats.contains(&vk::PresentModeKHR::MAILBOX) {
|
||||||
} else {
|
vk::PresentModeKHR::MAILBOX
|
||||||
vk::PresentModeKHR::FIFO
|
} else {
|
||||||
})
|
vk::PresentModeKHR::FIFO
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn choose_swapchain_extent(&self, base: &VulkanBase, width: u32, height: u32) -> VkResult<vk::Extent2D> {
|
pub fn choose_swapchain_extent(
|
||||||
|
&self,
|
||||||
|
base: &VulkanBase,
|
||||||
|
width: u32,
|
||||||
|
height: u32,
|
||||||
|
) -> VkResult<vk::Extent2D> {
|
||||||
let capabilities = self.get_capabilities(base)?;
|
let capabilities = self.get_capabilities(base)?;
|
||||||
if capabilities.current_extent.width != u32::MAX {
|
if capabilities.current_extent.width != u32::MAX {
|
||||||
Ok(capabilities.current_extent)
|
Ok(capabilities.current_extent)
|
||||||
|
@ -108,7 +118,8 @@ impl VulkanSurface {
|
||||||
|
|
||||||
pub fn get_capabilities(&self, base: &VulkanBase) -> VkResult<vk::SurfaceCapabilitiesKHR> {
|
pub fn get_capabilities(&self, base: &VulkanBase) -> VkResult<vk::SurfaceCapabilitiesKHR> {
|
||||||
unsafe {
|
unsafe {
|
||||||
self.surface_loader.get_physical_device_surface_capabilities(base.physical_device, self.surface)
|
self.surface_loader
|
||||||
|
.get_physical_device_surface_capabilities(base.physical_device, self.surface)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -119,4 +130,4 @@ impl Drop for VulkanSurface {
|
||||||
self.surface_loader.destroy_surface(self.surface, None);
|
self.surface_loader.destroy_surface(self.surface, None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
use ash::prelude::VkResult;
|
|
||||||
use ash::vk;
|
|
||||||
use ash::vk::Extent3D;
|
|
||||||
use crate::hello_triangle::surface::VulkanSurface;
|
use crate::hello_triangle::surface::VulkanSurface;
|
||||||
use crate::hello_triangle::vulkan_base::VulkanBase;
|
use crate::hello_triangle::vulkan_base::VulkanBase;
|
||||||
use crate::util::find_vulkan_memory_type;
|
use crate::util::find_vulkan_memory_type;
|
||||||
use crate::vulkan_primitives::VulkanImageMemory;
|
use crate::vulkan_primitives::VulkanImageMemory;
|
||||||
|
use ash::prelude::VkResult;
|
||||||
|
use ash::vk;
|
||||||
|
use ash::vk::Extent3D;
|
||||||
|
|
||||||
pub struct VulkanSwapchain {
|
pub struct VulkanSwapchain {
|
||||||
pub swapchain: vk::SwapchainKHR,
|
pub swapchain: vk::SwapchainKHR,
|
||||||
|
@ -21,7 +21,12 @@ pub struct VulkanSwapchain {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VulkanSwapchain {
|
impl VulkanSwapchain {
|
||||||
pub fn new(base: &VulkanBase, surface: &VulkanSurface, width: u32, height:u32 ) -> VkResult<VulkanSwapchain> {
|
pub fn new(
|
||||||
|
base: &VulkanBase,
|
||||||
|
surface: &VulkanSurface,
|
||||||
|
width: u32,
|
||||||
|
height: u32,
|
||||||
|
) -> VkResult<VulkanSwapchain> {
|
||||||
let format = surface.choose_format(base)?;
|
let format = surface.choose_format(base)?;
|
||||||
let mode = surface.choose_present_mode(base)?;
|
let mode = surface.choose_present_mode(base)?;
|
||||||
let extent = surface.choose_swapchain_extent(base, width, height)?;
|
let extent = surface.choose_swapchain_extent(base, width, height)?;
|
||||||
|
@ -56,13 +61,10 @@ impl VulkanSwapchain {
|
||||||
|
|
||||||
let loader = ash::extensions::khr::Swapchain::new(&base.instance, &base.device);
|
let loader = ash::extensions::khr::Swapchain::new(&base.instance, &base.device);
|
||||||
|
|
||||||
let swapchain = unsafe {
|
let swapchain = unsafe { loader.create_swapchain(&create_info, None)? };
|
||||||
loader.create_swapchain(&create_info, None)?
|
|
||||||
};
|
|
||||||
|
|
||||||
let swapchain_images = unsafe { loader.get_swapchain_images(swapchain)? };
|
let swapchain_images = unsafe { loader.get_swapchain_images(swapchain)? };
|
||||||
|
|
||||||
|
|
||||||
let mut render_images = vec![];
|
let mut render_images = vec![];
|
||||||
|
|
||||||
for _ in 0..swapchain_images.len() {
|
for _ in 0..swapchain_images.len() {
|
||||||
|
@ -79,10 +81,7 @@ impl VulkanSwapchain {
|
||||||
.tiling(vk::ImageTiling::OPTIMAL)
|
.tiling(vk::ImageTiling::OPTIMAL)
|
||||||
.array_layers(1)
|
.array_layers(1)
|
||||||
.mip_levels(1)
|
.mip_levels(1)
|
||||||
.usage(
|
.usage(vk::ImageUsageFlags::SAMPLED | vk::ImageUsageFlags::COLOR_ATTACHMENT)
|
||||||
vk::ImageUsageFlags::SAMPLED
|
|
||||||
| vk::ImageUsageFlags::COLOR_ATTACHMENT
|
|
||||||
)
|
|
||||||
.initial_layout(vk::ImageLayout::UNDEFINED);
|
.initial_layout(vk::ImageLayout::UNDEFINED);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -100,70 +99,68 @@ impl VulkanSwapchain {
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
// todo: optimize by reusing existing memory.
|
// todo: optimize by reusing existing memory.
|
||||||
let memory = VulkanImageMemory::new(&base.device, &alloc_info)
|
let memory = VulkanImageMemory::new(&base.device, &alloc_info).unwrap();
|
||||||
.unwrap();
|
memory.bind(&image).unwrap();
|
||||||
memory.bind(&image)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
render_images.push((image, memory))
|
render_images.push((image, memory))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let image_views: VkResult<Vec<vk::ImageView>> = swapchain_images.iter().map(|image| {
|
let image_views: VkResult<Vec<vk::ImageView>> = swapchain_images
|
||||||
let create_info = vk::ImageViewCreateInfo::builder()
|
.iter()
|
||||||
.view_type(vk::ImageViewType::TYPE_2D)
|
.map(|image| {
|
||||||
.format(format.format)
|
let create_info = vk::ImageViewCreateInfo::builder()
|
||||||
.components(vk::ComponentMapping {
|
.view_type(vk::ImageViewType::TYPE_2D)
|
||||||
r: vk::ComponentSwizzle::IDENTITY,
|
.format(format.format)
|
||||||
g: vk::ComponentSwizzle::IDENTITY,
|
.components(vk::ComponentMapping {
|
||||||
b: vk::ComponentSwizzle::IDENTITY,
|
r: vk::ComponentSwizzle::IDENTITY,
|
||||||
a: vk::ComponentSwizzle::IDENTITY,
|
g: vk::ComponentSwizzle::IDENTITY,
|
||||||
})
|
b: vk::ComponentSwizzle::IDENTITY,
|
||||||
.subresource_range(vk::ImageSubresourceRange {
|
a: vk::ComponentSwizzle::IDENTITY,
|
||||||
aspect_mask: vk::ImageAspectFlags::COLOR,
|
})
|
||||||
base_mip_level: 0,
|
.subresource_range(vk::ImageSubresourceRange {
|
||||||
level_count: 1,
|
aspect_mask: vk::ImageAspectFlags::COLOR,
|
||||||
base_array_layer: 0,
|
base_mip_level: 0,
|
||||||
layer_count: 1,
|
level_count: 1,
|
||||||
})
|
base_array_layer: 0,
|
||||||
.image(*image)
|
layer_count: 1,
|
||||||
.build();
|
})
|
||||||
|
.image(*image)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
let view = unsafe { base.device.create_image_view(&create_info, None)? };
|
||||||
|
|
||||||
let view = unsafe {
|
Ok(view)
|
||||||
base.device.create_image_view(&create_info, None)?
|
})
|
||||||
};
|
.collect();
|
||||||
|
|
||||||
Ok(view)
|
let render_image_views: VkResult<Vec<vk::ImageView>> = render_images
|
||||||
}).collect();
|
.iter()
|
||||||
|
.map(|(image, _)| {
|
||||||
|
let create_info = vk::ImageViewCreateInfo::builder()
|
||||||
|
.view_type(vk::ImageViewType::TYPE_2D)
|
||||||
|
.format(format.format)
|
||||||
|
.components(vk::ComponentMapping {
|
||||||
|
r: vk::ComponentSwizzle::IDENTITY,
|
||||||
|
g: vk::ComponentSwizzle::IDENTITY,
|
||||||
|
b: vk::ComponentSwizzle::IDENTITY,
|
||||||
|
a: vk::ComponentSwizzle::IDENTITY,
|
||||||
|
})
|
||||||
|
.subresource_range(vk::ImageSubresourceRange {
|
||||||
|
aspect_mask: vk::ImageAspectFlags::COLOR,
|
||||||
|
base_mip_level: 0,
|
||||||
|
level_count: 1,
|
||||||
|
base_array_layer: 0,
|
||||||
|
layer_count: 1,
|
||||||
|
})
|
||||||
|
.image(*image)
|
||||||
|
.build();
|
||||||
|
|
||||||
let render_image_views: VkResult<Vec<vk::ImageView>> = render_images.iter().map(|(image, _)| {
|
let view = unsafe { base.device.create_image_view(&create_info, None)? };
|
||||||
let create_info = vk::ImageViewCreateInfo::builder()
|
|
||||||
.view_type(vk::ImageViewType::TYPE_2D)
|
|
||||||
.format(format.format)
|
|
||||||
.components(vk::ComponentMapping {
|
|
||||||
r: vk::ComponentSwizzle::IDENTITY,
|
|
||||||
g: vk::ComponentSwizzle::IDENTITY,
|
|
||||||
b: vk::ComponentSwizzle::IDENTITY,
|
|
||||||
a: vk::ComponentSwizzle::IDENTITY,
|
|
||||||
})
|
|
||||||
.subresource_range(vk::ImageSubresourceRange {
|
|
||||||
aspect_mask: vk::ImageAspectFlags::COLOR,
|
|
||||||
base_mip_level: 0,
|
|
||||||
level_count: 1,
|
|
||||||
base_array_layer: 0,
|
|
||||||
layer_count: 1,
|
|
||||||
})
|
|
||||||
.image(*image)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
|
Ok(view)
|
||||||
let view = unsafe {
|
})
|
||||||
base.device.create_image_view(&create_info, None)?
|
.collect();
|
||||||
};
|
|
||||||
|
|
||||||
Ok(view)
|
|
||||||
}).collect();
|
|
||||||
Ok(VulkanSwapchain {
|
Ok(VulkanSwapchain {
|
||||||
swapchain,
|
swapchain,
|
||||||
loader,
|
loader,
|
||||||
|
@ -174,7 +171,7 @@ impl VulkanSwapchain {
|
||||||
render_images,
|
render_images,
|
||||||
swapchain_image_views: image_views?,
|
swapchain_image_views: image_views?,
|
||||||
render_image_views: render_image_views?,
|
render_image_views: render_image_views?,
|
||||||
device: base.device.clone()
|
device: base.device.clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -188,4 +185,4 @@ impl Drop for VulkanSwapchain {
|
||||||
self.loader.destroy_swapchain(self.swapchain, None)
|
self.loader.destroy_swapchain(self.swapchain, None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,21 +4,28 @@ use ash::vk;
|
||||||
pub struct SyncObjects {
|
pub struct SyncObjects {
|
||||||
pub image_available: vk::Semaphore,
|
pub image_available: vk::Semaphore,
|
||||||
pub render_finished: vk::Semaphore,
|
pub render_finished: vk::Semaphore,
|
||||||
pub in_flight: vk::Fence
|
pub in_flight: vk::Fence,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SyncObjects {
|
impl SyncObjects {
|
||||||
pub fn new(device: &ash::Device) -> VkResult<SyncObjects> {
|
pub fn new(device: &ash::Device) -> VkResult<SyncObjects> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let image_available = device.create_semaphore(&vk::SemaphoreCreateInfo::default(), None)?;
|
let image_available =
|
||||||
let render_finished = device.create_semaphore(&vk::SemaphoreCreateInfo::default(), None)?;
|
device.create_semaphore(&vk::SemaphoreCreateInfo::default(), None)?;
|
||||||
let in_flight = device.create_fence(&vk::FenceCreateInfo::builder().flags(vk::FenceCreateFlags::SIGNALED).build(), None)?;
|
let render_finished =
|
||||||
|
device.create_semaphore(&vk::SemaphoreCreateInfo::default(), None)?;
|
||||||
|
let in_flight = device.create_fence(
|
||||||
|
&vk::FenceCreateInfo::builder()
|
||||||
|
.flags(vk::FenceCreateFlags::SIGNALED)
|
||||||
|
.build(),
|
||||||
|
None,
|
||||||
|
)?;
|
||||||
|
|
||||||
Ok(SyncObjects {
|
Ok(SyncObjects {
|
||||||
image_available,
|
image_available,
|
||||||
render_finished,
|
render_finished,
|
||||||
in_flight
|
in_flight,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
|
use ash::vk;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use ash::vk;
|
|
||||||
|
|
||||||
use std::ffi::{CStr, CString};
|
|
||||||
use ash::prelude::VkResult;
|
|
||||||
use crate::filter_chain::Vulkan;
|
use crate::filter_chain::Vulkan;
|
||||||
use crate::hello_triangle::debug::VulkanDebug;
|
use crate::hello_triangle::debug::VulkanDebug;
|
||||||
use crate::hello_triangle::physicaldevice::{find_queue_family, pick_physical_device};
|
use crate::hello_triangle::physicaldevice::{find_queue_family, pick_physical_device};
|
||||||
use crate::hello_triangle::surface::VulkanSurface;
|
use crate::hello_triangle::surface::VulkanSurface;
|
||||||
|
use ash::prelude::VkResult;
|
||||||
|
use std::ffi::{CStr, CString};
|
||||||
|
|
||||||
const WINDOW_TITLE: &'static str = "librashader Vulkan";
|
const WINDOW_TITLE: &'static str = "librashader Vulkan";
|
||||||
|
|
||||||
|
@ -39,13 +38,11 @@ impl VulkanBase {
|
||||||
let extensions = [
|
let extensions = [
|
||||||
ash::extensions::khr::Surface::name().as_ptr(),
|
ash::extensions::khr::Surface::name().as_ptr(),
|
||||||
ash::extensions::khr::Win32Surface::name().as_ptr(),
|
ash::extensions::khr::Win32Surface::name().as_ptr(),
|
||||||
ash::extensions::ext::DebugUtils::name().as_ptr()
|
ash::extensions::ext::DebugUtils::name().as_ptr(),
|
||||||
];
|
];
|
||||||
|
|
||||||
let layers = unsafe {
|
let layers = unsafe {
|
||||||
[CStr::from_bytes_with_nul_unchecked(
|
[CStr::from_bytes_with_nul_unchecked(b"VK_LAYER_KHRONOS_validation\0").as_ptr()]
|
||||||
b"VK_LAYER_KHRONOS_validation\0",
|
|
||||||
).as_ptr()]
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let create_info = vk::InstanceCreateInfo::builder()
|
let create_info = vk::InstanceCreateInfo::builder()
|
||||||
|
@ -54,9 +51,7 @@ impl VulkanBase {
|
||||||
.enabled_extension_names(&extensions)
|
.enabled_extension_names(&extensions)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let instance = unsafe {
|
let instance = unsafe { entry.create_instance(&create_info, None)? };
|
||||||
entry.create_instance(&create_info, None)?
|
|
||||||
};
|
|
||||||
|
|
||||||
let debug = VulkanDebug::new(&entry, &instance, Some(vulkan_debug_callback))?;
|
let debug = VulkanDebug::new(&entry, &instance, Some(vulkan_debug_callback))?;
|
||||||
|
|
||||||
|
@ -64,9 +59,7 @@ impl VulkanBase {
|
||||||
|
|
||||||
let (device, queue) = VulkanBase::create_device(&instance, &physical_device)?;
|
let (device, queue) = VulkanBase::create_device(&instance, &physical_device)?;
|
||||||
|
|
||||||
let mem_props = unsafe {
|
let mem_props = unsafe { instance.get_physical_device_memory_properties(physical_device) };
|
||||||
instance.get_physical_device_memory_properties(physical_device)
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(VulkanBase {
|
Ok(VulkanBase {
|
||||||
entry,
|
entry,
|
||||||
|
@ -79,11 +72,12 @@ impl VulkanBase {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_device(instance: &ash::Instance, physical_device: &vk::PhysicalDevice) -> VkResult<(ash::Device, vk::Queue)> {
|
fn create_device(
|
||||||
|
instance: &ash::Instance,
|
||||||
|
physical_device: &vk::PhysicalDevice,
|
||||||
|
) -> VkResult<(ash::Device, vk::Queue)> {
|
||||||
let debug = unsafe {
|
let debug = unsafe {
|
||||||
CStr::from_bytes_with_nul_unchecked(
|
CStr::from_bytes_with_nul_unchecked(b"VK_LAYER_KHRONOS_validation\0").as_ptr()
|
||||||
b"VK_LAYER_KHRONOS_validation\0",
|
|
||||||
).as_ptr()
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let indices = find_queue_family(&instance, *physical_device);
|
let indices = find_queue_family(&instance, *physical_device);
|
||||||
|
@ -97,15 +91,12 @@ impl VulkanBase {
|
||||||
let device_create_info = vk::DeviceCreateInfo::builder()
|
let device_create_info = vk::DeviceCreateInfo::builder()
|
||||||
.queue_create_infos(&[queue_info])
|
.queue_create_infos(&[queue_info])
|
||||||
.enabled_layer_names(&[debug])
|
.enabled_layer_names(&[debug])
|
||||||
.enabled_extension_names(&[
|
.enabled_extension_names(&[ash::extensions::khr::Swapchain::name().as_ptr()])
|
||||||
ash::extensions::khr::Swapchain::name().as_ptr()
|
|
||||||
])
|
|
||||||
.enabled_features(&physical_device_features)
|
.enabled_features(&physical_device_features)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let device = unsafe {
|
let device =
|
||||||
instance.create_device(*physical_device, &device_create_info, None)?
|
unsafe { instance.create_device(*physical_device, &device_create_info, None)? };
|
||||||
};
|
|
||||||
|
|
||||||
let queue = unsafe { device.get_device_queue(indices.graphics_family(), 0) };
|
let queue = unsafe { device.get_device_queue(indices.graphics_family(), 0) };
|
||||||
|
|
||||||
|
@ -113,7 +104,6 @@ impl VulkanBase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
unsafe extern "system" fn vulkan_debug_callback(
|
unsafe extern "system" fn vulkan_debug_callback(
|
||||||
message_severity: vk::DebugUtilsMessageSeverityFlagsEXT,
|
message_severity: vk::DebugUtilsMessageSeverityFlagsEXT,
|
||||||
message_type: vk::DebugUtilsMessageTypeFlagsEXT,
|
message_type: vk::DebugUtilsMessageTypeFlagsEXT,
|
||||||
|
@ -159,6 +149,10 @@ impl TryFrom<&VulkanBase> for Vulkan {
|
||||||
type Error = Box<dyn Error>;
|
type Error = Box<dyn Error>;
|
||||||
|
|
||||||
fn try_from(value: &VulkanBase) -> Result<Self, Self::Error> {
|
fn try_from(value: &VulkanBase) -> Result<Self, Self::Error> {
|
||||||
Vulkan::try_from((value.device.clone(), value.graphics_queue.clone(), value.mem_props))
|
Vulkan::try_from((
|
||||||
|
value.device.clone(),
|
||||||
|
value.graphics_queue.clone(),
|
||||||
|
value.mem_props,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,16 +7,16 @@ mod error;
|
||||||
mod filter_chain;
|
mod filter_chain;
|
||||||
mod filter_pass;
|
mod filter_pass;
|
||||||
mod framebuffer;
|
mod framebuffer;
|
||||||
|
mod hello_triangle;
|
||||||
mod luts;
|
mod luts;
|
||||||
mod renderpass;
|
mod renderpass;
|
||||||
|
mod rendertarget;
|
||||||
|
mod samplers;
|
||||||
|
mod texture;
|
||||||
|
mod ubo_ring;
|
||||||
mod util;
|
mod util;
|
||||||
mod vulkan_primitives;
|
mod vulkan_primitives;
|
||||||
mod vulkan_state;
|
mod vulkan_state;
|
||||||
mod samplers;
|
|
||||||
mod texture;
|
|
||||||
mod rendertarget;
|
|
||||||
mod ubo_ring;
|
|
||||||
mod hello_triangle;
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
@ -26,15 +26,14 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn triangle_vk() {
|
fn triangle_vk() {
|
||||||
let entry = unsafe {
|
let entry = unsafe { ash::Entry::load().unwrap() };
|
||||||
ash::Entry::load().unwrap()
|
|
||||||
};
|
|
||||||
let base = VulkanBase::new(entry).unwrap();
|
let base = VulkanBase::new(entry).unwrap();
|
||||||
let mut filter = FilterChainVulkan::load_from_path(
|
let mut filter = FilterChainVulkan::load_from_path(
|
||||||
&base,
|
&base,
|
||||||
"../test/slang-shaders/border/gameboy-player/gameboy-player-crt-royale.slangp",
|
"../test/slang-shaders/border/gameboy-player/gameboy-player-crt-royale.slangp",
|
||||||
None
|
None,
|
||||||
).unwrap();
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
crate::hello_triangle::main(base, filter)
|
crate::hello_triangle::main(base, filter)
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
use crate::filter_chain::Vulkan;
|
use crate::filter_chain::Vulkan;
|
||||||
|
use crate::texture::{Texture, VulkanImage};
|
||||||
use crate::vulkan_primitives::{VulkanBuffer, VulkanImageMemory};
|
use crate::vulkan_primitives::{VulkanBuffer, VulkanImageMemory};
|
||||||
use crate::{error, util};
|
use crate::{error, util};
|
||||||
use ash::vk;
|
use ash::vk;
|
||||||
use librashader_presets::TextureConfig;
|
use librashader_presets::TextureConfig;
|
||||||
use librashader_runtime::image::{Image, BGRA8};
|
use librashader_runtime::image::{Image, BGRA8};
|
||||||
use librashader_runtime::scaling::MipmapSize;
|
use librashader_runtime::scaling::MipmapSize;
|
||||||
use crate::texture::{Texture, VulkanImage};
|
|
||||||
|
|
||||||
pub struct LutTexture {
|
pub struct LutTexture {
|
||||||
pub memory: VulkanImageMemory,
|
pub memory: VulkanImageMemory,
|
||||||
pub staging: VulkanBuffer,
|
pub staging: VulkanBuffer,
|
||||||
pub image: Texture
|
pub image: Texture,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LutTexture {
|
impl LutTexture {
|
||||||
|
@ -238,12 +238,12 @@ impl LutTexture {
|
||||||
image: VulkanImage {
|
image: VulkanImage {
|
||||||
size: image.size,
|
size: image.size,
|
||||||
image: texture,
|
image: texture,
|
||||||
format: vk::Format::B8G8R8A8_UNORM
|
format: vk::Format::B8G8R8A8_UNORM,
|
||||||
},
|
},
|
||||||
filter_mode: config.filter_mode,
|
filter_mode: config.filter_mode,
|
||||||
wrap_mode: config.wrap_mode,
|
wrap_mode: config.wrap_mode,
|
||||||
mip_filter: config.filter_mode,
|
mip_filter: config.filter_mode,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,10 +50,7 @@ impl VulkanRenderPass {
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let rp = device.create_render_pass(&renderpass_info, None)?;
|
let rp = device.create_render_pass(&renderpass_info, None)?;
|
||||||
Ok(Self {
|
Ok(Self { handle: rp, format })
|
||||||
handle: rp,
|
|
||||||
format,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
|
use crate::framebuffer::OutputFramebuffer;
|
||||||
use ash::vk;
|
use ash::vk;
|
||||||
use crate::framebuffer::{OutputFramebuffer,};
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) struct RenderTarget<'a> {
|
pub(crate) struct RenderTarget<'a> {
|
||||||
pub mvp: &'a [f32; 16],
|
pub mvp: &'a [f32; 16],
|
||||||
pub output: OutputFramebuffer,
|
pub output: OutputFramebuffer,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,20 @@
|
||||||
use ash::vk;
|
|
||||||
use rustc_hash::FxHashMap;
|
|
||||||
use librashader_common::{FilterMode, WrapMode};
|
|
||||||
use crate::error;
|
use crate::error;
|
||||||
|
use ash::vk;
|
||||||
|
use librashader_common::{FilterMode, WrapMode};
|
||||||
|
use rustc_hash::FxHashMap;
|
||||||
|
|
||||||
pub struct VulkanSampler {
|
pub struct VulkanSampler {
|
||||||
pub handle: vk::Sampler,
|
pub handle: vk::Sampler,
|
||||||
device: ash::Device
|
device: ash::Device,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VulkanSampler {
|
impl VulkanSampler {
|
||||||
pub fn new(device: &ash::Device, wrap: WrapMode, filter: FilterMode, mipmap: FilterMode) -> error::Result<VulkanSampler> {
|
pub fn new(
|
||||||
|
device: &ash::Device,
|
||||||
|
wrap: WrapMode,
|
||||||
|
filter: FilterMode,
|
||||||
|
mipmap: FilterMode,
|
||||||
|
) -> error::Result<VulkanSampler> {
|
||||||
let create_info = vk::SamplerCreateInfo::builder()
|
let create_info = vk::SamplerCreateInfo::builder()
|
||||||
.mip_lod_bias(0.0)
|
.mip_lod_bias(0.0)
|
||||||
.max_anisotropy(1.0)
|
.max_anisotropy(1.0)
|
||||||
|
@ -26,13 +31,11 @@ impl VulkanSampler {
|
||||||
.address_mode_w(wrap.into())
|
.address_mode_w(wrap.into())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let sampler = unsafe {
|
let sampler = unsafe { device.create_sampler(&create_info, None)? };
|
||||||
device.create_sampler(&create_info, None)?
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(VulkanSampler {
|
Ok(VulkanSampler {
|
||||||
handle: sampler,
|
handle: sampler,
|
||||||
device: device.clone()
|
device: device.clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,7 +50,6 @@ impl Drop for VulkanSampler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub struct SamplerSet {
|
pub struct SamplerSet {
|
||||||
// todo: may need to deal with differences in mip filter.
|
// todo: may need to deal with differences in mip filter.
|
||||||
samplers: FxHashMap<(WrapMode, FilterMode, FilterMode), VulkanSampler>,
|
samplers: FxHashMap<(WrapMode, FilterMode, FilterMode), VulkanSampler>,
|
||||||
|
@ -79,11 +81,11 @@ impl SamplerSet {
|
||||||
|
|
||||||
samplers.insert(
|
samplers.insert(
|
||||||
(*wrap_mode, FilterMode::Nearest, FilterMode::Nearest),
|
(*wrap_mode, FilterMode::Nearest, FilterMode::Nearest),
|
||||||
VulkanSampler::new(device, *wrap_mode, FilterMode::Nearest, FilterMode::Nearest)?
|
VulkanSampler::new(device, *wrap_mode, FilterMode::Nearest, FilterMode::Nearest)?,
|
||||||
);
|
);
|
||||||
samplers.insert(
|
samplers.insert(
|
||||||
(*wrap_mode, FilterMode::Nearest, FilterMode::Linear),
|
(*wrap_mode, FilterMode::Nearest, FilterMode::Linear),
|
||||||
VulkanSampler::new(device, *wrap_mode, FilterMode::Nearest, FilterMode::Linear)?
|
VulkanSampler::new(device, *wrap_mode, FilterMode::Nearest, FilterMode::Linear)?,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
use ash::vk;
|
|
||||||
use ash::vk::{ImageAspectFlags, ImageLayout, ImageTiling, ImageType, ImageUsageFlags, ImageViewType, SampleCountFlags, SharingMode};
|
|
||||||
use librashader_common::{FilterMode, ImageFormat, Size, WrapMode};
|
|
||||||
use librashader_runtime::scaling::MipmapSize;
|
|
||||||
use crate::error;
|
use crate::error;
|
||||||
use crate::filter_chain::Vulkan;
|
use crate::filter_chain::Vulkan;
|
||||||
use crate::util::find_vulkan_memory_type;
|
use crate::util::find_vulkan_memory_type;
|
||||||
use crate::vulkan_primitives::VulkanImageMemory;
|
use crate::vulkan_primitives::VulkanImageMemory;
|
||||||
|
use ash::vk;
|
||||||
|
use ash::vk::{
|
||||||
|
ImageAspectFlags, ImageLayout, ImageTiling, ImageType, ImageUsageFlags, ImageViewType,
|
||||||
|
SampleCountFlags, SharingMode,
|
||||||
|
};
|
||||||
|
use librashader_common::{FilterMode, ImageFormat, Size, WrapMode};
|
||||||
|
use librashader_runtime::scaling::MipmapSize;
|
||||||
|
|
||||||
pub struct OwnedTexture {
|
pub struct OwnedTexture {
|
||||||
pub device: ash::Device,
|
pub device: ash::Device,
|
||||||
|
@ -16,16 +19,17 @@ pub struct OwnedTexture {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OwnedTexture {
|
impl OwnedTexture {
|
||||||
pub fn new(vulkan: &Vulkan, size: Size<u32>, format: ImageFormat, max_miplevels: u32)
|
pub fn new(
|
||||||
-> error::Result<OwnedTexture> {
|
vulkan: &Vulkan,
|
||||||
|
size: Size<u32>,
|
||||||
|
format: ImageFormat,
|
||||||
|
max_miplevels: u32,
|
||||||
|
) -> error::Result<OwnedTexture> {
|
||||||
let image_create_info = vk::ImageCreateInfo::builder()
|
let image_create_info = vk::ImageCreateInfo::builder()
|
||||||
.image_type(ImageType::TYPE_2D)
|
.image_type(ImageType::TYPE_2D)
|
||||||
.format(format.into())
|
.format(format.into())
|
||||||
.extent(size.into())
|
.extent(size.into())
|
||||||
.mip_levels(std::cmp::min(
|
.mip_levels(std::cmp::min(max_miplevels, size.calculate_miplevels()))
|
||||||
max_miplevels,
|
|
||||||
size.calculate_miplevels(),
|
|
||||||
))
|
|
||||||
.array_layers(1)
|
.array_layers(1)
|
||||||
.samples(SampleCountFlags::TYPE_1)
|
.samples(SampleCountFlags::TYPE_1)
|
||||||
.tiling(ImageTiling::OPTIMAL)
|
.tiling(ImageTiling::OPTIMAL)
|
||||||
|
@ -86,7 +90,7 @@ impl OwnedTexture {
|
||||||
image: VulkanImage {
|
image: VulkanImage {
|
||||||
image,
|
image,
|
||||||
size,
|
size,
|
||||||
format: format.into()
|
format: format.into(),
|
||||||
},
|
},
|
||||||
memory,
|
memory,
|
||||||
max_miplevels,
|
max_miplevels,
|
||||||
|
@ -109,7 +113,6 @@ impl OwnedTexture {
|
||||||
.a(vk::ComponentSwizzle::A)
|
.a(vk::ComponentSwizzle::A)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
|
||||||
let mut view_info = vk::ImageViewCreateInfo::builder()
|
let mut view_info = vk::ImageViewCreateInfo::builder()
|
||||||
.view_type(ImageViewType::TYPE_2D)
|
.view_type(ImageViewType::TYPE_2D)
|
||||||
.format(self.image.format)
|
.format(self.image.format)
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
|
use crate::error;
|
||||||
|
use crate::vulkan_primitives::VulkanBuffer;
|
||||||
use ash::vk;
|
use ash::vk;
|
||||||
use librashader_runtime::ringbuffer::{BoxRingBuffer, InlineRingBuffer, RingBuffer};
|
use librashader_runtime::ringbuffer::{BoxRingBuffer, InlineRingBuffer, RingBuffer};
|
||||||
use librashader_runtime::uniforms::UniformStorageAccess;
|
use librashader_runtime::uniforms::UniformStorageAccess;
|
||||||
use crate::error;
|
|
||||||
use crate::vulkan_primitives::VulkanBuffer;
|
|
||||||
|
|
||||||
pub struct VkUboRing {
|
pub struct VkUboRing {
|
||||||
ring: BoxRingBuffer<VulkanBuffer>,
|
ring: BoxRingBuffer<VulkanBuffer>,
|
||||||
|
@ -10,19 +10,34 @@ pub struct VkUboRing {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VkUboRing {
|
impl VkUboRing {
|
||||||
pub fn new(device: &ash::Device, mem_props: &vk::PhysicalDeviceMemoryProperties, ring_size: usize, buffer_size: usize) -> error::Result<Self> {
|
pub fn new(
|
||||||
|
device: &ash::Device,
|
||||||
|
mem_props: &vk::PhysicalDeviceMemoryProperties,
|
||||||
|
ring_size: usize,
|
||||||
|
buffer_size: usize,
|
||||||
|
) -> error::Result<Self> {
|
||||||
let mut ring = Vec::new();
|
let mut ring = Vec::new();
|
||||||
for _ in 0..ring_size {
|
for _ in 0..ring_size {
|
||||||
ring.push(VulkanBuffer::new(device, mem_props, vk::BufferUsageFlags::UNIFORM_BUFFER, buffer_size)?);
|
ring.push(VulkanBuffer::new(
|
||||||
|
device,
|
||||||
|
mem_props,
|
||||||
|
vk::BufferUsageFlags::UNIFORM_BUFFER,
|
||||||
|
buffer_size,
|
||||||
|
)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(VkUboRing {
|
Ok(VkUboRing {
|
||||||
ring: BoxRingBuffer::from_vec(ring),
|
ring: BoxRingBuffer::from_vec(ring),
|
||||||
device: device.clone()
|
device: device.clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bind_to_descriptor_set(&mut self, descriptor_set: vk::DescriptorSet, binding: u32, storage: &impl UniformStorageAccess) -> error::Result<()>{
|
pub fn bind_to_descriptor_set(
|
||||||
|
&mut self,
|
||||||
|
descriptor_set: vk::DescriptorSet,
|
||||||
|
binding: u32,
|
||||||
|
storage: &impl UniformStorageAccess,
|
||||||
|
) -> error::Result<()> {
|
||||||
let mut buffer = self.ring.current_mut();
|
let mut buffer = self.ring.current_mut();
|
||||||
// todo: write directly to allocated buffer.
|
// todo: write directly to allocated buffer.
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|
|
@ -124,8 +124,13 @@ impl Drop for VulkanBuffer {
|
||||||
|
|
||||||
impl<'a> VulkanBufferMapHandle<'a> {
|
impl<'a> VulkanBufferMapHandle<'a> {
|
||||||
pub unsafe fn copy_from(&mut self, offset: usize, src: &[u8]) {
|
pub unsafe fn copy_from(&mut self, offset: usize, src: &[u8]) {
|
||||||
std::ptr::copy_nonoverlapping(src.as_ptr(),
|
std::ptr::copy_nonoverlapping(
|
||||||
self.ptr.map_addr(|original| original.wrapping_add(offset)).cast(), src.len());
|
src.as_ptr(),
|
||||||
|
self.ptr
|
||||||
|
.map_addr(|original| original.wrapping_add(offset))
|
||||||
|
.cast(),
|
||||||
|
src.len(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,14 +31,12 @@ pub trait UniformStorageAccess {
|
||||||
/// This pointer must be valid for the lifetime of the implementing struct.
|
/// This pointer must be valid for the lifetime of the implementing struct.
|
||||||
fn push_pointer(&self) -> *const u8;
|
fn push_pointer(&self) -> *const u8;
|
||||||
|
|
||||||
|
|
||||||
/// Get a slice to the backing Push Constant buffer storage.
|
/// Get a slice to the backing Push Constant buffer storage.
|
||||||
/// This pointer must be valid for the lifetime of the implementing struct.
|
/// This pointer must be valid for the lifetime of the implementing struct.
|
||||||
fn push_slice(&self) -> &[u8];
|
fn push_slice(&self) -> &[u8];
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, H> UniformStorageAccess for UniformStorage<T, H> {
|
impl<T, H> UniformStorageAccess for UniformStorage<T, H> {
|
||||||
|
|
||||||
fn ubo_pointer(&self) -> *const u8 {
|
fn ubo_pointer(&self) -> *const u8 {
|
||||||
self.ubo.as_ptr()
|
self.ubo.as_ptr()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue