vk: make fbos
This commit is contained in:
parent
2baeae494d
commit
0c072dbc91
5 changed files with 361 additions and 15 deletions
|
@ -1,6 +1,7 @@
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use ash::vk;
|
use ash::vk;
|
||||||
|
use ash::vk::{PFN_vkGetInstanceProcAddr, PrimitiveTopology, PushConstantRange, StaticFn};
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use librashader_preprocess::ShaderSource;
|
use librashader_preprocess::ShaderSource;
|
||||||
use librashader_presets::{ShaderPassConfig, ShaderPreset, TextureConfig};
|
use librashader_presets::{ShaderPassConfig, ShaderPreset, TextureConfig};
|
||||||
|
@ -10,12 +11,14 @@ use librashader_reflect::front::shaderc::GlslangCompilation;
|
||||||
use librashader_reflect::reflect::ReflectShader;
|
use librashader_reflect::reflect::ReflectShader;
|
||||||
use librashader_reflect::reflect::semantics::{Semantic, ShaderSemantics, TextureSemantics, UniformBinding, UniformSemantic, UniqueSemantics};
|
use librashader_reflect::reflect::semantics::{Semantic, ShaderSemantics, TextureSemantics, UniformBinding, UniformSemantic, UniqueSemantics};
|
||||||
use librashader_runtime::uniforms::UniformStorage;
|
use librashader_runtime::uniforms::UniformStorage;
|
||||||
use crate::error;
|
use crate::{error, util};
|
||||||
use crate::filter_pass::{FilterPass, PipelineDescriptors};
|
use crate::filter_pass::{FilterPass, PipelineDescriptors, PipelineObjects};
|
||||||
|
use crate::framebuffer::Framebuffer;
|
||||||
|
|
||||||
pub struct Vulkan {
|
pub struct Vulkan {
|
||||||
physical_device: vk::PhysicalDevice,
|
physical_device: vk::PhysicalDevice,
|
||||||
device: vk::Device,
|
device: ash::Device,
|
||||||
|
instance: ash::Instance,
|
||||||
queue: vk::Queue,
|
queue: vk::Queue,
|
||||||
command_pool: vk::CommandPool,
|
command_pool: vk::CommandPool,
|
||||||
pipelines: vk::PipelineCache,
|
pipelines: vk::PipelineCache,
|
||||||
|
@ -34,8 +37,10 @@ type ShaderPassMeta = (
|
||||||
pub struct VulkanInfo<'a> {
|
pub struct VulkanInfo<'a> {
|
||||||
physical_device: &'a vk::PhysicalDevice,
|
physical_device: &'a vk::PhysicalDevice,
|
||||||
device: &'a vk::Device,
|
device: &'a vk::Device,
|
||||||
|
instance: &'a vk::Instance,
|
||||||
queue: &'a vk::Queue,
|
queue: &'a vk::Queue,
|
||||||
memory_properties: &'a vk::PhysicalDeviceMemoryProperties
|
memory_properties: &'a vk::PhysicalDeviceMemoryProperties,
|
||||||
|
get_instance_proc_addr: PFN_vkGetInstanceProcAddr
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct FilterChainVulkan {
|
pub struct FilterChainVulkan {
|
||||||
|
@ -76,6 +81,16 @@ impl FilterChainVulkan {
|
||||||
options: Option<&FilterChainOptionsVulkan>,
|
options: Option<&FilterChainOptionsVulkan>,
|
||||||
) -> error::Result<FilterChainVulkan> {
|
) -> error::Result<FilterChainVulkan> {
|
||||||
let (passes, semantics) = FilterChainVulkan::load_preset(preset.shaders, &preset.textures)?;
|
let (passes, semantics) = FilterChainVulkan::load_preset(preset.shaders, &preset.textures)?;
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let instance = ash::Instance::load(&StaticFn {
|
||||||
|
get_instance_proc_addr: vulkan.get_instance_proc_addr,
|
||||||
|
}, vulkan.instance.clone());
|
||||||
|
|
||||||
|
let device = ash::Device::load(instance.fp_v1_0(), vulkan.device.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
todo!();
|
todo!();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,6 +147,7 @@ impl FilterChainVulkan {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init_passes(
|
fn init_passes(
|
||||||
|
device: &ash::Device,
|
||||||
passes: Vec<ShaderPassMeta>,
|
passes: Vec<ShaderPassMeta>,
|
||||||
semantics: &ShaderSemantics,
|
semantics: &ShaderSemantics,
|
||||||
images: u32,
|
images: u32,
|
||||||
|
@ -143,6 +159,9 @@ impl FilterChainVulkan {
|
||||||
let reflection = reflect.reflect(index, semantics)?;
|
let reflection = reflect.reflect(index, semantics)?;
|
||||||
let spirv_words = reflect.compile(None)?;
|
let spirv_words = reflect.compile(None)?;
|
||||||
|
|
||||||
|
// todo: make framebuffers:
|
||||||
|
// shader_vulkan: 2280
|
||||||
|
|
||||||
let uniform_storage = UniformStorage::new(
|
let uniform_storage = UniformStorage::new(
|
||||||
reflection
|
reflection
|
||||||
.ubo
|
.ubo
|
||||||
|
@ -170,10 +189,25 @@ impl FilterChainVulkan {
|
||||||
uniform_bindings.insert(UniformBinding::TextureSize(*semantics), param.offset);
|
uniform_bindings.insert(UniformBinding::TextureSize(*semantics), param.offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut pipeline = PipelineDescriptors::new(images);
|
|
||||||
pipeline.add_ubo_binding(reflection.ubo.as_ref());
|
|
||||||
pipeline.add_texture_bindings(reflection.meta.texture_meta.values());
|
|
||||||
// shader_vulkan 1927 (pipeline_layout)
|
// shader_vulkan 1927 (pipeline_layout)
|
||||||
|
let pipeline_objects = PipelineObjects::new(&reflection, images, device)?;
|
||||||
|
|
||||||
|
let ia = vk::PipelineInputAssemblyStateCreateInfo::builder()
|
||||||
|
.topology(PrimitiveTopology::TRIANGLE_STRIP);
|
||||||
|
let vao_attrs = [vk::VertexInputAttributeDescription {
|
||||||
|
location: 0,
|
||||||
|
binding: 0,
|
||||||
|
format: vk::Format::R32G32_SFLOAT,
|
||||||
|
offset: 0,
|
||||||
|
}, vk::VertexInputAttributeDescription {
|
||||||
|
location: 1,
|
||||||
|
binding: 0,
|
||||||
|
format: vk::Format::R32G32_SFLOAT,
|
||||||
|
offset: (2 * std::mem::size_of::<f32>()) as u32,
|
||||||
|
}];
|
||||||
|
|
||||||
|
// shader_vulkan: 2026
|
||||||
|
|
||||||
filters.push(FilterPass {
|
filters.push(FilterPass {
|
||||||
compiled: spirv_words,
|
compiled: spirv_words,
|
||||||
uniform_storage,
|
uniform_storage,
|
||||||
|
|
|
@ -5,6 +5,8 @@ use librashader_reflect::back::ShaderCompilerOutput;
|
||||||
use librashader_reflect::reflect::semantics::{BindingStage, MemberOffset, TextureBinding, UboReflection, UniformBinding};
|
use librashader_reflect::reflect::semantics::{BindingStage, MemberOffset, TextureBinding, UboReflection, UniformBinding};
|
||||||
use librashader_runtime::uniforms::UniformStorage;
|
use librashader_runtime::uniforms::UniformStorage;
|
||||||
use ash::vk;
|
use ash::vk;
|
||||||
|
use librashader_reflect::reflect::ShaderReflection;
|
||||||
|
use crate::{error, util};
|
||||||
|
|
||||||
pub struct FilterPass {
|
pub struct FilterPass {
|
||||||
pub(crate) compiled: ShaderCompilerOutput<Vec<u32>>,
|
pub(crate) compiled: ShaderCompilerOutput<Vec<u32>>,
|
||||||
|
@ -31,13 +33,7 @@ impl PipelineDescriptors {
|
||||||
|
|
||||||
pub fn add_ubo_binding(&mut self, ubo_meta: Option<&UboReflection>) {
|
pub fn add_ubo_binding(&mut self, ubo_meta: Option<&UboReflection>) {
|
||||||
if let Some(ubo_meta) = ubo_meta && !ubo_meta.stage_mask.is_empty() {
|
if let Some(ubo_meta) = ubo_meta && !ubo_meta.stage_mask.is_empty() {
|
||||||
let mut ubo_mask = vk::ShaderStageFlags::default();
|
let mut ubo_mask = util::binding_stage_to_vulkan_stage(ubo_meta.stage_mask);
|
||||||
if ubo_meta.stage_mask.contains(BindingStage::VERTEX) {
|
|
||||||
ubo_mask |= vk::ShaderStageFlags::VERTEX;
|
|
||||||
}
|
|
||||||
if ubo_meta.stage_mask.contains(BindingStage::FRAGMENT) {
|
|
||||||
ubo_mask |= vk::ShaderStageFlags::FRAGMENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.layout_bindings.push(vk::DescriptorSetLayoutBinding {
|
self.layout_bindings.push(vk::DescriptorSetLayoutBinding {
|
||||||
binding: ubo_meta.binding,
|
binding: ubo_meta.binding,
|
||||||
|
@ -79,4 +75,80 @@ impl PipelineDescriptors {
|
||||||
pub fn bindings(&self) -> &[vk::DescriptorSetLayoutBinding] {
|
pub fn bindings(&self) -> &[vk::DescriptorSetLayoutBinding] {
|
||||||
self.layout_bindings.as_ref()
|
self.layout_bindings.as_ref()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
pub fn create_descriptor_set_layout(&self, device: &ash::Device) -> error::Result<vk::DescriptorSetLayout> {
|
||||||
|
unsafe {
|
||||||
|
let layout = device.create_descriptor_set_layout(
|
||||||
|
&vk::DescriptorSetLayoutCreateInfo::builder()
|
||||||
|
.bindings(self.bindings())
|
||||||
|
.build(),
|
||||||
|
None)?;
|
||||||
|
Ok(layout)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct PipelineObjects {
|
||||||
|
pub layout: vk::PipelineLayout,
|
||||||
|
pub pool: vk::DescriptorPool,
|
||||||
|
pub descriptor_sets: Vec<vk::DescriptorSet>,
|
||||||
|
pub descriptor_set_layout: [vk::DescriptorSetLayout;1],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PipelineObjects {
|
||||||
|
pub fn new(reflection: &ShaderReflection, replicas: u32, device: &ash::Device) -> error::Result<Self> {
|
||||||
|
let mut descriptors = PipelineDescriptors::new(replicas);
|
||||||
|
descriptors.add_ubo_binding(reflection.ubo.as_ref());
|
||||||
|
descriptors.add_texture_bindings(reflection.meta.texture_meta.values());
|
||||||
|
|
||||||
|
let mut descriptor_set_layout = [descriptors.create_descriptor_set_layout(device)?];
|
||||||
|
|
||||||
|
let mut pipeline_create_info = vk::PipelineLayoutCreateInfo::builder()
|
||||||
|
.set_layouts(&descriptor_set_layout);
|
||||||
|
|
||||||
|
let pipeline_create_info = if let Some(push_constant) = &reflection.push_constant {
|
||||||
|
let mut stage_mask = util::binding_stage_to_vulkan_stage(push_constant.stage_mask);
|
||||||
|
let push_constant_range = [
|
||||||
|
vk::PushConstantRange::builder()
|
||||||
|
.stage_flags(stage_mask)
|
||||||
|
.size(push_constant.size)
|
||||||
|
.build()
|
||||||
|
];
|
||||||
|
pipeline_create_info.push_constant_ranges(&push_constant_range).build()
|
||||||
|
} else {
|
||||||
|
pipeline_create_info.build()
|
||||||
|
};
|
||||||
|
|
||||||
|
let layout = unsafe {
|
||||||
|
device.create_pipeline_layout(&pipeline_create_info, None)?
|
||||||
|
};
|
||||||
|
|
||||||
|
let pool = unsafe {
|
||||||
|
device.create_descriptor_pool(&vk::DescriptorPoolCreateInfo::builder()
|
||||||
|
.max_sets(replicas)
|
||||||
|
.pool_sizes(&descriptors.pool_sizes)
|
||||||
|
.build(), None)?
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut descriptor_sets = Vec::new();
|
||||||
|
let alloc_info = vk::DescriptorSetAllocateInfo::builder()
|
||||||
|
.descriptor_pool(pool)
|
||||||
|
.set_layouts(&descriptor_set_layout)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
for _ in 0..replicas {
|
||||||
|
unsafe {
|
||||||
|
descriptor_sets.push(device.allocate_descriptor_sets(&alloc_info)?)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let descriptor_sets: Vec<vk::DescriptorSet> = descriptor_sets.into_iter().flatten().collect();
|
||||||
|
|
||||||
|
return Ok(PipelineObjects {
|
||||||
|
layout,
|
||||||
|
descriptor_set_layout,
|
||||||
|
descriptor_sets,
|
||||||
|
pool,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
208
librashader-runtime-vk/src/framebuffer.rs
Normal file
208
librashader-runtime-vk/src/framebuffer.rs
Normal file
|
@ -0,0 +1,208 @@
|
||||||
|
use ash::vk;
|
||||||
|
use ash::vk::{AttachmentLoadOp, AttachmentStoreOp, DeviceSize, Extent2D, Extent3D, ImageAspectFlags, ImageLayout, ImageTiling, ImageType, ImageUsageFlags, ImageViewType, PipelineBindPoint, SampleCountFlags, SharingMode};
|
||||||
|
use glfw::Key::P;
|
||||||
|
use librashader_common::{ImageFormat, Size};
|
||||||
|
use crate::error;
|
||||||
|
use crate::util::find_vulkan_memory_type;
|
||||||
|
|
||||||
|
pub struct Framebuffer {
|
||||||
|
device: ash::Device,
|
||||||
|
size: Size<u32>,
|
||||||
|
format: ImageFormat,
|
||||||
|
max_levels: u32,
|
||||||
|
mem_props: vk::PhysicalDeviceMemoryProperties,
|
||||||
|
render_pass: vk::RenderPass,
|
||||||
|
framebuffer: Option<VulkanFramebuffer>
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct VulkanFramebuffer {
|
||||||
|
pub device: ash::Device,
|
||||||
|
pub framebuffer: vk::Framebuffer,
|
||||||
|
pub image_view: vk::ImageView,
|
||||||
|
pub fb_view: vk::ImageView,
|
||||||
|
pub image: vk::Image,
|
||||||
|
pub memory: VulkanMemory,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct VulkanMemory {
|
||||||
|
pub handle: vk::DeviceMemory,
|
||||||
|
device: ash::Device
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VulkanMemory {
|
||||||
|
pub fn new(device: &ash::Device, alloc: &vk::MemoryAllocateInfo) -> error::Result<VulkanMemory> {
|
||||||
|
unsafe {
|
||||||
|
Ok(VulkanMemory {
|
||||||
|
handle: device.allocate_memory(alloc, None)?,
|
||||||
|
device: device.clone()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn bind(&self, image: &vk::Image) -> error::Result<()>{
|
||||||
|
unsafe {
|
||||||
|
Ok(self.device.bind_image_memory(image.clone(), self.handle.clone(), 0)?)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for VulkanMemory {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe {
|
||||||
|
self.device.free_memory(self.handle, None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for VulkanFramebuffer {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe {
|
||||||
|
if self.framebuffer != vk::Framebuffer::null() {
|
||||||
|
self.device.destroy_framebuffer(self.framebuffer, None);
|
||||||
|
}
|
||||||
|
if self.image_view != vk::ImageView::null() {
|
||||||
|
self.device.destroy_image_view(self.image_view, None);
|
||||||
|
}
|
||||||
|
if self.fb_view != vk::ImageView::null() {
|
||||||
|
self.device.destroy_image_view(self.fb_view, None);
|
||||||
|
}
|
||||||
|
if self.image != vk::Image::null() {
|
||||||
|
self.device.destroy_image(self.image, None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Framebuffer {
|
||||||
|
pub fn create_render_pass(device: &ash::Device, format: vk::Format) -> error::Result<vk::RenderPass> {
|
||||||
|
let attachment = vk::AttachmentDescription::builder()
|
||||||
|
.flags(vk::AttachmentDescriptionFlags::empty())
|
||||||
|
.format(format)
|
||||||
|
.samples(SampleCountFlags::TYPE_1)
|
||||||
|
.load_op(AttachmentLoadOp::DONT_CARE)
|
||||||
|
.store_op(AttachmentStoreOp::STORE)
|
||||||
|
.stencil_load_op(AttachmentLoadOp::DONT_CARE)
|
||||||
|
.stencil_store_op(AttachmentStoreOp::DONT_CARE)
|
||||||
|
.initial_layout(ImageLayout::COLOR_ATTACHMENT_OPTIMAL)
|
||||||
|
.final_layout(ImageLayout::COLOR_ATTACHMENT_OPTIMAL)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
let attachment_ref = vk::AttachmentReference::builder()
|
||||||
|
.attachment(0)
|
||||||
|
.layout(ImageLayout::COLOR_ATTACHMENT_OPTIMAL)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
let subpass = vk::SubpassDescription::builder()
|
||||||
|
.pipeline_bind_point(PipelineBindPoint::GRAPHICS)
|
||||||
|
.color_attachments(&[attachment_ref])
|
||||||
|
.build();
|
||||||
|
|
||||||
|
let renderpass_info = vk::RenderPassCreateInfo::builder()
|
||||||
|
.flags(vk::RenderPassCreateFlags::empty())
|
||||||
|
.attachments(&[attachment])
|
||||||
|
.subpasses(&[subpass])
|
||||||
|
.build();
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
Ok(device.create_render_pass(&renderpass_info, None)?)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(device: &ash::Device, size: Size<u32>, format: ImageFormat, mip_levels: u32, mem_props: vk::PhysicalDeviceMemoryProperties) -> error::Result<Self> {
|
||||||
|
let mut framebuffer = Framebuffer {
|
||||||
|
device: device.clone(),
|
||||||
|
size,
|
||||||
|
format,
|
||||||
|
max_levels: mip_levels,
|
||||||
|
mem_props,
|
||||||
|
render_pass: Framebuffer::create_render_pass(device, format.into())?,
|
||||||
|
framebuffer: None
|
||||||
|
};
|
||||||
|
|
||||||
|
let vulkan_image = framebuffer.create_vulkan_image()?;
|
||||||
|
framebuffer.framebuffer = Some(vulkan_image);
|
||||||
|
|
||||||
|
Ok(framebuffer)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_vulkan_image(&mut self) -> error::Result<VulkanFramebuffer> {
|
||||||
|
let image_create_info = vk::ImageCreateInfo::builder()
|
||||||
|
.image_type(ImageType::TYPE_2D)
|
||||||
|
.format(self.format.into())
|
||||||
|
.extent(Extent3D {
|
||||||
|
width: self.size.width,
|
||||||
|
height: self.size.height,
|
||||||
|
depth: 1
|
||||||
|
})
|
||||||
|
.mip_levels(std::cmp::min(self.max_levels, librashader_runtime::scaling::calc_miplevel(self.size)))
|
||||||
|
.array_layers(1)
|
||||||
|
.samples(SampleCountFlags::TYPE_1)
|
||||||
|
.tiling(ImageTiling::OPTIMAL)
|
||||||
|
.usage(ImageUsageFlags::SAMPLED | ImageUsageFlags::COLOR_ATTACHMENT | ImageUsageFlags::TRANSFER_DST | ImageUsageFlags::TRANSFER_SRC)
|
||||||
|
.sharing_mode(SharingMode::EXCLUSIVE)
|
||||||
|
.initial_layout(ImageLayout::UNDEFINED)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
let image = unsafe { self.device.create_image(&image_create_info, None)? };
|
||||||
|
let mem_reqs = unsafe { self.device.get_image_memory_requirements(image.clone()) };
|
||||||
|
|
||||||
|
let alloc_info = vk::MemoryAllocateInfo::builder()
|
||||||
|
.allocation_size(mem_reqs.size)
|
||||||
|
.memory_type_index(find_vulkan_memory_type(&self.mem_props, mem_reqs.memory_type_bits, vk::MemoryPropertyFlags::DEVICE_LOCAL))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// todo: optimize by reusing existing memory.
|
||||||
|
let memory = VulkanMemory::new(&self.device, &alloc_info)?;
|
||||||
|
memory.bind(&image)?;
|
||||||
|
|
||||||
|
let image_subresource = vk::ImageSubresourceRange::builder()
|
||||||
|
.base_mip_level(0)
|
||||||
|
.base_array_layer(0)
|
||||||
|
.level_count(image_create_info.mip_levels)
|
||||||
|
.layer_count(1)
|
||||||
|
.aspect_mask(ImageAspectFlags::COLOR)
|
||||||
|
.build();
|
||||||
|
let swizzle_components = vk::ComponentMapping::builder()
|
||||||
|
.r(vk::ComponentSwizzle::R)
|
||||||
|
.g(vk::ComponentSwizzle::G)
|
||||||
|
.b(vk::ComponentSwizzle::B)
|
||||||
|
.a(vk::ComponentSwizzle::A)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
let mut view_info = vk::ImageViewCreateInfo::builder()
|
||||||
|
.view_type(ImageViewType::TYPE_2D)
|
||||||
|
.format(self.format.into())
|
||||||
|
.image(image.clone())
|
||||||
|
.subresource_range(image_subresource)
|
||||||
|
.components(swizzle_components)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
let image_view = unsafe {
|
||||||
|
self.device.create_image_view(&view_info, None)?
|
||||||
|
};
|
||||||
|
|
||||||
|
view_info.subresource_range.level_count = 1;
|
||||||
|
let fb_view = unsafe {
|
||||||
|
self.device.create_image_view(&view_info, None)?
|
||||||
|
};
|
||||||
|
|
||||||
|
let framebuffer = unsafe {
|
||||||
|
self.device.create_framebuffer(&vk::FramebufferCreateInfo::builder()
|
||||||
|
.render_pass(self.render_pass)
|
||||||
|
.attachments(&[image_view])
|
||||||
|
.width(self.size.width)
|
||||||
|
.height(self.size.height)
|
||||||
|
.layers(1).build(), None)?
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(VulkanFramebuffer {
|
||||||
|
device: self.device.clone(),
|
||||||
|
framebuffer,
|
||||||
|
memory,
|
||||||
|
image_view,
|
||||||
|
fb_view,
|
||||||
|
image
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,6 +5,8 @@ mod hello_triangle;
|
||||||
mod filter_chain;
|
mod filter_chain;
|
||||||
mod filter_pass;
|
mod filter_pass;
|
||||||
mod error;
|
mod error;
|
||||||
|
mod util;
|
||||||
|
mod framebuffer;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
30
librashader-runtime-vk/src/util.rs
Normal file
30
librashader-runtime-vk/src/util.rs
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
use ash::vk;
|
||||||
|
use librashader_reflect::reflect::semantics::BindingStage;
|
||||||
|
|
||||||
|
pub fn binding_stage_to_vulkan_stage(stage_mask: BindingStage) -> vk::ShaderStageFlags {
|
||||||
|
let mut mask = vk::ShaderStageFlags::default();
|
||||||
|
if stage_mask.contains(BindingStage::VERTEX) {
|
||||||
|
mask |= vk::ShaderStageFlags::VERTEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
if stage_mask.contains(BindingStage::FRAGMENT) {
|
||||||
|
mask |= vk::ShaderStageFlags::FRAGMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
mask
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn find_vulkan_memory_type(props: &vk::PhysicalDeviceMemoryProperties, device_reqs: u32, host_reqs: vk::MemoryPropertyFlags) -> u32 {
|
||||||
|
for i in 0..vk::MAX_MEMORY_TYPES {
|
||||||
|
if device_reqs & (1 << i) != 0
|
||||||
|
&& props.memory_types[i].property_flags & host_reqs == host_reqs {
|
||||||
|
return i as u32
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if host_reqs == vk::MemoryPropertyFlags::empty() {
|
||||||
|
panic!("[vk] Failed to find valid memory type.")
|
||||||
|
} else {
|
||||||
|
find_vulkan_memory_type(props, device_reqs, vk::MemoryPropertyFlags::empty())
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue