vk: some work on texture binding
This commit is contained in:
parent
abd38b9076
commit
2038da787e
8 changed files with 563 additions and 113 deletions
|
@ -126,13 +126,18 @@ pub struct FilterChainVulkan {
|
||||||
// pub(crate) draw_quad: DrawQuad,
|
// pub(crate) draw_quad: DrawQuad,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct FilterMutable {
|
||||||
|
pub(crate) passes_enabled: usize,
|
||||||
|
pub(crate) parameters: FxHashMap<String, f32>,
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) struct FilterCommon {
|
pub(crate) struct FilterCommon {
|
||||||
pub(crate) luts: FxHashMap<usize, LutTexture>,
|
pub(crate) luts: FxHashMap<usize, LutTexture>,
|
||||||
pub samplers: SamplerSet,
|
pub samplers: SamplerSet,
|
||||||
// pub output_textures: Box<[Option<Texture>]>,
|
// pub output_textures: Box<[Option<Texture>]>,
|
||||||
// pub feedback_textures: Box<[Option<Texture>]>,
|
// pub feedback_textures: Box<[Option<Texture>]>,
|
||||||
// pub history_textures: Box<[Option<Texture>]>,
|
// pub history_textures: Box<[Option<Texture>]>,
|
||||||
// pub config: FilterMutable,
|
pub config: FilterMutable,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type FilterChainOptionsVulkan = ();
|
pub type FilterChainOptionsVulkan = ();
|
||||||
|
@ -164,7 +169,17 @@ impl FilterChainVulkan {
|
||||||
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 { luts, samplers },
|
common: FilterCommon { luts,
|
||||||
|
samplers,
|
||||||
|
config: FilterMutable {
|
||||||
|
passes_enabled: preset.shader_count as usize,
|
||||||
|
parameters: preset
|
||||||
|
.parameters
|
||||||
|
.into_iter()
|
||||||
|
.map(|param| (param.name, param.value))
|
||||||
|
.collect(),
|
||||||
|
},
|
||||||
|
},
|
||||||
passes: filters,
|
passes: filters,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -278,6 +293,8 @@ impl FilterChainVulkan {
|
||||||
|
|
||||||
// shader_vulkan: 2026
|
// shader_vulkan: 2026
|
||||||
filters.push(FilterPass {
|
filters.push(FilterPass {
|
||||||
|
device: vulkan.device.clone(),
|
||||||
|
reflection,
|
||||||
compiled: spirv_words,
|
compiled: spirv_words,
|
||||||
uniform_storage,
|
uniform_storage,
|
||||||
uniform_bindings,
|
uniform_bindings,
|
||||||
|
|
|
@ -1,12 +1,20 @@
|
||||||
|
use ash::vk;
|
||||||
use crate::vulkan_state::VulkanGraphicsPipeline;
|
use crate::vulkan_state::VulkanGraphicsPipeline;
|
||||||
use librashader_preprocess::ShaderSource;
|
use librashader_preprocess::ShaderSource;
|
||||||
use librashader_presets::ShaderPassConfig;
|
use librashader_presets::ShaderPassConfig;
|
||||||
use librashader_reflect::back::ShaderCompilerOutput;
|
use librashader_reflect::back::ShaderCompilerOutput;
|
||||||
use librashader_reflect::reflect::semantics::{MemberOffset, UniformBinding};
|
use librashader_reflect::reflect::semantics::{MemberOffset, TextureBinding, TextureSemantics, UniformBinding, UniqueSemantics};
|
||||||
use librashader_runtime::uniforms::UniformStorage;
|
use librashader_runtime::uniforms::UniformStorage;
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
|
use librashader_common::Size;
|
||||||
|
use librashader_reflect::reflect::ShaderReflection;
|
||||||
|
use crate::filter_chain::FilterCommon;
|
||||||
|
use crate::texture::Texture;
|
||||||
|
use crate::samplers::{SamplerSet, VulkanSampler};
|
||||||
|
|
||||||
pub struct FilterPass {
|
pub struct FilterPass {
|
||||||
|
pub device: ash::Device,
|
||||||
|
pub reflection: ShaderReflection,
|
||||||
pub(crate) compiled: ShaderCompilerOutput<Vec<u32>>,
|
pub(crate) compiled: ShaderCompilerOutput<Vec<u32>>,
|
||||||
pub(crate) uniform_storage: UniformStorage,
|
pub(crate) uniform_storage: UniformStorage,
|
||||||
pub uniform_bindings: FxHashMap<UniformBinding, MemberOffset>,
|
pub uniform_bindings: FxHashMap<UniformBinding, MemberOffset>,
|
||||||
|
@ -14,3 +22,298 @@ pub struct FilterPass {
|
||||||
pub config: ShaderPassConfig,
|
pub config: ShaderPassConfig,
|
||||||
pub graphics_pipeline: VulkanGraphicsPipeline,
|
pub graphics_pipeline: VulkanGraphicsPipeline,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl FilterPass {
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn bind_texture(device: &ash::Device,
|
||||||
|
samplers: &SamplerSet,
|
||||||
|
descriptor_set: vk::DescriptorSet,
|
||||||
|
binding: &TextureBinding,
|
||||||
|
texture: &Texture) {
|
||||||
|
let sampler = samplers.get(texture.wrap_mode, texture.filter_mode, texture.mip_filter);
|
||||||
|
let image_info = [vk::DescriptorImageInfo::builder()
|
||||||
|
.sampler(sampler.handle)
|
||||||
|
.image_view(texture.image_view)
|
||||||
|
.image_layout(vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL)
|
||||||
|
.build()];
|
||||||
|
|
||||||
|
let write_desc = [vk::WriteDescriptorSet::builder()
|
||||||
|
.dst_set(descriptor_set)
|
||||||
|
.dst_binding(binding.binding)
|
||||||
|
.dst_array_element(0)
|
||||||
|
.descriptor_type(vk::DescriptorType::COMBINED_IMAGE_SAMPLER)
|
||||||
|
.image_info(&image_info)
|
||||||
|
.build()];
|
||||||
|
unsafe {
|
||||||
|
device.update_descriptor_sets(&write_desc, &[]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_semantics(
|
||||||
|
&mut self,
|
||||||
|
pass_index: usize,
|
||||||
|
parent: &FilterCommon,
|
||||||
|
mvp: &[f32; 16],
|
||||||
|
frame_count: u32,
|
||||||
|
frame_direction: i32,
|
||||||
|
fb_size: Size<u32>,
|
||||||
|
viewport_size: Size<u32>,
|
||||||
|
descriptor_set: vk::DescriptorSet,
|
||||||
|
original: &Texture,
|
||||||
|
source: &Texture,
|
||||||
|
) {
|
||||||
|
if let Some(offset) = self.uniform_bindings.get(&UniqueSemantics::MVP.into()) {
|
||||||
|
self.uniform_storage.bind_mat4(*offset, mvp, None);
|
||||||
|
}
|
||||||
|
|
||||||
|
// bind OutputSize
|
||||||
|
if let Some(offset) = self.uniform_bindings.get(&UniqueSemantics::Output.into()) {
|
||||||
|
self.uniform_storage.bind_vec4(*offset, fb_size, None);
|
||||||
|
}
|
||||||
|
|
||||||
|
// bind FinalViewportSize
|
||||||
|
if let Some(offset) = self
|
||||||
|
.uniform_bindings
|
||||||
|
.get(&UniqueSemantics::FinalViewport.into())
|
||||||
|
{
|
||||||
|
self.uniform_storage.bind_vec4(*offset, viewport_size, None);
|
||||||
|
}
|
||||||
|
|
||||||
|
// bind FrameCount
|
||||||
|
if let Some(offset) = self
|
||||||
|
.uniform_bindings
|
||||||
|
.get(&UniqueSemantics::FrameCount.into())
|
||||||
|
{
|
||||||
|
self.uniform_storage.bind_scalar(*offset, frame_count, None);
|
||||||
|
}
|
||||||
|
|
||||||
|
// bind FrameDirection
|
||||||
|
if let Some(offset) = self
|
||||||
|
.uniform_bindings
|
||||||
|
.get(&UniqueSemantics::FrameDirection.into())
|
||||||
|
{
|
||||||
|
self.uniform_storage
|
||||||
|
.bind_scalar(*offset, frame_direction, None);
|
||||||
|
}
|
||||||
|
|
||||||
|
// bind Original sampler
|
||||||
|
if let Some(binding) = self
|
||||||
|
.reflection
|
||||||
|
.meta
|
||||||
|
.texture_meta
|
||||||
|
.get(&TextureSemantics::Original.semantics(0))
|
||||||
|
{
|
||||||
|
FilterPass::bind_texture(
|
||||||
|
&self.device,
|
||||||
|
&parent.samplers,
|
||||||
|
descriptor_set,
|
||||||
|
binding,
|
||||||
|
original,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// bind OriginalSize
|
||||||
|
if let Some(offset) = self
|
||||||
|
.uniform_bindings
|
||||||
|
.get(&TextureSemantics::Original.semantics(0).into())
|
||||||
|
{
|
||||||
|
self.uniform_storage
|
||||||
|
.bind_vec4(*offset, original.size, None);
|
||||||
|
}
|
||||||
|
|
||||||
|
// bind Source sampler
|
||||||
|
if let Some(binding) = self
|
||||||
|
.reflection
|
||||||
|
.meta
|
||||||
|
.texture_meta
|
||||||
|
.get(&TextureSemantics::Source.semantics(0))
|
||||||
|
{
|
||||||
|
// eprintln!("setting source binding to {}", binding.binding);
|
||||||
|
FilterPass::bind_texture(
|
||||||
|
&self.device,
|
||||||
|
&parent.samplers,
|
||||||
|
descriptor_set,
|
||||||
|
binding,
|
||||||
|
source
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// bind SourceSize
|
||||||
|
if let Some(offset) = self
|
||||||
|
.uniform_bindings
|
||||||
|
.get(&TextureSemantics::Source.semantics(0).into())
|
||||||
|
{
|
||||||
|
self.uniform_storage
|
||||||
|
.bind_vec4(*offset, source.size, None);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(binding) = self
|
||||||
|
.reflection
|
||||||
|
.meta
|
||||||
|
.texture_meta
|
||||||
|
.get(&TextureSemantics::OriginalHistory.semantics(0))
|
||||||
|
{
|
||||||
|
FilterPass::bind_texture(
|
||||||
|
&self.device,
|
||||||
|
&parent.samplers,
|
||||||
|
descriptor_set,
|
||||||
|
binding,
|
||||||
|
original,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(offset) = self
|
||||||
|
.uniform_bindings
|
||||||
|
.get(&TextureSemantics::OriginalHistory.semantics(0).into())
|
||||||
|
{
|
||||||
|
self.uniform_storage
|
||||||
|
.bind_vec4(*offset, original.size, None);
|
||||||
|
}
|
||||||
|
|
||||||
|
// for (index, output) in parent.history_textures.iter().enumerate() {
|
||||||
|
// let Some(output) = output else {
|
||||||
|
// eprintln!("no history");
|
||||||
|
// continue;
|
||||||
|
// };
|
||||||
|
// if let Some(binding) = self
|
||||||
|
// .reflection
|
||||||
|
// .meta
|
||||||
|
// .texture_meta
|
||||||
|
// .get(&TextureSemantics::OriginalHistory.semantics(index + 1))
|
||||||
|
// {
|
||||||
|
// FilterPass::bind_texture(
|
||||||
|
// &self.device,
|
||||||
|
// &parent.samplers,
|
||||||
|
// descriptor_set,
|
||||||
|
// binding,
|
||||||
|
// output,
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if let Some(offset) = self.uniform_bindings.get(
|
||||||
|
// &TextureSemantics::OriginalHistory
|
||||||
|
// .semantics(index + 1)
|
||||||
|
// .into(),
|
||||||
|
// ) {
|
||||||
|
// self.uniform_storage
|
||||||
|
// .bind_vec4(*offset, output.size, None);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// PassOutput
|
||||||
|
// for (index, output) in parent.output_textures[0..pass_index].iter().enumerate() {
|
||||||
|
// let Some(output) = output else {
|
||||||
|
// eprintln!("no passoutput {index}");
|
||||||
|
//
|
||||||
|
// continue;
|
||||||
|
// };
|
||||||
|
// if let Some(binding) = self
|
||||||
|
// .reflection
|
||||||
|
// .meta
|
||||||
|
// .texture_meta
|
||||||
|
// .get(&TextureSemantics::PassOutput.semantics(index))
|
||||||
|
// {
|
||||||
|
// FilterPass::bind_texture(
|
||||||
|
// &self.device,
|
||||||
|
// &parent.samplers,
|
||||||
|
// descriptor_set,
|
||||||
|
// binding,
|
||||||
|
// output,
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if let Some(offset) = self
|
||||||
|
// .uniform_bindings
|
||||||
|
// .get(&TextureSemantics::PassOutput.semantics(index).into())
|
||||||
|
// {
|
||||||
|
// self.uniform_storage
|
||||||
|
// .bind_vec4(*offset, output.view.size, None);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // PassFeedback
|
||||||
|
// for (index, feedback) in parent.feedback_textures.iter().enumerate() {
|
||||||
|
// let Some(feedback) = feedback else {
|
||||||
|
// eprintln!("no passfeedback {index}");
|
||||||
|
// continue;
|
||||||
|
// };
|
||||||
|
// if let Some(binding) = self
|
||||||
|
// .reflection
|
||||||
|
// .meta
|
||||||
|
// .texture_meta
|
||||||
|
// .get(&TextureSemantics::PassFeedback.semantics(index))
|
||||||
|
// {
|
||||||
|
// FilterPass::bind_texture(
|
||||||
|
// &parent.samplers,
|
||||||
|
// &mut textures,
|
||||||
|
// &mut samplers,
|
||||||
|
// binding,
|
||||||
|
// feedback,
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if let Some(offset) = self
|
||||||
|
// .uniform_bindings
|
||||||
|
// .get(&TextureSemantics::PassFeedback.semantics(index).into())
|
||||||
|
// {
|
||||||
|
// self.uniform_storage
|
||||||
|
// .bind_vec4(*offset, feedback.view.size, None);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// bind float parameters
|
||||||
|
for (id, offset) in
|
||||||
|
self.uniform_bindings
|
||||||
|
.iter()
|
||||||
|
.filter_map(|(binding, value)| match binding {
|
||||||
|
UniformBinding::Parameter(id) => Some((id, value)),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
{
|
||||||
|
let id = id.as_str();
|
||||||
|
|
||||||
|
let default = self
|
||||||
|
.source
|
||||||
|
.parameters
|
||||||
|
.iter()
|
||||||
|
.find(|&p| p.id == id)
|
||||||
|
.map(|f| f.initial)
|
||||||
|
.unwrap_or(0f32);
|
||||||
|
|
||||||
|
let value = *parent.config.parameters.get(id).unwrap_or(&default);
|
||||||
|
|
||||||
|
self.uniform_storage.bind_scalar(*offset, value, None);
|
||||||
|
}
|
||||||
|
|
||||||
|
// bind luts
|
||||||
|
for (index, lut) in &parent.luts {
|
||||||
|
if let Some(binding) = self
|
||||||
|
.reflection
|
||||||
|
.meta
|
||||||
|
.texture_meta
|
||||||
|
.get(&TextureSemantics::User.semantics(*index))
|
||||||
|
{
|
||||||
|
FilterPass::bind_texture(
|
||||||
|
&self.device,
|
||||||
|
&parent.samplers,
|
||||||
|
descriptor_set,
|
||||||
|
binding,
|
||||||
|
&lut.image,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(offset) = self
|
||||||
|
.uniform_bindings
|
||||||
|
.get(&TextureSemantics::User.semantics(*index).into())
|
||||||
|
{
|
||||||
|
self.uniform_storage
|
||||||
|
.bind_vec4(*offset, lut.image.size, None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// (textures, samplers)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,31 +1,17 @@
|
||||||
use crate::error;
|
use crate::error;
|
||||||
use crate::renderpass::VulkanRenderPass;
|
use crate::renderpass::VulkanRenderPass;
|
||||||
use crate::util::find_vulkan_memory_type;
|
|
||||||
use crate::vulkan_primitives::VulkanImageMemory;
|
|
||||||
use ash::vk;
|
use ash::vk;
|
||||||
use ash::vk::{
|
use ash::vk::{
|
||||||
Extent3D, ImageAspectFlags, ImageLayout, ImageTiling, ImageType, ImageUsageFlags,
|
ImageAspectFlags,
|
||||||
ImageViewType, SampleCountFlags, SharingMode,
|
ImageViewType,
|
||||||
};
|
};
|
||||||
use librashader_common::Size;
|
use librashader_common::Size;
|
||||||
use librashader_runtime::scaling::MipmapSize;
|
use crate::filter_chain::Vulkan;
|
||||||
|
use crate::texture::OwnedTexture;
|
||||||
pub struct Framebuffer {
|
|
||||||
device: ash::Device,
|
|
||||||
size: Size<u32>,
|
|
||||||
max_levels: u32,
|
|
||||||
mem_props: vk::PhysicalDeviceMemoryProperties,
|
|
||||||
render_pass: VulkanRenderPass,
|
|
||||||
framebuffer: Option<VulkanFramebuffer>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct VulkanFramebuffer {
|
pub struct VulkanFramebuffer {
|
||||||
pub device: ash::Device,
|
pub device: ash::Device,
|
||||||
pub framebuffer: vk::Framebuffer,
|
pub framebuffer: vk::Framebuffer,
|
||||||
pub image_view: vk::ImageView,
|
|
||||||
pub fb_view: vk::ImageView,
|
|
||||||
pub image: vk::Image,
|
|
||||||
pub memory: VulkanImageMemory,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for VulkanFramebuffer {
|
impl Drop for VulkanFramebuffer {
|
||||||
|
@ -34,87 +20,72 @@ impl Drop for VulkanFramebuffer {
|
||||||
if self.framebuffer != vk::Framebuffer::null() {
|
if self.framebuffer != vk::Framebuffer::null() {
|
||||||
self.device.destroy_framebuffer(self.framebuffer, None);
|
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 struct OwnedFramebuffer {
|
||||||
|
pub size: Size<u32>,
|
||||||
|
pub image: OwnedTexture,
|
||||||
|
pub render_pass: VulkanRenderPass,
|
||||||
|
pub framebuffer: VulkanFramebuffer,
|
||||||
|
pub view: vk::ImageView,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OwnedFramebuffer {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
device: &ash::Device,
|
vulkan: &Vulkan,
|
||||||
size: Size<u32>,
|
size: Size<u32>,
|
||||||
render_pass: VulkanRenderPass,
|
render_pass: VulkanRenderPass,
|
||||||
mip_levels: u32,
|
max_miplevels: u32,
|
||||||
mem_props: vk::PhysicalDeviceMemoryProperties,
|
|
||||||
) -> error::Result<Self> {
|
) -> error::Result<Self> {
|
||||||
let mut framebuffer = Framebuffer {
|
let image = OwnedTexture::new(vulkan, size, render_pass.format, max_miplevels)?;
|
||||||
device: device.clone(),
|
let fb_view = image.create_texture_view()?;
|
||||||
size,
|
let framebuffer = unsafe {
|
||||||
max_levels: mip_levels,
|
vulkan.device.create_framebuffer(
|
||||||
mem_props,
|
&vk::FramebufferCreateInfo::builder()
|
||||||
render_pass,
|
.render_pass(render_pass.handle)
|
||||||
framebuffer: None,
|
.attachments(&[image.image_view])
|
||||||
|
.width(image.size.width)
|
||||||
|
.height(image.size.height)
|
||||||
|
.layers(1)
|
||||||
|
.build(),
|
||||||
|
None,
|
||||||
|
)?
|
||||||
};
|
};
|
||||||
|
|
||||||
let vulkan_image = framebuffer.create_vulkan_image()?;
|
Ok(OwnedFramebuffer {
|
||||||
framebuffer.framebuffer = Some(vulkan_image);
|
size,
|
||||||
|
image,
|
||||||
Ok(framebuffer)
|
view: fb_view,
|
||||||
|
render_pass,
|
||||||
|
framebuffer: VulkanFramebuffer {
|
||||||
|
device: vulkan.device.clone(),
|
||||||
|
framebuffer,
|
||||||
|
},
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn create_vulkan_image(&mut self) -> error::Result<VulkanFramebuffer> {
|
pub struct OutputFramebuffer<'a> {
|
||||||
let image_create_info = vk::ImageCreateInfo::builder()
|
device: ash::Device,
|
||||||
.image_type(ImageType::TYPE_2D)
|
render_pass: &'a VulkanRenderPass,
|
||||||
.format(self.render_pass.format.into())
|
pub handle: vk::Framebuffer,
|
||||||
.extent(self.size.into())
|
pub size: Size<u32>,
|
||||||
.mip_levels(std::cmp::min(
|
pub image: vk::Image,
|
||||||
self.max_levels,
|
pub image_view: vk::ImageView,
|
||||||
self.size.calculate_miplevels(),
|
}
|
||||||
))
|
|
||||||
.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 = VulkanImageMemory::new(&self.device, &alloc_info)?;
|
|
||||||
memory.bind(&image)?;
|
|
||||||
|
|
||||||
|
impl<'a> OutputFramebuffer<'a> {
|
||||||
|
pub fn new(vulkan: &Vulkan, render_pass: &'a VulkanRenderPass, image: vk::Image, size: Size<u32>) -> error::Result<OutputFramebuffer<'a>> {
|
||||||
let image_subresource = vk::ImageSubresourceRange::builder()
|
let image_subresource = vk::ImageSubresourceRange::builder()
|
||||||
.base_mip_level(0)
|
.base_mip_level(0)
|
||||||
.base_array_layer(0)
|
.base_array_layer(0)
|
||||||
.level_count(image_create_info.mip_levels)
|
.level_count(1)
|
||||||
.layer_count(1)
|
.layer_count(1)
|
||||||
.aspect_mask(ImageAspectFlags::COLOR)
|
.aspect_mask(ImageAspectFlags::COLOR)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let swizzle_components = vk::ComponentMapping::builder()
|
let swizzle_components = vk::ComponentMapping::builder()
|
||||||
.r(vk::ComponentSwizzle::R)
|
.r(vk::ComponentSwizzle::R)
|
||||||
.g(vk::ComponentSwizzle::G)
|
.g(vk::ComponentSwizzle::G)
|
||||||
|
@ -124,37 +95,47 @@ impl Framebuffer {
|
||||||
|
|
||||||
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.render_pass.format.into())
|
.format(render_pass.format.into())
|
||||||
.image(image.clone())
|
.image(image.clone())
|
||||||
.subresource_range(image_subresource)
|
.subresource_range(image_subresource)
|
||||||
.components(swizzle_components)
|
.components(swizzle_components)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let image_view = unsafe { self.device.create_image_view(&view_info, None)? };
|
let image_view = unsafe { vulkan.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 {
|
let framebuffer = unsafe {
|
||||||
self.device.create_framebuffer(
|
vulkan.device.create_framebuffer(
|
||||||
&vk::FramebufferCreateInfo::builder()
|
&vk::FramebufferCreateInfo::builder()
|
||||||
.render_pass(self.render_pass.render_pass)
|
.render_pass(render_pass.handle)
|
||||||
.attachments(&[image_view])
|
.attachments(&[image_view])
|
||||||
.width(self.size.width)
|
.width(size.width)
|
||||||
.height(self.size.height)
|
.height(size.height)
|
||||||
.layers(1)
|
.layers(1)
|
||||||
.build(),
|
.build(),
|
||||||
None,
|
None,
|
||||||
)?
|
)?
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(VulkanFramebuffer {
|
Ok(OutputFramebuffer {
|
||||||
device: self.device.clone(),
|
device: vulkan.device.clone(),
|
||||||
framebuffer,
|
|
||||||
memory,
|
|
||||||
image_view,
|
|
||||||
fb_view,
|
|
||||||
image,
|
image,
|
||||||
|
image_view,
|
||||||
|
render_pass,
|
||||||
|
size,
|
||||||
|
handle: framebuffer,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_renderpass_begin_info(&self, area: vk::Rect2D, clear: Option<&[vk::ClearValue]>) -> vk::RenderPassBeginInfo {
|
||||||
|
let mut builder = vk::RenderPassBeginInfo::builder()
|
||||||
|
.render_pass(self.render_pass.handle)
|
||||||
|
.framebuffer(self.handle)
|
||||||
|
.render_area(area);
|
||||||
|
|
||||||
|
if let Some(clear) = clear {
|
||||||
|
builder = builder.clear_values(clear)
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.build()
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -13,6 +13,7 @@ mod util;
|
||||||
mod vulkan_primitives;
|
mod vulkan_primitives;
|
||||||
mod vulkan_state;
|
mod vulkan_state;
|
||||||
mod samplers;
|
mod samplers;
|
||||||
|
mod texture;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
|
@ -8,15 +8,12 @@ use librashader_common::{FilterMode, WrapMode};
|
||||||
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;
|
||||||
|
|
||||||
pub struct LutTexture {
|
pub struct LutTexture {
|
||||||
pub texture: vk::Image,
|
|
||||||
pub texture_view: vk::ImageView,
|
|
||||||
pub memory: VulkanImageMemory,
|
pub memory: VulkanImageMemory,
|
||||||
pub staging: VulkanBuffer,
|
pub staging: VulkanBuffer,
|
||||||
pub filter_mode: FilterMode,
|
pub image: Texture
|
||||||
pub wrap_mode: WrapMode,
|
|
||||||
pub mipmap: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LutTexture {
|
impl LutTexture {
|
||||||
|
@ -237,13 +234,17 @@ impl LutTexture {
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(LutTexture {
|
Ok(LutTexture {
|
||||||
texture,
|
|
||||||
texture_view,
|
|
||||||
memory,
|
memory,
|
||||||
staging,
|
staging,
|
||||||
|
image: Texture {
|
||||||
|
size: image.size,
|
||||||
|
image_view: texture_view,
|
||||||
|
image: texture,
|
||||||
filter_mode: config.filter_mode,
|
filter_mode: config.filter_mode,
|
||||||
wrap_mode: config.wrap_mode,
|
wrap_mode: config.wrap_mode,
|
||||||
mipmap: config.mipmap,
|
mip_filter: config.filter_mode,
|
||||||
|
format: vk::Format::B8G8R8A8_UNORM
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ use ash::vk::{
|
||||||
use librashader_common::ImageFormat;
|
use librashader_common::ImageFormat;
|
||||||
|
|
||||||
pub struct VulkanRenderPass {
|
pub struct VulkanRenderPass {
|
||||||
pub render_pass: vk::RenderPass,
|
pub handle: vk::RenderPass,
|
||||||
pub format: ImageFormat,
|
pub format: ImageFormat,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,7 +51,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 {
|
||||||
render_pass: rp,
|
handle: rp,
|
||||||
format,
|
format,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
147
librashader-runtime-vk/src/texture.rs
Normal file
147
librashader-runtime-vk/src/texture.rs
Normal file
|
@ -0,0 +1,147 @@
|
||||||
|
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::filter_chain::Vulkan;
|
||||||
|
use crate::util::find_vulkan_memory_type;
|
||||||
|
use crate::vulkan_primitives::VulkanImageMemory;
|
||||||
|
|
||||||
|
pub struct OwnedTexture {
|
||||||
|
pub device: ash::Device,
|
||||||
|
pub image_view: vk::ImageView,
|
||||||
|
pub image: vk::Image,
|
||||||
|
pub format: vk::Format,
|
||||||
|
pub memory: VulkanImageMemory,
|
||||||
|
pub size: Size<u32>,
|
||||||
|
pub max_miplevels: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OwnedTexture {
|
||||||
|
pub fn new(vulkan: &Vulkan, size: Size<u32>, format: ImageFormat, max_miplevels: u32)
|
||||||
|
-> error::Result<OwnedTexture> {
|
||||||
|
let image_create_info = vk::ImageCreateInfo::builder()
|
||||||
|
.image_type(ImageType::TYPE_2D)
|
||||||
|
.format(format.into())
|
||||||
|
.extent(size.into())
|
||||||
|
.mip_levels(std::cmp::min(
|
||||||
|
max_miplevels,
|
||||||
|
size.calculate_miplevels(),
|
||||||
|
))
|
||||||
|
.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 { vulkan.device.create_image(&image_create_info, None)? };
|
||||||
|
let mem_reqs = unsafe { vulkan.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(
|
||||||
|
&vulkan.memory_properties,
|
||||||
|
mem_reqs.memory_type_bits,
|
||||||
|
vk::MemoryPropertyFlags::DEVICE_LOCAL,
|
||||||
|
))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// todo: optimize by reusing existing memory.
|
||||||
|
let memory = VulkanImageMemory::new(&vulkan.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(format.into())
|
||||||
|
.image(image.clone())
|
||||||
|
.subresource_range(image_subresource)
|
||||||
|
.components(swizzle_components)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
let image_view = unsafe { vulkan.device.create_image_view(&view_info, None)? };
|
||||||
|
|
||||||
|
Ok(OwnedTexture {
|
||||||
|
device: vulkan.device.clone(),
|
||||||
|
image_view,
|
||||||
|
image,
|
||||||
|
size,
|
||||||
|
format: format.into(),
|
||||||
|
memory,
|
||||||
|
max_miplevels,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_texture_view(&self) -> error::Result<vk::ImageView> {
|
||||||
|
let image_subresource = vk::ImageSubresourceRange::builder()
|
||||||
|
.base_mip_level(0)
|
||||||
|
.base_array_layer(0)
|
||||||
|
.level_count(1)
|
||||||
|
.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)
|
||||||
|
.image(self.image.clone())
|
||||||
|
.subresource_range(image_subresource)
|
||||||
|
.components(swizzle_components)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
let image_view = unsafe { self.device.create_image_view(&view_info, None)? };
|
||||||
|
Ok(image_view)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for OwnedTexture {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe {
|
||||||
|
if self.image_view != vk::ImageView::null() {
|
||||||
|
self.device.destroy_image_view(self.image_view, None);
|
||||||
|
}
|
||||||
|
if self.image != vk::Image::null() {
|
||||||
|
self.device.destroy_image(self.image, None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Texture {
|
||||||
|
pub size: Size<u32>,
|
||||||
|
pub image_view: vk::ImageView,
|
||||||
|
pub image: vk::Image,
|
||||||
|
pub format: vk::Format,
|
||||||
|
pub wrap_mode: WrapMode,
|
||||||
|
pub filter_mode: FilterMode,
|
||||||
|
pub mip_filter: FilterMode,
|
||||||
|
}
|
|
@ -302,7 +302,7 @@ impl VulkanGraphicsPipeline {
|
||||||
.viewport_state(&viewport_state)
|
.viewport_state(&viewport_state)
|
||||||
.depth_stencil_state(&depth_stencil_state)
|
.depth_stencil_state(&depth_stencil_state)
|
||||||
.dynamic_state(&dynamic_state)
|
.dynamic_state(&dynamic_state)
|
||||||
.render_pass(render_pass.render_pass.clone())
|
.render_pass(render_pass.handle.clone())
|
||||||
.layout(pipeline_layout.layout)
|
.layout(pipeline_layout.layout)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue